| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 	"net/http/httptest" | 
					
						
							|  |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-16 02:13:30 +08:00
										 |  |  | 	prometheus "github.com/prometheus/alertmanager/config" | 
					
						
							| 
									
										
										
										
											2023-07-25 05:56:53 +08:00
										 |  |  | 	"github.com/prometheus/alertmanager/pkg/labels" | 
					
						
							| 
									
										
										
										
											2022-07-16 02:13:30 +08:00
										 |  |  | 	"github.com/prometheus/alertmanager/timeinterval" | 
					
						
							| 
									
										
										
										
											2022-08-12 06:58:02 +08:00
										 |  |  | 	"github.com/prometheus/common/model" | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 	"github.com/stretchr/testify/mock" | 
					
						
							| 
									
										
										
										
											2022-07-16 02:13:30 +08:00
										 |  |  | 	"github.com/stretchr/testify/require" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/components/simplejson" | 
					
						
							| 
									
										
										
										
											2022-10-19 21:02:15 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/db" | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/log" | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/infra/log/logtest" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/accesscontrol" | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | 	contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/dashboards" | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/models" | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/notifier" | 
					
						
							| 
									
										
										
										
											2022-04-28 04:15:41 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/provisioning" | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/ngalert/store" | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/secrets" | 
					
						
							|  |  |  | 	secrets_fakes "github.com/grafana/grafana/pkg/services/secrets/fakes" | 
					
						
							| 
									
										
										
										
											2022-08-10 17:56:48 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/user" | 
					
						
							| 
									
										
										
										
											2022-07-16 02:13:30 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/setting" | 
					
						
							| 
									
										
										
										
											2023-09-09 03:09:35 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/util" | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/web" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestProvisioningApi(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	t.Run("policies", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("successful GET returns 200", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetPolicyTree(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("successful PUT returns 202", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 			tree := definitions.Route{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RoutePutPolicyTree(&rc, tree) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 202, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-09 05:23:18 +08:00
										 |  |  | 		t.Run("successful DELETE returns 202", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteResetPolicyTree(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 202, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		t.Run("when new policy tree is invalid", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("PUT returns 400", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				sut.policies = &fakeRejectingNotificationPolicyService{} | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				tree := definitions.Route{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RoutePutPolicyTree(&rc, tree) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							| 
									
										
										
										
											2023-10-31 02:06:26 +08:00
										 |  |  | 				expBody := `{"message":"invalid object specification: invalid policy tree"}` | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				require.Equal(t, expBody, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("when org has no AM config", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("GET returns 404", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							| 
									
										
										
										
											2022-08-11 19:28:55 +08:00
										 |  |  | 				rc.SignedInUser.OrgID = 2 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTree(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 404, response.Status()) | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 			t.Run("POST returns 404", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							| 
									
										
										
										
											2022-08-11 19:28:55 +08:00
										 |  |  | 				rc.SignedInUser.OrgID = 2 | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				response := sut.RouteGetPolicyTree(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 404, response.Status()) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-22 16:43:38 +08:00
										 |  |  | 		t.Run("when an unspecified error occurs", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 			t.Run("GET returns 500", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				sut.policies = &fakeFailingNotificationPolicyService{} | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTree(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 500, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "something went wrong") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("PUT returns 500", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				sut.policies = &fakeFailingNotificationPolicyService{} | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				tree := definitions.Route{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RoutePutPolicyTree(&rc, tree) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 500, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "something went wrong") | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2022-07-09 05:23:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("DELETE returns 500", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				sut.policies = &fakeFailingNotificationPolicyService{} | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteResetPolicyTree(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 500, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "something went wrong") | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	t.Run("contact points", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("are invalid", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("POST returns 400", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				cp := createInvalidContactPoint() | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				response := sut.RoutePostContactPoint(&rc, cp) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "recipient must be specified") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("PUT returns 400", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				cp := createInvalidContactPoint() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-24 04:13:39 +08:00
										 |  |  | 				response := sut.RoutePutContactPoint(&rc, cp, "email-uid") | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "recipient must be specified") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-06-24 04:13:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("are missing, PUT returns 404", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 			cp := createInvalidContactPoint() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RoutePutContactPoint(&rc, cp, "does not exist") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 404, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	t.Run("templates", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("are invalid", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("PUT returns 400", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							| 
									
										
										
										
											2023-01-19 01:26:34 +08:00
										 |  |  | 				tmpl := definitions.NotificationTemplateContent{Template: ""} | 
					
						
							| 
									
										
										
										
											2022-04-28 04:15:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-24 04:13:39 +08:00
										 |  |  | 				response := sut.RoutePutTemplate(&rc, tmpl, "test") | 
					
						
							| 
									
										
										
										
											2022-04-28 04:15:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "template must have content") | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2022-04-28 04:15:41 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	t.Run("mute timings", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("are invalid", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("POST returns 400", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				mti := createInvalidMuteTiming() | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				response := sut.RoutePostMuteTiming(&rc, mti) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "invalid") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("PUT returns 400", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				mti := createInvalidMuteTiming() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-24 04:13:39 +08:00
										 |  |  | 				response := sut.RoutePutMuteTiming(&rc, mti, "interval") | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "invalid") | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		t.Run("are missing, PUT returns 404", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 			rc := createTestRequestCtx() | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 			mti := definitions.MuteTimeInterval{} | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-24 04:13:39 +08:00
										 |  |  | 			response := sut.RoutePutMuteTiming(&rc, mti, "does not exist") | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 404, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	t.Run("alert rules", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("are invalid", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-11-12 02:58:45 +08:00
										 |  |  | 			t.Run("POST returns 400 on wrong body params", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				rule := createInvalidAlertRule() | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				response := sut.RoutePostAlertRule(&rc, rule) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "invalid alert rule") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-12 02:58:45 +08:00
										 |  |  | 			t.Run("PUT returns 400 on wrong body params", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							| 
									
										
										
										
											2022-08-12 06:58:02 +08:00
										 |  |  | 				uid := "123123" | 
					
						
							|  |  |  | 				rule := createTestAlertRule("rule", 1) | 
					
						
							|  |  |  | 				rule.UID = uid | 
					
						
							|  |  |  | 				insertRule(t, sut, rule) | 
					
						
							|  |  |  | 				rule = createInvalidAlertRule() | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-12 06:58:02 +08:00
										 |  |  | 				response := sut.RoutePutAlertRule(&rc, rule, uid) | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "invalid alert rule") | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 		t.Run("exist in non-default orgs", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-11-12 02:58:45 +08:00
										 |  |  | 			t.Run("POST sets expected fields with no provenance", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							| 
									
										
										
										
											2022-11-12 02:58:45 +08:00
										 |  |  | 				rc.Req.Header = map[string][]string{"X-Disable-Provenance": {"true"}} | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 				rc.OrgID = 3 | 
					
						
							|  |  |  | 				rule := createTestAlertRule("rule", 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RoutePostAlertRule(&rc, rule) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 201, response.Status()) | 
					
						
							|  |  |  | 				created := deserializeRule(t, response.Body()) | 
					
						
							|  |  |  | 				require.Equal(t, int64(3), created.OrgID) | 
					
						
							| 
									
										
										
										
											2023-02-28 06:57:15 +08:00
										 |  |  | 				require.Equal(t, definitions.Provenance(models.ProvenanceNone), created.Provenance) | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-12 02:58:45 +08:00
										 |  |  | 			t.Run("PUT sets expected fields with no provenance", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							| 
									
										
										
										
											2023-09-09 03:09:35 +08:00
										 |  |  | 				uid := util.GenerateShortUID() | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 				rule := createTestAlertRule("rule", 1) | 
					
						
							|  |  |  | 				rule.UID = uid | 
					
						
							|  |  |  | 				insertRuleInOrg(t, sut, rule, 3) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							| 
									
										
										
										
											2022-11-12 02:58:45 +08:00
										 |  |  | 				rc.Req.Header = map[string][]string{"X-Disable-Provenance": {"hello"}} | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 				rc.OrgID = 3 | 
					
						
							|  |  |  | 				rule.OrgID = 1 // Set the org back to something wrong, we should still prefer the value from the req context.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RoutePutAlertRule(&rc, rule, rule.UID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				created := deserializeRule(t, response.Body()) | 
					
						
							|  |  |  | 				require.Equal(t, int64(3), created.OrgID) | 
					
						
							| 
									
										
										
										
											2023-02-28 06:57:15 +08:00
										 |  |  | 				require.Equal(t, definitions.Provenance(models.ProvenanceNone), created.Provenance) | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		t.Run("are missing, PUT returns 404", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 			rc := createTestRequestCtx() | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 			rule := createTestAlertRule("rule", 1) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-24 04:13:39 +08:00
										 |  |  | 			response := sut.RoutePutAlertRule(&rc, rule, "does not exist") | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 			require.Equal(t, 404, response.Status()) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-27 16:25:34 +08:00
										 |  |  | 		t.Run("are missing, GET returns 404", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 			response := sut.RouteRouteGetAlertRule(&rc, "does not exist") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 404, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 		t.Run("have reached the rule quota, POST returns 403", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 			env := createTestEnv(t, testConfig) | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 			quotas := provisioning.MockQuotaChecker{} | 
					
						
							|  |  |  | 			quotas.EXPECT().LimitExceeded() | 
					
						
							|  |  |  | 			env.quotas = "as | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 			rule := createTestAlertRule("rule", 1) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RoutePostAlertRule(&rc, rule) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 403, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-07-06 00:53:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("alert rule groups", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("are present, GET returns 200", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 			insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetAlertRuleGroup(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("are missing, GET returns 404", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 			insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetAlertRuleGroup(&rc, "folder-uid", "does not exist") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 404, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-08-11 01:33:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("are invalid at group level", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("PUT returns 400", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 				group := createInvalidAlertRuleGroup() | 
					
						
							|  |  |  | 				group.Interval = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RoutePutAlertRuleGroup(&rc, group, "folder-uid", group.Title) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "invalid alert rule") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("are invalid at rule level", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("PUT returns 400", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 				group := createInvalidAlertRuleGroup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RoutePutAlertRuleGroup(&rc, group, "folder-uid", group.Title) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				require.NotEmpty(t, response.Body()) | 
					
						
							|  |  |  | 				require.Contains(t, string(response.Body()), "invalid alert rule") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-07-06 00:53:50 +08:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	t.Run("exports", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("alert rule group", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("are present, GET returns 200", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("are missing, GET returns 404", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "does not exist") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 404, response.Status()) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains yaml, GET returns text yaml", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-03 00:10:02 +08:00
										 |  |  | 			t.Run("query format contains yaml, GET returns text yaml", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("format", "yaml") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query format contains unknown value, GET returns text yaml", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("format", "foo") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 			t.Run("accept header contains json, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains json and yaml, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json, application/yaml") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download=true, GET returns content disposition attachment", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("download", "true") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Contains(t, rc.Context.Resp.Header().Get("Content-Disposition"), "attachment") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download=false, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("download", "false") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download not set, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-03 00:10:02 +08:00
										 |  |  | 			t.Run("yaml body content is the default", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule2", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				expectedResponse := "apiVersion: 1\ngroups:\n    - orgId: 1\n      name: my-cool-group\n      folder" + | 
					
						
							|  |  |  | 					": Folder Title\n      interval: 1m\n      rules:\n        - uid: rule1\n          title: rule1\n" + | 
					
						
							|  |  |  | 					"          condition: A\n          data:\n            - refId: A\n              datasourceUid" + | 
					
						
							|  |  |  | 					": \"\"\n              model:\n                conditions:\n                    - evaluator:\n" + | 
					
						
							|  |  |  | 					"                        params:\n                            - 3\n                        type: gt\n                      operator:\n                        type: and\n                      query:\n                        params:\n                            - A\n                      reducer:\n                        type: last\n                      type: query\n                datasource:\n                    type: __expr__\n                    uid: __expr__\n                expression: 1==0\n                intervalMs: 1000\n                maxDataPoints: 43200\n                refId: A\n                type: math\n          noDataState: OK\n          execErrState: OK\n          for: 0s\n          isPaused: false\n        - uid: rule2\n          title: rule2\n          condition: A\n          data:\n            - refId: A\n              datasourceUid: \"\"\n              model:\n                conditions:\n                    - evaluator:\n                        params:\n                            - 3\n                        type: gt\n                      operator:\n                        type: and\n                      query:\n                        params:\n                            - A\n                      reducer:\n                        type: last\n                      type: query\n                datasource:\n                    type: __expr__\n                    uid: __expr__\n                expression: 1==0\n                intervalMs: 1000\n                maxDataPoints: 43200\n                refId: A\n                type: math\n          noDataState: OK\n          execErrState: OK\n          for: 0s\n          isPaused: false\n" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 			t.Run("json body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule2", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-03 00:10:02 +08:00
										 |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							| 
									
										
										
										
											2023-02-01 01:50:10 +08:00
										 |  |  | 				expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"my-cool-group","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false},{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}` | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("yaml body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule2", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							| 
									
										
										
										
											2023-02-01 01:50:10 +08:00
										 |  |  | 				expectedResponse := "apiVersion: 1\ngroups:\n    - orgId: 1\n      name: my-cool-group\n      folder" + | 
					
						
							|  |  |  | 					": Folder Title\n      interval: 1m\n      rules:\n        - uid: rule1\n          title: rule1\n" + | 
					
						
							|  |  |  | 					"          condition: A\n          data:\n            - refId: A\n              datasourceUid" + | 
					
						
							|  |  |  | 					": \"\"\n              model:\n                conditions:\n                    - evaluator:\n" + | 
					
						
							|  |  |  | 					"                        params:\n                            - 3\n                        type: gt\n                      operator:\n                        type: and\n                      query:\n                        params:\n                            - A\n                      reducer:\n                        type: last\n                      type: query\n                datasource:\n                    type: __expr__\n                    uid: __expr__\n                expression: 1==0\n                intervalMs: 1000\n                maxDataPoints: 43200\n                refId: A\n                type: math\n          noDataState: OK\n          execErrState: OK\n          for: 0s\n          isPaused: false\n        - uid: rule2\n          title: rule2\n          condition: A\n          data:\n            - refId: A\n              datasourceUid: \"\"\n              model:\n                conditions:\n                    - evaluator:\n                        params:\n                            - 3\n                        type: gt\n                      operator:\n                        type: and\n                      query:\n                        params:\n                            - A\n                      reducer:\n                        type: last\n                      type: query\n                datasource:\n                    type: __expr__\n                    uid: __expr__\n                expression: 1==0\n                intervalMs: 1000\n                maxDataPoints: 43200\n                refId: A\n                type: math\n          noDataState: OK\n          execErrState: OK\n          for: 0s\n          isPaused: false\n" | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2023-09-11 23:48:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("hcl body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rule1 := createTestAlertRule("rule1", 1) | 
					
						
							|  |  |  | 				rule1.Labels = map[string]string{ | 
					
						
							|  |  |  | 					"test": "label", | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				rule1.Annotations = map[string]string{ | 
					
						
							|  |  |  | 					"test": "annotation", | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				rule1.NoDataState = definitions.Alerting | 
					
						
							|  |  |  | 				rule1.ExecErrState = definitions.ErrorErrState | 
					
						
							|  |  |  | 				insertRule(t, sut, rule1) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule2", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				expectedResponse := `resource "grafana_rule_group" "rule_group_0000" { | 
					
						
							|  |  |  |   org_id           = 1 | 
					
						
							|  |  |  |   name             = "my-cool-group" | 
					
						
							|  |  |  |   folder_uid       = "folder-uid" | 
					
						
							|  |  |  |   interval_seconds = 60 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rule { | 
					
						
							|  |  |  |     name      = "rule1" | 
					
						
							|  |  |  |     condition = "A" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     data { | 
					
						
							| 
									
										
										
										
											2023-10-06 03:16:44 +08:00
										 |  |  |       ref_id = "A" | 
					
						
							| 
									
										
										
										
											2023-09-11 23:48:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       relative_time_range { | 
					
						
							|  |  |  |         from = 0 | 
					
						
							|  |  |  |         to   = 0 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       datasource_uid = "" | 
					
						
							|  |  |  |       model          = "{\"conditions\":[{\"evaluator\":{\"params\":[3],\"type\":\"gt\"},\"operator\":{\"type\":\"and\"},\"query\":{\"params\":[\"A\"]},\"reducer\":{\"type\":\"last\"},\"type\":\"query\"}],\"datasource\":{\"type\":\"__expr__\",\"uid\":\"__expr__\"},\"expression\":\"1==0\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"refId\":\"A\",\"type\":\"math\"}" | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     no_data_state  = "Alerting" | 
					
						
							|  |  |  |     exec_err_state = "Error" | 
					
						
							| 
									
										
										
										
											2023-10-20 17:09:08 +08:00
										 |  |  |     for            = "0s" | 
					
						
							| 
									
										
										
										
											2023-09-11 23:48:23 +08:00
										 |  |  |     annotations = { | 
					
						
							|  |  |  |       test = "annotation" | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     labels = { | 
					
						
							|  |  |  |       test = "label" | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     is_paused = false | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   rule { | 
					
						
							|  |  |  |     name      = "rule2" | 
					
						
							|  |  |  |     condition = "A" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     data { | 
					
						
							| 
									
										
										
										
											2023-10-06 03:16:44 +08:00
										 |  |  |       ref_id = "A" | 
					
						
							| 
									
										
										
										
											2023-09-11 23:48:23 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       relative_time_range { | 
					
						
							|  |  |  |         from = 0 | 
					
						
							|  |  |  |         to   = 0 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       datasource_uid = "" | 
					
						
							|  |  |  |       model          = "{\"conditions\":[{\"evaluator\":{\"params\":[3],\"type\":\"gt\"},\"operator\":{\"type\":\"and\"},\"query\":{\"params\":[\"A\"]},\"reducer\":{\"type\":\"last\"},\"type\":\"query\"}],\"datasource\":{\"type\":\"__expr__\",\"uid\":\"__expr__\"},\"expression\":\"1==0\",\"intervalMs\":1000,\"maxDataPoints\":43200,\"refId\":\"A\",\"type\":\"math\"}" | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     no_data_state  = "OK" | 
					
						
							|  |  |  |     exec_err_state = "OK" | 
					
						
							| 
									
										
										
										
											2023-10-20 17:09:08 +08:00
										 |  |  |     for            = "0s" | 
					
						
							| 
									
										
										
										
											2023-09-11 23:48:23 +08:00
										 |  |  |     is_paused      = false | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("format", "hcl") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("download", "false") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 				require.Equal(t, "text/hcl", rc.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				t.Run("and add specific headers if download=true", func(t *testing.T) { | 
					
						
							|  |  |  | 					rc := createTestRequestCtx() | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("format", "hcl") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("download", "true") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					response := sut.RouteGetAlertRuleGroupExport(&rc, "folder-uid", "my-cool-group") | 
					
						
							|  |  |  | 					response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 					require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 					require.Equal(t, "application/terraform+hcl", rc.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 					require.Equal(t, `attachment;filename=export.tf`, rc.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("alert rule", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("are present, GET returns 200", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("are missing, GET returns 404", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule404") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 404, response.Status()) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains yaml, GET returns text yaml", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule1") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains json, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule1") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains json and yaml, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json, application/yaml") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule1") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download=true, GET returns content disposition attachment", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("download", "true") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule1") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Contains(t, rc.Context.Resp.Header().Get("Content-Disposition"), "attachment") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download=false, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("download", "false") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule1") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download not set, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule1") | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("json body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 01:50:10 +08:00
										 |  |  | 				expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"my-cool-group","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}` | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-03 00:10:02 +08:00
										 |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("yaml body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule1", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							| 
									
										
										
										
											2023-02-01 01:50:10 +08:00
										 |  |  | 				expectedResponse := "apiVersion: 1\ngroups:\n    - orgId: 1\n      name: my-cool-group\n      folder: Folder Title\n      interval: 1m\n      rules:\n        - uid: rule1\n          title: rule1\n          condition: A\n          data:\n            - refId: A\n              datasourceUid: \"\"\n              model:\n                conditions:\n                    - evaluator:\n                        params:\n                            - 3\n                        type: gt\n                      operator:\n                        type: and\n                      query:\n                        params:\n                            - A\n                      reducer:\n                        type: last\n                      type: query\n                datasource:\n                    type: __expr__\n                    uid: __expr__\n                expression: 1==0\n                intervalMs: 1000\n                maxDataPoints: 43200\n                refId: A\n                type: math\n          noDataState: OK\n          execErrState: OK\n          for: 0s\n          isPaused: false\n" | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRuleExport(&rc, "rule1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("all alert rules", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("are present, GET returns 200", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains yaml, GET returns text yaml", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains json, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains json and yaml, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json, application/yaml") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download=true, GET returns content disposition attachment", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("download", "true") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Contains(t, rc.Context.Resp.Header().Get("Content-Disposition"), "attachment") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download=false, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("download", "false") | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download not set, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRule("rule", 1)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("json body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule1", 1, "folder-uid", "groupa")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule2", 1, "folder-uid", "groupb")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule3", 1, "folder-uid2", "groupb")) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-03 00:10:02 +08:00
										 |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							| 
									
										
										
										
											2023-02-01 01:50:10 +08:00
										 |  |  | 				expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]},{"orgId":1,"name":"groupb","folder":"Folder Title2","interval":"1m","rules":[{"uid":"rule3","title":"rule3","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}` | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("yaml body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule1", 1, "folder-uid", "groupa")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule2", 1, "folder-uid", "groupb")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule3", 1, "folder-uid2", "groupb")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							| 
									
										
										
										
											2023-02-01 01:50:10 +08:00
										 |  |  | 				expectedResponse := "apiVersion: 1\ngroups:\n    - orgId: 1\n      name: groupa\n      folder: Folder Title\n      interval: 1m\n      rules:\n        - uid: rule1\n          title: rule1\n          condition: A\n          data:\n            - refId: A\n              datasourceUid: \"\"\n              model:\n                conditions:\n                    - evaluator:\n                        params:\n                            - 3\n                        type: gt\n                      operator:\n                        type: and\n                      query:\n                        params:\n                            - A\n                      reducer:\n                        type: last\n                      type: query\n                datasource:\n                    type: __expr__\n                    uid: __expr__\n                expression: 1==0\n                intervalMs: 1000\n                maxDataPoints: 43200\n                refId: A\n                type: math\n          noDataState: OK\n          execErrState: OK\n          for: 0s\n          isPaused: false\n    - orgId: 1\n      name: groupb\n      folder: Folder Title\n      interval: 1m\n      rules:\n        - uid: rule2\n          title: rule2\n          condition: A\n          data:\n            - refId: A\n              datasourceUid: \"\"\n              model:\n                conditions:\n                    - evaluator:\n                        params:\n                            - 3\n                        type: gt\n                      operator:\n                        type: and\n                      query:\n                        params:\n                            - A\n                      reducer:\n                        type: last\n                      type: query\n                datasource:\n                    type: __expr__\n                    uid: __expr__\n                expression: 1==0\n                intervalMs: 1000\n                maxDataPoints: 43200\n                refId: A\n                type: math\n          noDataState: OK\n          execErrState: OK\n          for: 0s\n          isPaused: false\n    - orgId: 1\n      name: groupb\n      folder: Folder Title2\n      interval: 1m\n      rules:\n        - uid: rule3\n          title: rule3\n          condition: A\n          data:\n            - refId: A\n              datasourceUid: \"\"\n              model:\n                conditions:\n                    - evaluator:\n                        params:\n                            - 3\n                        type: gt\n                      operator:\n                        type: and\n                      query:\n                        params:\n                            - A\n                      reducer:\n                        type: last\n                      type: query\n                datasource:\n                    type: __expr__\n                    uid: __expr__\n                expression: 1==0\n                intervalMs: 1000\n                maxDataPoints: 43200\n                refId: A\n                type: math\n          noDataState: OK\n          execErrState: OK\n          for: 0s\n          isPaused: false\n" | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2023-09-08 05:34:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept query parameter folder_uid", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule1", 1, "folder-uid", "groupa")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule2", 1, "folder-uid", "groupb")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule3", 1, "folder-uid2", "groupb")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("folderUid", "folder-uid") | 
					
						
							|  |  |  | 				expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-12 01:13:02 +08:00
										 |  |  | 			t.Run("accept multiple query parameters folder_uid", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule1", 1, "folder-uid", "groupa")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule2", 1, "folder-uid", "groupb")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule3", 1, "folder-uid2", "groupb")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("folder_uid", "folder-uid") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Add("folder_uid", "folder-uid2") | 
					
						
							|  |  |  | 				expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]},{"orgId":1,"name":"groupb","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule2","title":"rule2","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]},{"orgId":1,"name":"groupb","folder":"Folder Title2","interval":"1m","rules":[{"uid":"rule3","title":"rule3","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-08 05:34:32 +08:00
										 |  |  | 			t.Run("accepts parameter group", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule1", 1, "folder-uid", "groupa")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule2", 1, "folder-uid", "groupb")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule3", 1, "folder-uid2", "groupb")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("folderUid", "folder-uid") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("group", "groupa") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				t.Run("and fails if folderUID is empty", func(t *testing.T) { | 
					
						
							|  |  |  | 					rc := createTestRequestCtx() | 
					
						
							|  |  |  | 					rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("group", "groupa") | 
					
						
							| 
									
										
										
										
											2023-09-12 01:13:02 +08:00
										 |  |  | 					rc.Context.Req.Form.Set("folderUid", "") | 
					
						
							|  |  |  | 					response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				t.Run("and fails if multiple folder UIDs are specified", func(t *testing.T) { | 
					
						
							|  |  |  | 					rc := createTestRequestCtx() | 
					
						
							|  |  |  | 					rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("group", "groupa") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("folderUid", "folder-uid") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Add("folderUid", "folder-uid2") | 
					
						
							|  |  |  | 					response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accepts parameter ruleUid", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule1", 1, "folder-uid", "groupa")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule2", 1, "folder-uid", "groupa")) | 
					
						
							|  |  |  | 				insertRule(t, sut, createTestAlertRuleWithFolderAndGroup("rule3", 1, "folder-uid2", "groupb")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("ruleUid", "rule1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				expectedResponse := `{"apiVersion":1,"groups":[{"orgId":1,"name":"groupa","folder":"Folder Title","interval":"1m","rules":[{"uid":"rule1","title":"rule1","condition":"A","data":[{"refId":"A","relativeTimeRange":{"from":0,"to":0},"datasourceUid":"","model":{"conditions":[{"evaluator":{"params":[3],"type":"gt"},"operator":{"type":"and"},"query":{"params":["A"]},"reducer":{"type":"last"},"type":"query"}],"datasource":{"type":"__expr__","uid":"__expr__"},"expression":"1==0","intervalMs":1000,"maxDataPoints":43200,"refId":"A","type":"math"}}],"noDataState":"OK","execErrState":"OK","for":"0s","isPaused":false}]}]}` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				t.Run("and fails if folderUID and group are specified", func(t *testing.T) { | 
					
						
							|  |  |  | 					rc := createTestRequestCtx() | 
					
						
							|  |  |  | 					rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("group", "groupa") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("folderUid", "folder-uid") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("ruleUid", "rule1") | 
					
						
							|  |  |  | 					response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				t.Run("and fails if only folderUID is specified", func(t *testing.T) { | 
					
						
							|  |  |  | 					rc := createTestRequestCtx() | 
					
						
							|  |  |  | 					rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("folderUid", "folder-uid") | 
					
						
							|  |  |  | 					rc.Context.Req.Form.Set("ruleUid", "rule2") | 
					
						
							| 
									
										
										
										
											2023-09-08 05:34:32 +08:00
										 |  |  | 					response := sut.RouteGetAlertRulesExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					require.Equal(t, 400, response.Status()) | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2023-07-25 05:56:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("notification policies", func(t *testing.T) { | 
					
						
							|  |  |  | 			t.Run("are present, GET returns 200", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains yaml, GET returns text yaml", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains json, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("accept header contains json and yaml, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json, application/yaml") | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download=true, GET returns content disposition attachment", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("download", "true") | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Contains(t, rc.Context.Resp.Header().Get("Content-Disposition"), "attachment") | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download=false, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("download", "false") | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("query param download not set, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 				response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("json body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				sut.policies = createFakeNotificationPolicyService() | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							| 
									
										
										
										
											2023-12-05 05:57:37 +08:00
										 |  |  | 				expectedResponse := `{"apiVersion":1,"policies":[{"orgId":1,"receiver":"default-receiver","group_by":["g1","g2"],"routes":[{"receiver":"nested-receiver","group_by":["g3","g4"],"matchers":["a=\"b\""],"object_matchers":[["foo","=","bar"]],"mute_time_intervals":["interval"],"continue":true,"group_wait":"5m","group_interval":"5m","repeat_interval":"5m"}],"group_wait":"30s","group_interval":"5m","repeat_interval":"1h"}]}` | 
					
						
							| 
									
										
										
										
											2023-07-25 05:56:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("yaml body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				sut.policies = createFakeNotificationPolicyService() | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 				expectedResponse := "apiVersion: 1\npolicies:\n    - orgId: 1\n      receiver: default-receiver\n      group_by:\n        - g1\n        - g2\n      routes:\n        - receiver: nested-receiver\n          group_by:\n            - g3\n            - g4\n          matchers:\n            - a=\"b\"\n          object_matchers:\n            - - foo\n              - =\n              - bar\n          mute_time_intervals:\n            - interval\n          continue: true\n          group_wait: 5m\n          group_interval: 5m\n          repeat_interval: 5m\n      group_wait: 30s\n      group_interval: 5m\n      repeat_interval: 1h\n" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2023-10-13 00:10:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			t.Run("hcl body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 				sut.policies = createFakeNotificationPolicyService() | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Add("format", "hcl") | 
					
						
							|  |  |  | 				expectedResponse := "resource \"grafana_notification_policy\" \"notification_policy_1\" {\n  contact_point = \"default-receiver\"\n  group_by      = [\"g1\", \"g2\"]\n\n  policy {\n    contact_point = \"nested-receiver\"\n    group_by      = [\"g3\", \"g4\"]\n\n    matcher {\n      label = \"foo\"\n      match = \"=\"\n      value = \"bar\"\n    }\n\n    mute_timings    = [\"interval\"]\n    continue        = true\n    group_wait      = \"5m\"\n    group_interval  = \"5m\"\n    repeat_interval = \"5m\"\n  }\n\n  group_wait      = \"30s\"\n  group_interval  = \"5m\"\n  repeat_interval = \"1h\"\n}\n" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetPolicyTreeExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				t.Log(string(response.Body())) | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2023-07-25 05:56:53 +08:00
										 |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | func TestProvisioningApiContactPointExport(t *testing.T) { | 
					
						
							|  |  |  | 	t.Run("contact point export", func(t *testing.T) { | 
					
						
							|  |  |  | 		t.Run("are present, GET returns 200", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("accept header contains yaml, GET returns text yaml", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 			response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 			response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			require.Equal(t, "text/yaml", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("accept header contains json, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 			response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 			response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("accept header contains json and yaml, GET returns json", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rc.Context.Req.Header.Add("Accept", "application/json, application/yaml") | 
					
						
							|  |  |  | 			response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 			response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			require.Equal(t, "application/json", rc.Context.Resp.Header().Get("Content-Type")) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("query param download=true, GET returns content disposition attachment", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rc.Context.Req.Form.Set("download", "true") | 
					
						
							|  |  |  | 			response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 			response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			require.Contains(t, rc.Context.Resp.Header().Get("Content-Disposition"), "attachment") | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("query param download=false, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rc.Context.Req.Form.Set("download", "false") | 
					
						
							|  |  |  | 			response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 			response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("query param download not set, GET returns empty content disposition", func(t *testing.T) { | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSut(t) | 
					
						
							|  |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 			response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 			require.Equal(t, "", rc.Context.Resp.Header().Get("Content-Disposition")) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 		t.Run("decrypt true without alert.provisioning.secrets:read permissions returns 403", func(t *testing.T) { | 
					
						
							|  |  |  | 			env := createTestEnv(t, testConfig) | 
					
						
							|  |  |  | 			env.ac = &recordingAccessControlFake{ | 
					
						
							|  |  |  | 				Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { | 
					
						
							|  |  |  | 					return false, nil | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rc.Context.Req.Form.Set("decrypt", "true") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 403, response.Status()) | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 			require.Len(t, env.ac.EvaluateRecordings, 1) | 
					
						
							|  |  |  | 			require.Equal(t, accesscontrol.ActionAlertingProvisioningReadSecrets, env.ac.EvaluateRecordings[0].Evaluator.String()) | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("decrypt true with admin returns 200", func(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 			env := createTestEnv(t, testConfig) | 
					
						
							|  |  |  | 			env.ac = &recordingAccessControlFake{ | 
					
						
							|  |  |  | 				Callback: func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { | 
					
						
							|  |  |  | 					require.Equal(t, accesscontrol.ActionAlertingProvisioningReadSecrets, evaluator.String()) | 
					
						
							|  |  |  | 					return true, nil | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 			rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rc.Context.Req.Form.Set("decrypt", "true") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 			response.WriteTo(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			require.Equal(t, 200, response.Status()) | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 			require.Len(t, env.ac.EvaluateRecordings, 1) | 
					
						
							|  |  |  | 			require.Equal(t, accesscontrol.ActionAlertingProvisioningReadSecrets, env.ac.EvaluateRecordings[0].Evaluator.String()) | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("json body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 			expectedRedactedResponse := `{"apiVersion":1,"contactPoints":[{"orgId":1,"name":"grafana-default-email","receivers":[{"uid":"ad95bd8a-49ed-4adc-bf89-1b444fa1aa5b","type":"email","settings":{"addresses":"\u003cexample@email.com\u003e"},"disableResolveMessage":false}]},{"orgId":1,"name":"multiple integrations","receivers":[{"uid":"c2090fda-f824-4add-b545-5a4d5c2ef082","type":"prometheus-alertmanager","settings":{"basicAuthPassword":"[REDACTED]","basicAuthUser":"test","url":"http://localhost:9093"},"disableResolveMessage":true},{"uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1","type":"discord","settings":{"avatar_url":"some avatar","url":"some url","use_discord_username":true},"disableResolveMessage":false}]},{"orgId":1,"name":"pagerduty test","receivers":[{"uid":"b9bf06f8-bde2-4438-9d4a-bba0522dcd4d","type":"pagerduty","settings":{"client":"some client","integrationKey":"[REDACTED]","severity":"criticalish"},"disableResolveMessage":false}]},{"orgId":1,"name":"slack test","receivers":[{"uid":"cbfd0976-8228-4126-b672-4419f30a9e50","type":"slack","settings":{"text":"title body test","title":"title test","url":"[REDACTED]"},"disableResolveMessage":true}]}]}` | 
					
						
							|  |  |  | 			t.Run("decrypt false", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "false") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedRedactedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			t.Run("decrypt missing", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedRedactedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			t.Run("decrypt true", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 				env.ac.Callback = func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { | 
					
						
							|  |  |  | 					return true, nil | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 				sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "true") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				expectedResponse := `{"apiVersion":1,"contactPoints":[{"orgId":1,"name":"grafana-default-email","receivers":[{"uid":"ad95bd8a-49ed-4adc-bf89-1b444fa1aa5b","type":"email","settings":{"addresses":"\u003cexample@email.com\u003e"},"disableResolveMessage":false}]},{"orgId":1,"name":"multiple integrations","receivers":[{"uid":"c2090fda-f824-4add-b545-5a4d5c2ef082","type":"prometheus-alertmanager","settings":{"basicAuthPassword":"testpass","basicAuthUser":"test","url":"http://localhost:9093"},"disableResolveMessage":true},{"uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1","type":"discord","settings":{"avatar_url":"some avatar","url":"some url","use_discord_username":true},"disableResolveMessage":false}]},{"orgId":1,"name":"pagerduty test","receivers":[{"uid":"b9bf06f8-bde2-4438-9d4a-bba0522dcd4d","type":"pagerduty","settings":{"client":"some client","integrationKey":"some key","severity":"criticalish"},"disableResolveMessage":false}]},{"orgId":1,"name":"slack test","receivers":[{"uid":"cbfd0976-8228-4126-b672-4419f30a9e50","type":"slack","settings":{"text":"title body test","title":"title test","url":"some secure slack webhook"},"disableResolveMessage":true}]}]}` | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			t.Run("name filters response", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/json") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("name", "multiple integrations") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				expectedResponse := `{"apiVersion":1,"contactPoints":[{"orgId":1,"name":"multiple integrations","receivers":[{"uid":"c2090fda-f824-4add-b545-5a4d5c2ef082","type":"prometheus-alertmanager","settings":{"basicAuthPassword":"[REDACTED]","basicAuthUser":"test","url":"http://localhost:9093"},"disableResolveMessage":true},{"uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1","type":"discord","settings":{"avatar_url":"some avatar","url":"some url","use_discord_username":true},"disableResolveMessage":false}]}]}` | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		t.Run("yaml body content is as expected", func(t *testing.T) { | 
					
						
							|  |  |  | 			expectedRedactedResponse := "apiVersion: 1\ncontactPoints:\n    - orgId: 1\n      name: grafana-default-email\n      receivers:\n        - uid: ad95bd8a-49ed-4adc-bf89-1b444fa1aa5b\n          type: email\n          settings:\n            addresses: <example@email.com>\n          disableResolveMessage: false\n    - orgId: 1\n      name: multiple integrations\n      receivers:\n        - uid: c2090fda-f824-4add-b545-5a4d5c2ef082\n          type: prometheus-alertmanager\n          settings:\n            basicAuthPassword: '[REDACTED]'\n            basicAuthUser: test\n            url: http://localhost:9093\n          disableResolveMessage: true\n        - uid: c84539ec-f87e-4fc5-9a91-7a687d34bbd1\n          type: discord\n          settings:\n            avatar_url: some avatar\n            url: some url\n            use_discord_username: true\n          disableResolveMessage: false\n    - orgId: 1\n      name: pagerduty test\n      receivers:\n        - uid: b9bf06f8-bde2-4438-9d4a-bba0522dcd4d\n          type: pagerduty\n          settings:\n            client: some client\n            integrationKey: '[REDACTED]'\n            severity: criticalish\n          disableResolveMessage: false\n    - orgId: 1\n      name: slack test\n      receivers:\n        - uid: cbfd0976-8228-4126-b672-4419f30a9e50\n          type: slack\n          settings:\n            text: title body test\n            title: title test\n            url: '[REDACTED]'\n          disableResolveMessage: true\n" | 
					
						
							|  |  |  | 			t.Run("decrypt false", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "false") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedRedactedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			t.Run("decrypt missing", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedRedactedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			t.Run("decrypt true", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 				env.ac.Callback = func(user *user.SignedInUser, evaluator accesscontrol.Evaluator) (bool, error) { | 
					
						
							|  |  |  | 					return true, nil | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 				sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("decrypt", "true") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				expectedResponse := "apiVersion: 1\ncontactPoints:\n    - orgId: 1\n      name: grafana-default-email\n      receivers:\n        - uid: ad95bd8a-49ed-4adc-bf89-1b444fa1aa5b\n          type: email\n          settings:\n            addresses: <example@email.com>\n          disableResolveMessage: false\n    - orgId: 1\n      name: multiple integrations\n      receivers:\n        - uid: c2090fda-f824-4add-b545-5a4d5c2ef082\n          type: prometheus-alertmanager\n          settings:\n            basicAuthPassword: testpass\n            basicAuthUser: test\n            url: http://localhost:9093\n          disableResolveMessage: true\n        - uid: c84539ec-f87e-4fc5-9a91-7a687d34bbd1\n          type: discord\n          settings:\n            avatar_url: some avatar\n            url: some url\n            use_discord_username: true\n          disableResolveMessage: false\n    - orgId: 1\n      name: pagerduty test\n      receivers:\n        - uid: b9bf06f8-bde2-4438-9d4a-bba0522dcd4d\n          type: pagerduty\n          settings:\n            client: some client\n            integrationKey: some key\n            severity: criticalish\n          disableResolveMessage: false\n    - orgId: 1\n      name: slack test\n      receivers:\n        - uid: cbfd0976-8228-4126-b672-4419f30a9e50\n          type: slack\n          settings:\n            text: title body test\n            title: title test\n            url: some secure slack webhook\n          disableResolveMessage: true\n" | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			t.Run("name filters response", func(t *testing.T) { | 
					
						
							|  |  |  | 				env := createTestEnv(t, testContactPointConfig) | 
					
						
							|  |  |  | 				sut := createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | 				rc := createTestRequestCtx() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				rc.Context.Req.Header.Add("Accept", "application/yaml") | 
					
						
							|  |  |  | 				rc.Context.Req.Form.Set("name", "multiple integrations") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				response := sut.RouteGetContactPointsExport(&rc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				expectedResponse := "apiVersion: 1\ncontactPoints:\n    - orgId: 1\n      name: multiple integrations\n      receivers:\n        - uid: c2090fda-f824-4add-b545-5a4d5c2ef082\n          type: prometheus-alertmanager\n          settings:\n            basicAuthPassword: '[REDACTED]'\n            basicAuthUser: test\n            url: http://localhost:9093\n          disableResolveMessage: true\n        - uid: c84539ec-f87e-4fc5-9a91-7a687d34bbd1\n          type: discord\n          settings:\n            avatar_url: some avatar\n            url: some url\n            use_discord_username: true\n          disableResolveMessage: false\n" | 
					
						
							|  |  |  | 				require.Equal(t, 200, response.Status()) | 
					
						
							|  |  |  | 				require.Equal(t, expectedResponse, string(response.Body())) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | // testEnvironment binds together common dependencies for testing alerting APIs.
 | 
					
						
							|  |  |  | type testEnvironment struct { | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 	secrets          secrets.Service | 
					
						
							|  |  |  | 	log              log.Logger | 
					
						
							|  |  |  | 	store            store.DBstore | 
					
						
							|  |  |  | 	dashboardService dashboards.DashboardService | 
					
						
							|  |  |  | 	configs          provisioning.AMConfigStore | 
					
						
							|  |  |  | 	xact             provisioning.TransactionManager | 
					
						
							|  |  |  | 	quotas           provisioning.QuotaChecker | 
					
						
							|  |  |  | 	prov             provisioning.ProvisioningStore | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 	ac               *recordingAccessControlFake | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | func createTestEnv(t *testing.T, testConfig string) testEnvironment { | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	t.Helper() | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 	secretsService := secrets_fakes.NewFakeSecretsService() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Encrypt secure settings.
 | 
					
						
							|  |  |  | 	c, err := notifier.Load([]byte(testConfig)) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							| 
									
										
										
										
											2023-07-25 22:04:27 +08:00
										 |  |  | 	err = notifier.EncryptReceiverConfigs(c.AlertmanagerConfig.Receivers, func(ctx context.Context, payload []byte) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 		return secretsService.Encrypt(ctx, payload, secrets.WithoutScope()) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	raw, err := json.Marshal(c) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	log := log.NewNopLogger() | 
					
						
							|  |  |  | 	configs := &provisioning.MockAMConfigStore{} | 
					
						
							|  |  |  | 	configs.EXPECT(). | 
					
						
							|  |  |  | 		GetsConfig(models.AlertConfiguration{ | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 			AlertmanagerConfiguration: string(raw), | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2022-10-19 21:02:15 +08:00
										 |  |  | 	sqlStore := db.InitTestDB(t) | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	store := store.DBstore{ | 
					
						
							| 
									
										
										
										
											2022-07-16 02:13:30 +08:00
										 |  |  | 		SQLStore: sqlStore, | 
					
						
							|  |  |  | 		Cfg: setting.UnifiedAlertingSettings{ | 
					
						
							|  |  |  | 			BaseInterval: time.Second * 10, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 	quotas := &provisioning.MockQuotaChecker{} | 
					
						
							|  |  |  | 	quotas.EXPECT().LimitOK() | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	xact := &provisioning.NopTransactionManager{} | 
					
						
							|  |  |  | 	prov := &provisioning.MockProvisioningStore{} | 
					
						
							|  |  |  | 	prov.EXPECT().SaveSucceeds() | 
					
						
							|  |  |  | 	prov.EXPECT().GetReturns(models.ProvenanceNone) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 	dashboardService := dashboards.NewFakeDashboardService(t) | 
					
						
							|  |  |  | 	dashboardService.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(&dashboards.Dashboard{ | 
					
						
							|  |  |  | 		UID:   "folder-uid", | 
					
						
							|  |  |  | 		Title: "Folder Title", | 
					
						
							|  |  |  | 	}, nil).Maybe() | 
					
						
							|  |  |  | 	dashboardService.On("GetDashboards", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardsQuery")).Return([]*dashboards.Dashboard{{ | 
					
						
							|  |  |  | 		UID:   "folder-uid", | 
					
						
							|  |  |  | 		Title: "Folder Title", | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			UID:   "folder-uid2", | 
					
						
							|  |  |  | 			Title: "Folder Title2", | 
					
						
							|  |  |  | 		}}, nil).Maybe() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 	ac := &recordingAccessControlFake{} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 	return testEnvironment{ | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 		secrets:          secretsService, | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 		log:              log, | 
					
						
							|  |  |  | 		configs:          configs, | 
					
						
							|  |  |  | 		store:            store, | 
					
						
							|  |  |  | 		dashboardService: dashboardService, | 
					
						
							|  |  |  | 		xact:             xact, | 
					
						
							|  |  |  | 		prov:             prov, | 
					
						
							|  |  |  | 		quotas:           quotas, | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 		ac:               ac, | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func createProvisioningSrvSut(t *testing.T) ProvisioningSrv { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 	env := createTestEnv(t, testConfig) | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 	return createProvisioningSrvSutFromEnv(t, &env) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func createProvisioningSrvSutFromEnv(t *testing.T, env *testEnvironment) ProvisioningSrv { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	return ProvisioningSrv{ | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 		log:                 env.log, | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		policies:            newFakeNotificationPolicyService(), | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 		contactPointService: provisioning.NewContactPointService(env.configs, env.secrets, env.prov, env.xact, env.log, env.ac), | 
					
						
							| 
									
										
										
										
											2022-07-14 06:36:17 +08:00
										 |  |  | 		templates:           provisioning.NewTemplateService(env.configs, env.prov, env.xact, env.log), | 
					
						
							|  |  |  | 		muteTimings:         provisioning.NewMuteTimingService(env.configs, env.prov, env.xact, env.log), | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 		alertRules:          provisioning.NewAlertRuleService(env.store, env.prov, env.dashboardService, env.quotas, env.xact, 60, 10, env.log), | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-27 15:50:36 +08:00
										 |  |  | func createTestRequestCtx() contextmodel.ReqContext { | 
					
						
							|  |  |  | 	return contextmodel.ReqContext{ | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 		Context: &web.Context{ | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 			Req: &http.Request{ | 
					
						
							|  |  |  | 				Header: make(http.Header), | 
					
						
							|  |  |  | 				Form:   make(url.Values), | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			Resp: web.NewResponseWriter("GET", httptest.NewRecorder()), | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-08-10 17:56:48 +08:00
										 |  |  | 		SignedInUser: &user.SignedInUser{ | 
					
						
							| 
									
										
										
										
											2022-08-11 19:28:55 +08:00
										 |  |  | 			OrgID: 1, | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2023-08-09 00:29:34 +08:00
										 |  |  | 		Logger: &logtest.Fake{}, | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type fakeNotificationPolicyService struct { | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	tree definitions.Route | 
					
						
							|  |  |  | 	prov models.Provenance | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newFakeNotificationPolicyService() *fakeNotificationPolicyService { | 
					
						
							|  |  |  | 	return &fakeNotificationPolicyService{ | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		tree: definitions.Route{ | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 			Receiver: "some-receiver", | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		prov: models.ProvenanceNone, | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-25 05:56:53 +08:00
										 |  |  | func createFakeNotificationPolicyService() *fakeNotificationPolicyService { | 
					
						
							|  |  |  | 	seconds := model.Duration(time.Duration(30) * time.Second) | 
					
						
							|  |  |  | 	minutes := model.Duration(time.Duration(5) * time.Minute) | 
					
						
							|  |  |  | 	hours := model.Duration(time.Duration(1) * time.Hour) | 
					
						
							|  |  |  | 	return &fakeNotificationPolicyService{ | 
					
						
							|  |  |  | 		tree: definitions.Route{ | 
					
						
							|  |  |  | 			Receiver:       "default-receiver", | 
					
						
							|  |  |  | 			GroupByStr:     []string{"g1", "g2"}, | 
					
						
							|  |  |  | 			GroupWait:      &seconds, | 
					
						
							|  |  |  | 			GroupInterval:  &minutes, | 
					
						
							|  |  |  | 			RepeatInterval: &hours, | 
					
						
							|  |  |  | 			Routes: []*definitions.Route{{ | 
					
						
							|  |  |  | 				Receiver:   "nested-receiver", | 
					
						
							|  |  |  | 				GroupByStr: []string{"g3", "g4"}, | 
					
						
							|  |  |  | 				Matchers: prometheus.Matchers{ | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						Name:  "a", | 
					
						
							|  |  |  | 						Type:  labels.MatchEqual, | 
					
						
							|  |  |  | 						Value: "b", | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				ObjectMatchers:    definitions.ObjectMatchers{{Type: 0, Name: "foo", Value: "bar"}}, | 
					
						
							|  |  |  | 				MuteTimeIntervals: []string{"interval"}, | 
					
						
							|  |  |  | 				Continue:          true, | 
					
						
							|  |  |  | 				GroupWait:         &minutes, | 
					
						
							|  |  |  | 				GroupInterval:     &minutes, | 
					
						
							|  |  |  | 				RepeatInterval:    &minutes, | 
					
						
							|  |  |  | 			}}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		prov: models.ProvenanceAPI, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | func (f *fakeNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) { | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	if orgID != 1 { | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		return definitions.Route{}, store.ErrNoAlertmanagerConfiguration | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-23 00:57:56 +08:00
										 |  |  | 	result := f.tree | 
					
						
							| 
									
										
										
										
											2023-02-28 06:57:15 +08:00
										 |  |  | 	result.Provenance = definitions.Provenance(f.prov) | 
					
						
							| 
									
										
										
										
											2022-04-23 00:57:56 +08:00
										 |  |  | 	return result, nil | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | func (f *fakeNotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgID int64, tree definitions.Route, p models.Provenance) error { | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	if orgID != 1 { | 
					
						
							|  |  |  | 		return store.ErrNoAlertmanagerConfiguration | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	f.tree = tree | 
					
						
							|  |  |  | 	f.prov = p | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-09 05:23:18 +08:00
										 |  |  | func (f *fakeNotificationPolicyService) ResetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) { | 
					
						
							|  |  |  | 	f.tree = definitions.Route{} // TODO
 | 
					
						
							|  |  |  | 	return f.tree, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | type fakeFailingNotificationPolicyService struct{} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | func (f *fakeFailingNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) { | 
					
						
							|  |  |  | 	return definitions.Route{}, fmt.Errorf("something went wrong") | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | func (f *fakeFailingNotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgID int64, tree definitions.Route, p models.Provenance) error { | 
					
						
							| 
									
										
										
										
											2022-04-06 05:48:51 +08:00
										 |  |  | 	return fmt.Errorf("something went wrong") | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-04-28 04:15:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-09 05:23:18 +08:00
										 |  |  | func (f *fakeFailingNotificationPolicyService) ResetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) { | 
					
						
							|  |  |  | 	return definitions.Route{}, fmt.Errorf("something went wrong") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-28 04:15:41 +08:00
										 |  |  | type fakeRejectingNotificationPolicyService struct{} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | func (f *fakeRejectingNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) { | 
					
						
							|  |  |  | 	return definitions.Route{}, nil | 
					
						
							| 
									
										
										
										
											2022-04-28 04:15:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | func (f *fakeRejectingNotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgID int64, tree definitions.Route, p models.Provenance) error { | 
					
						
							| 
									
										
										
										
											2022-04-28 04:15:41 +08:00
										 |  |  | 	return fmt.Errorf("%w: invalid policy tree", provisioning.ErrValidation) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-09 05:23:18 +08:00
										 |  |  | func (f *fakeRejectingNotificationPolicyService) ResetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) { | 
					
						
							|  |  |  | 	return definitions.Route{}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | func createInvalidContactPoint() definitions.EmbeddedContactPoint { | 
					
						
							|  |  |  | 	settings, _ := simplejson.NewJson([]byte(`{}`)) | 
					
						
							|  |  |  | 	return definitions.EmbeddedContactPoint{ | 
					
						
							|  |  |  | 		Name:     "test-contact-point", | 
					
						
							|  |  |  | 		Type:     "slack", | 
					
						
							|  |  |  | 		Settings: settings, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func createInvalidMuteTiming() definitions.MuteTimeInterval { | 
					
						
							|  |  |  | 	return definitions.MuteTimeInterval{ | 
					
						
							|  |  |  | 		MuteTimeInterval: prometheus.MuteTimeInterval{ | 
					
						
							|  |  |  | 			Name: "interval", | 
					
						
							|  |  |  | 			TimeIntervals: []timeinterval.TimeInterval{ | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					Weekdays: []timeinterval.WeekdayRange{ | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							InclusiveRange: timeinterval.InclusiveRange{ | 
					
						
							|  |  |  | 								Begin: -1, | 
					
						
							|  |  |  | 								End:   7, | 
					
						
							|  |  |  | 							}, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 17:34:54 +08:00
										 |  |  | func createInvalidAlertRule() definitions.ProvisionedAlertRule { | 
					
						
							|  |  |  | 	return definitions.ProvisionedAlertRule{} | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-11 01:33:41 +08:00
										 |  |  | func createInvalidAlertRuleGroup() definitions.AlertRuleGroup { | 
					
						
							|  |  |  | 	return definitions.AlertRuleGroup{ | 
					
						
							|  |  |  | 		Title:    "invalid", | 
					
						
							|  |  |  | 		Interval: 10, | 
					
						
							| 
									
										
										
										
											2022-08-13 05:36:50 +08:00
										 |  |  | 		Rules:    []definitions.ProvisionedAlertRule{{}}, | 
					
						
							| 
									
										
										
										
											2022-08-11 01:33:41 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | func createTestAlertRuleWithFolderAndGroup(title string, orgID int64, folderUid string, group string) definitions.ProvisionedAlertRule { | 
					
						
							|  |  |  | 	rule := createTestAlertRule(title, orgID) | 
					
						
							|  |  |  | 	rule.FolderUID = folderUid | 
					
						
							|  |  |  | 	rule.RuleGroup = group | 
					
						
							|  |  |  | 	return rule | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 17:34:54 +08:00
										 |  |  | func createTestAlertRule(title string, orgID int64) definitions.ProvisionedAlertRule { | 
					
						
							|  |  |  | 	return definitions.ProvisionedAlertRule{ | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 		UID:       title, | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 		OrgID:     orgID, | 
					
						
							|  |  |  | 		Title:     title, | 
					
						
							|  |  |  | 		Condition: "A", | 
					
						
							| 
									
										
										
										
											2023-03-27 23:55:13 +08:00
										 |  |  | 		Data: []definitions.AlertQuery{ | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				RefID: "A", | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | 				Model: json.RawMessage(testModel), | 
					
						
							| 
									
										
										
										
											2023-03-27 23:55:13 +08:00
										 |  |  | 				RelativeTimeRange: definitions.RelativeTimeRange{ | 
					
						
							|  |  |  | 					From: definitions.Duration(60), | 
					
						
							|  |  |  | 					To:   definitions.Duration(0), | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		RuleGroup:    "my-cool-group", | 
					
						
							| 
									
										
										
										
											2022-07-06 00:53:50 +08:00
										 |  |  | 		FolderUID:    "folder-uid", | 
					
						
							| 
									
										
										
										
											2022-08-12 06:58:02 +08:00
										 |  |  | 		For:          model.Duration(60), | 
					
						
							| 
									
										
										
										
											2023-03-01 05:21:41 +08:00
										 |  |  | 		NoDataState:  definitions.OK, | 
					
						
							|  |  |  | 		ExecErrState: definitions.OkErrState, | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 17:34:54 +08:00
										 |  |  | func insertRule(t *testing.T, srv ProvisioningSrv, rule definitions.ProvisionedAlertRule) { | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 	insertRuleInOrg(t, srv, rule, 1) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func insertRuleInOrg(t *testing.T, srv ProvisioningSrv, rule definitions.ProvisionedAlertRule, orgID int64) { | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rc := createTestRequestCtx() | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | 	rc.OrgID = orgID | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 	resp := srv.RoutePostAlertRule(&rc, rule) | 
					
						
							|  |  |  | 	require.Equal(t, 201, resp.Status()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-07 03:51:54 +08:00
										 |  |  | func deserializeRule(t *testing.T, data []byte) definitions.ProvisionedAlertRule { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var rule definitions.ProvisionedAlertRule | 
					
						
							|  |  |  | 	err := json.Unmarshal(data, &rule) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 	return rule | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  | var testModel = ` | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   "conditions": [ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       "evaluator": { | 
					
						
							|  |  |  |         "params": [ | 
					
						
							|  |  |  |           3 | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         "type": "gt" | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       "operator": { | 
					
						
							|  |  |  |         "type": "and" | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       "query": { | 
					
						
							|  |  |  |         "params": [ | 
					
						
							|  |  |  |           "A" | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       "reducer": { | 
					
						
							|  |  |  |         "type": "last" | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       "type": "query" | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   ], | 
					
						
							|  |  |  |   "datasource": { | 
					
						
							|  |  |  |     "type": "__expr__", | 
					
						
							| 
									
										
										
										
											2023-02-01 01:50:10 +08:00
										 |  |  |     "uid": "__expr__" | 
					
						
							| 
									
										
										
										
											2023-01-28 00:39:16 +08:00
										 |  |  |   }, | 
					
						
							|  |  |  |   "expression": "1==0", | 
					
						
							|  |  |  |   "intervalMs": 1000, | 
					
						
							|  |  |  |   "maxDataPoints": 43200, | 
					
						
							|  |  |  |   "refId": "A", | 
					
						
							|  |  |  |   "type": "math" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | var testConfig = ` | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	"template_files": { | 
					
						
							|  |  |  | 		"a": "template" | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	"alertmanager_config": { | 
					
						
							|  |  |  | 		"route": { | 
					
						
							|  |  |  | 			"receiver": "grafana-default-email" | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		"receivers": [{ | 
					
						
							|  |  |  | 			"name": "grafana-default-email", | 
					
						
							|  |  |  | 			"grafana_managed_receiver_configs": [{ | 
					
						
							| 
									
										
										
										
											2022-06-24 04:13:39 +08:00
										 |  |  | 				"uid": "email-uid", | 
					
						
							| 
									
										
										
										
											2022-06-09 16:38:46 +08:00
										 |  |  | 				"name": "email receiver", | 
					
						
							|  |  |  | 				"type": "email", | 
					
						
							|  |  |  | 				"isDefault": true, | 
					
						
							|  |  |  | 				"settings": { | 
					
						
							|  |  |  | 					"addresses": "<example@email.com>" | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}] | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 		"mute_time_intervals": [{ | 
					
						
							|  |  |  | 			"name": "interval", | 
					
						
							|  |  |  | 			"time_intervals": [] | 
					
						
							|  |  |  | 		}] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ` | 
					
						
							| 
									
										
										
										
											2023-07-21 02:35:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | var testContactPointConfig = ` | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	"template_files": { | 
					
						
							|  |  |  | 		"a": "template" | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	"alertmanager_config": { | 
					
						
							|  |  |  | 		"route": { | 
					
						
							|  |  |  | 			"receiver": "grafana-default-email" | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		"receivers": [ | 
					
						
							|  |  |  |    { | 
					
						
							|  |  |  |       "name":"grafana-default-email", | 
					
						
							|  |  |  |       "grafana_managed_receiver_configs":[ | 
					
						
							|  |  |  |          { | 
					
						
							|  |  |  |             "uid":"ad95bd8a-49ed-4adc-bf89-1b444fa1aa5b", | 
					
						
							|  |  |  |             "name":"grafana-default-email", | 
					
						
							|  |  |  |             "type":"email", | 
					
						
							|  |  |  |             "disableResolveMessage":false, | 
					
						
							|  |  |  |             "settings":{ | 
					
						
							|  |  |  |                "addresses":"<example@email.com>" | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "secureSettings":{} | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |    }, | 
					
						
							|  |  |  |    { | 
					
						
							|  |  |  |       "name":"multiple integrations", | 
					
						
							|  |  |  |       "grafana_managed_receiver_configs":[ | 
					
						
							|  |  |  |          { | 
					
						
							|  |  |  |             "uid":"c2090fda-f824-4add-b545-5a4d5c2ef082", | 
					
						
							|  |  |  |             "name":"multiple integrations", | 
					
						
							|  |  |  |             "type":"prometheus-alertmanager", | 
					
						
							|  |  |  |             "disableResolveMessage":true, | 
					
						
							|  |  |  |             "settings":{ | 
					
						
							|  |  |  |                "basicAuthUser":"test", | 
					
						
							|  |  |  |                "url":"http://localhost:9093" | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "secureSettings":{ | 
					
						
							|  |  |  |                "basicAuthPassword":"testpass" | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |          }, | 
					
						
							|  |  |  |          { | 
					
						
							|  |  |  |             "uid":"c84539ec-f87e-4fc5-9a91-7a687d34bbd1", | 
					
						
							|  |  |  |             "name":"multiple integrations", | 
					
						
							|  |  |  |             "type":"discord", | 
					
						
							|  |  |  |             "disableResolveMessage":false, | 
					
						
							|  |  |  |             "settings":{ | 
					
						
							|  |  |  |                "avatar_url":"some avatar", | 
					
						
							|  |  |  |                "url":"some url", | 
					
						
							|  |  |  |                "use_discord_username":true | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "secureSettings":{} | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |    }, | 
					
						
							|  |  |  |    { | 
					
						
							|  |  |  |       "name":"pagerduty test", | 
					
						
							|  |  |  |       "grafana_managed_receiver_configs":[ | 
					
						
							|  |  |  |          { | 
					
						
							|  |  |  |             "uid":"b9bf06f8-bde2-4438-9d4a-bba0522dcd4d", | 
					
						
							|  |  |  |             "name":"pagerduty test", | 
					
						
							|  |  |  |             "type":"pagerduty", | 
					
						
							|  |  |  |             "disableResolveMessage":false, | 
					
						
							|  |  |  |             "settings":{ | 
					
						
							|  |  |  |                "client":"some client", | 
					
						
							|  |  |  |                "severity":"criticalish" | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "secureSettings":{ | 
					
						
							|  |  |  |                "integrationKey":"some key" | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |    }, | 
					
						
							|  |  |  |    { | 
					
						
							|  |  |  |       "name":"slack test", | 
					
						
							|  |  |  |       "grafana_managed_receiver_configs":[ | 
					
						
							|  |  |  |          { | 
					
						
							|  |  |  |             "uid":"cbfd0976-8228-4126-b672-4419f30a9e50", | 
					
						
							|  |  |  |             "name":"slack test", | 
					
						
							|  |  |  |             "type":"slack", | 
					
						
							|  |  |  |             "disableResolveMessage":true, | 
					
						
							|  |  |  |             "settings":{ | 
					
						
							|  |  |  |                "text":"title body test", | 
					
						
							|  |  |  |                "title":"title test" | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "secureSettings":{ | 
					
						
							|  |  |  |                "url":"some secure slack webhook" | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |       ] | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | ] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ` |