Merge branch 'main' of https://github.com/grafana/grafana into #45498-entity-events
This commit is contained in:
+1
-1
@@ -290,7 +290,7 @@ exports[`no enzyme tests`] = {
|
||||
"public/app/plugins/datasource/cloudwatch/components/ConfigEditor.test.tsx:2974837543": [
|
||||
[1, 19, 13, "RegExp match", "2409514259"]
|
||||
],
|
||||
"public/app/plugins/datasource/cloudwatch/components/LogsQueryField.test.tsx:132770839": [
|
||||
"public/app/plugins/datasource/cloudwatch/components/LogsQueryField.test.tsx:3888529428": [
|
||||
[1, 19, 13, "RegExp match", "2409514259"]
|
||||
],
|
||||
"public/app/plugins/datasource/elasticsearch/configuration/ConfigEditor.test.tsx:1089831034": [
|
||||
|
||||
+422
-339
File diff suppressed because it is too large
Load Diff
@@ -230,6 +230,9 @@ application_insights_connection_string =
|
||||
# Optional. Specifies an Application Insights endpoint URL where the endpoint string is wrapped in backticks ``.
|
||||
application_insights_endpoint_url =
|
||||
|
||||
# Controls if the UI contains any links to user feedback forms
|
||||
feedback_links_enabled = true
|
||||
|
||||
#################################### Security ############################
|
||||
[security]
|
||||
# disable creation of admin user on first start of grafana
|
||||
|
||||
@@ -230,6 +230,9 @@
|
||||
# Rudderstack Config url, optional, used by Rudderstack SDK to fetch source config
|
||||
;rudderstack_config_url =
|
||||
|
||||
# Controls if the UI contains any links to user feedback forms
|
||||
;feedback_links_enabled = true
|
||||
|
||||
#################################### Security ####################################
|
||||
[security]
|
||||
# disable creation of admin user on first start of grafana
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev_dashboards
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed *.json */*.json
|
||||
var DevDashboardFS embed.FS
|
||||
@@ -0,0 +1,84 @@
|
||||
package dev_dashboards
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"cuelang.org/go/cue/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/coremodel/dashboard"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
)
|
||||
|
||||
func TestDevenvDashboardValidity(t *testing.T) {
|
||||
m, err := themaTestableDashboards()
|
||||
require.NoError(t, err)
|
||||
cm, err := dashboard.ProvideCoremodel(cuectx.ProvideThemaLibrary())
|
||||
require.NoError(t, err)
|
||||
|
||||
for path, b := range m {
|
||||
t.Run(path, func(t *testing.T) {
|
||||
// The path arg here only matters for error output
|
||||
cv, err := cuectx.JSONtoCUE(path, b)
|
||||
require.NoError(t, err, "error while decoding dashboard JSON into a CUE value")
|
||||
|
||||
_, err = cm.CurrentSchema().Validate(cv)
|
||||
if err != nil {
|
||||
// Testify trims errors to short length. We want the full text
|
||||
errstr := errors.Details(err, nil)
|
||||
t.Log(errstr)
|
||||
if strings.Contains(errstr, "null") {
|
||||
t.Log("validation failure appears to involve nulls - see if scripts/stripnulls.sh has any effect?")
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func themaTestableDashboards() (map[string][]byte, error) {
|
||||
m := make(map[string][]byte)
|
||||
in := DevDashboardFS
|
||||
|
||||
err := fs.WalkDir(in, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.IsDir() || filepath.Ext(d.Name()) != ".json" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// nolint:gosec
|
||||
f, err := in.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close() // nolint: errcheck
|
||||
|
||||
b, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jtree := make(map[string]interface{})
|
||||
json.Unmarshal(b, &jtree)
|
||||
if oldschemav, has := jtree["schemaVersion"]; !has || !(oldschemav.(float64) > dashboard.HandoffSchemaVersion-1) {
|
||||
return nil
|
||||
}
|
||||
|
||||
m[path] = b
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
@@ -71,8 +71,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -178,8 +177,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -266,8 +264,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -354,8 +351,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -485,8 +481,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -573,8 +568,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -661,8 +655,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -792,8 +785,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -893,8 +885,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -982,8 +973,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -1069,8 +1059,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -1155,8 +1144,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -1253,8 +1241,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -1354,8 +1341,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -1455,8 +1441,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -1555,8 +1540,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -1692,8 +1676,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -1800,8 +1783,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -1909,8 +1891,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -2040,8 +2021,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -2128,8 +2108,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -2240,8 +2219,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -2356,8 +2334,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -2460,8 +2437,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -2564,8 +2540,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -2701,8 +2676,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -2838,8 +2812,7 @@
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
@@ -2934,7 +2907,7 @@
|
||||
}
|
||||
],
|
||||
"refresh": false,
|
||||
"schemaVersion": 32,
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [
|
||||
"gdev",
|
||||
@@ -2954,4 +2927,4 @@
|
||||
"uid": "1KxMUdE7k",
|
||||
"version": 1,
|
||||
"weekStart": ""
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2,6 +2,6 @@
|
||||
FROM golang:latest
|
||||
ADD main.go /
|
||||
WORKDIR /
|
||||
RUN go build -o main .
|
||||
RUN go mod init alert_webhook_listener && go build -o main .
|
||||
EXPOSE 3010
|
||||
ENTRYPOINT ["/main"]
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
alert_webhook_listener:
|
||||
build: docker/blocks/alert_webhook_listener
|
||||
network_mode: host
|
||||
ports:
|
||||
- "3010:3010"
|
||||
|
||||
@@ -509,6 +509,10 @@ If you want to track Grafana usage via Azure Application Insights, then specify
|
||||
|
||||
<hr />
|
||||
|
||||
### enable_feedback_links
|
||||
|
||||
If set to false will remove all feedback links from the UI. Defaults to true.
|
||||
|
||||
## [security]
|
||||
|
||||
### disable_initial_admin_creation
|
||||
|
||||
@@ -38,56 +38,37 @@ To access Prometheus settings, hover your mouse over the **Configuration** (gear
|
||||
|
||||
## Prometheus query editor
|
||||
|
||||
Below you can find information and options for Prometheus query editor in dashboard and in Explore.
|
||||
Prometheus query editor is separated into 3 distinct modes that you can switch between. See docs for each section below.
|
||||
|
||||
### Query editor in dashboards
|
||||

|
||||
|
||||
Open a graph in edit mode by clicking the title > Edit (or by pressing `e` key while hovering over panel).
|
||||
At the top of the editor there is `Run query` button that will run the query and `Explain | Builder | Code` tabs to switch between the editor modes. If the query editor is in Builder mode there are additional elements explained in the Builder section.
|
||||
|
||||
{{< figure src="/static/img/docs/v45/prometheus_query_editor_still.png"
|
||||
animated-gif="/static/img/docs/v45/prometheus_query_editor.gif" >}}
|
||||
Each mode is synchronized with the other modes, so you can switch between them without losing your work, although there are some limitations. Some more complex queries are not yet supported in the builder mode. If you try to switch from `Code` to `Builder` with such query, editor will show a popup explaining that you can lose some parts of the query, and you can decide if you still want to continue to `Builder` mode or not.
|
||||
|
||||
| Name | Description |
|
||||
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `Query expression` | Prometheus query expression. For more information, refer to the [Prometheus documentation](http://prometheus.io/docs/querying/basics/). |
|
||||
| `Legend format` | Controls the name of the time series, using name or pattern. For example, `{{hostname}}` is replaced by the label value for the label `hostname`. |
|
||||
| `Step` | Use 'Minimum' or 'Maximum' step mode to set the lower or upper bounds respectively on the interval between data points. For example, set "minimum 1h" to hint that measurements are not frequent (taken hourly). Use the 'Exact' step mode to set a precise interval between data points. `$__interval` and `$__rate_interval` are supported. |
|
||||
| `Resolution` | `1/1` sets both the `$__interval` variable and the [`step` parameter of Prometheus range queries](https://prometheus.io/docs/prometheus/latest/querying/api/#range-queries) such that each pixel corresponds to one data point. For better performance, you can pick lower resolutions. `1/2` only retrieves a data point for every other pixel, and `1/10` retrieves one data point per 10 pixels. Both _Min time interval_ and _Step_ limit the final value of `$__interval` and `step`. |
|
||||
| `Metric lookup` | Search for metric names in this input field. |
|
||||
| `Format as` | You can switch between `Table` `Time series` or `Heatmap` options. The `Table` option works only in the Table panel. `Heatmap` displays metrics of the Histogram type on a Heatmap panel. Under the hood, it converts cumulative histograms to regular ones and sorts series by the bucket bound. |
|
||||
| `Instant` | Perform an "instant" query to return only the latest value that Prometheus has scraped for the requested time series. Instant queries can return results much faster than normal range queries. Use them to look up label sets. |
|
||||
| `Min time interval` | This value multiplied by the denominator from the _Resolution_ setting sets a lower limit to both the `$__interval` variable and the [`step` parameter of Prometheus range queries](https://prometheus.io/docs/prometheus/latest/querying/api/#range-queries). Defaults to _Scrape interval_ as specified in the data source options. |
|
||||
| `Exemplars` | Run and show exemplars in the graph. |
|
||||
### Code mode
|
||||
|
||||
> **Note:** Grafana modifies the request dates for queries to align them with the dynamically calculated step. This ensures consistent display of metrics data, but it can result in a small gap of data at the right edge of a graph.
|
||||

|
||||
|
||||
#### Instant queries in dashboards
|
||||
Code mode allows you to write raw queries in a textual editor. It implements advanced autocomplete features and syntax highlighting to help with writing complex queries. In addition, it also contains `Metrics browser` to further aid with writing queries (see more docs below).
|
||||
|
||||
The Prometheus data source allows you to run "instant" queries, which query only the latest value.
|
||||
You can visualize the results in a table panel to see all available labels of a timeseries.
|
||||
For more information about Prometheus query language, refer to the [Prometheus documentation](http://prometheus.io/docs/querying/basics/).
|
||||
|
||||
Instant query results are made up only of one data point per series but can be shown in the graph panel with the help of [series overrides]({{< relref "../visualizations/graph-panel.md#series-overrides" >}}).
|
||||
To show them in the graph as a latest value point, add a series override and select `Points > true`.
|
||||
To show a horizontal line across the whole graph, add a series override and select `Transform > constant`.
|
||||
#### Autocomplete
|
||||
|
||||
> Support for constant series overrides is available from Grafana v6.4
|
||||

|
||||
|
||||
### Query editor in Explore
|
||||
Autocomplete kicks automatically in appropriate times during typing. Use `ctrl/cmd + space` to trigger autocomplete manually when needed. Autocomplete can suggest both static functions, aggregations and keywords but also dynamic items like metrics and labels. Autocomplete dropdown also shows documentation for the suggested items, either static one or dynamic metric documentation where available.
|
||||
|
||||
| Name | Description |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `Query expression` | Prometheus query expression, check out the [Prometheus documentation](http://prometheus.io/docs/querying/basics/). |
|
||||
| `Step` | [`Step` parameter of Prometheus range queries](https://prometheus.io/docs/prometheus/latest/querying/api/#range-queries). Time units can be used here, for example: 5s, 1m, 3h, 1d, 1y. Default unit if no unit specified is `s` (seconds). |
|
||||
| `Query type` | `Range`, `Instant`, or `Both`. When running **Range query**, the result of the query is displayed in graph and table. Instant query returns only the latest value that Prometheus has scraped for the requested time series and it is displayed in the table. When **Both** is selected, both instant query and range query is run. Result of range query is displayed in graph and the result of instant query is displayed in the table. |
|
||||
| `Exemplars` | Run and show exemplars in the graph. |
|
||||
In [Explore]({{< relref "../explore/_index.md" >}}) use `shift + enter` to run the query.
|
||||
|
||||
### Metrics browser
|
||||
#### Metrics browser
|
||||
|
||||
The metrics browser allows you to quickly find metrics and select relevant labels to build basic queries.
|
||||
When you open the browser you will see all available metrics and labels.
|
||||
If supported by your Prometheus instance, each metric will show its HELP and TYPE as a tooltip.
|
||||
|
||||
{{< figure src="/static/img/docs/v8/prometheus_metrics_browser.png" class="docs-image--no-shadow" max-width="800px" caption="Screenshot of the metrics browser for Prometheus" >}}
|
||||

|
||||
|
||||
When you select a metric, the browser narrows down the available labels to show only the ones applicable to the metric.
|
||||
You can then select one or more labels for which the available label values are shown in lists in the bottom section.
|
||||
@@ -95,14 +76,77 @@ Select one or more values for each label to tighten your query scope.
|
||||
|
||||
> **Note:** If you do not remember a metric name to start with, you can also select a few labels first, to narrow down the list and then find relevant label values.
|
||||
|
||||
All lists in the metrics browser have a search field above them to quickly filter for metrics or labels that match a certain string. The values section only has one search field. Its filtering applies to all labels to help you find values across labels once they have been selected, for example, among your labels `app`, `job`, `job_name` only one might with the value you are looking for.
|
||||
All lists in the metrics browser have a search field above them to quickly filter for metrics or labels that match a certain string. The values section only has one search field. It's filtering applies to all labels to help you find values across labels once they have been selected, for example, among your labels `app`, `job`, `job_name` only one might with the value you are looking for.
|
||||
|
||||
Once you are satisfied with your query, click "Use query" to run the query. The button "Use as rate query" adds a `rate(...)[$__interval]` around your query to help write queries for counter metrics.
|
||||
The "Validate selector" button will check with Prometheus how many time series are available for that selector.
|
||||
|
||||
#### Limitations
|
||||
#### Options
|
||||
|
||||
The metrics browser has a hard limit of 10,000 labels (keys) and 50,000 label values (including metric names). If your Prometheus instance returns more results, the browser will continue functioning. However, the result sets will be cut off above those maximum limits.
|
||||

|
||||
|
||||
| Name | Description |
|
||||
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `Legend` | Controls the name of the time series. Use predefined format or use custom format.<br/>`Auto` - only includes unique labels.<br/>`Verbose` - includes all labels.<br/>`Custom` - select will change to text input. Use use tamplating to select which labels will be included. For example, `{{hostname}}` is replaced by the label value for the label `hostname`. Clear the input and click outside the input to go back to select mode. |
|
||||
| `Min step` | Set the lower bounds on the interval between data points. For example, set "1h" to hint that measurements are not frequent (taken hourly). `$__interval` and `$__rate_interval` are supported. |
|
||||
| `Format` | You can switch between `Table` `Time series` or `Heatmap` options. The `Table` option works only in the Table panel. `Heatmap` displays metrics of the Histogram type on a Heatmap panel. Under the hood, it converts cumulative histograms to regular ones and sorts series by the bucket bound. |
|
||||
| `Type` | `Range` - Query returning a Range vector, a set of time series containing a range of data points over time for each time series.<br/>`Instant` - Perform an "instant" query to return only the latest value that Prometheus has scraped for the requested time series. Instant queries can return results much faster than normal range queries. Use them to look up label sets. Instant query results are made up only of one data point per series but can be shown in the graph panel in a dashboard with the help of [series overrides]({{< relref "../visualizations/graph-panel.md#series-overrides" >}}). To show them in the graph as a latest value point, add a series override and select `Points > true`. To show a horizontal line across the whole graph, add a series override and select `Transform > constant`. <br/>`Both` - Available only in Explore. Runs both range and instant query |
|
||||
| `Exemplars` | If on, run exemplars query with the regular query and show exemplars in the graph. |
|
||||
|
||||
> **Note:** Grafana modifies the request dates for queries to align them with the dynamically calculated step. This ensures consistent display of metrics data, but it can result in a small gap of data at the right edge of a graph.
|
||||
|
||||
### Builder mode
|
||||
|
||||
#### Toolbar
|
||||
|
||||
In addition to `Run query` button and mode switcher, in builder mode additional elements are available:
|
||||
|
||||
| Name | Description |
|
||||
| -------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Query patterns | A list of useful operation patterns that can be used to quickly add multiple operations to your query to achieve a specific goal. |
|
||||
| Raw query | Toggle to show raw query generated by the builder that will be sent to Prometheus instance. |
|
||||
|
||||
#### Metric and labels
|
||||
|
||||

|
||||
|
||||
Select a specific metric name from the dropdown list. List of available metrics is fetched from the Prometheus server based on selected time rage. Write into the select when the dropdown is open to search and filter the list.
|
||||
|
||||
Select desired labels and their values from the dropdown list. When metric is selected, available labels and their values are fetched from the server. Use the `+` button to add more labels. Use the `x` button to remove a label.
|
||||
|
||||
#### Operations
|
||||
|
||||

|
||||
|
||||
Use the `+ Operations` button to add operation to your query. Operations are grouped into sections for easier navigation. When the operations dropdown is open, write into the search input to search and filter operations list.
|
||||
|
||||
Operations in a query are shown as boxes in the operations section. Each has a header with a name and additional action buttons. Hover over the operation header to show the action buttons. Click the `v` button to quickly replace the operation with different one of the same type. Click the `info` button to open operations' description tooltip. Click the `x` button to remove the operation.
|
||||
|
||||
Operation can have additional parameters under the operation header. See the operation description or Prometheus docs for more details about each operation.
|
||||
|
||||
Some operations make sense only in specific order, if adding an operation would result in nonsensical query, operation will be added to the correct place. To order operations manually drag operation box by the operation name and drop in appropriate place.
|
||||
|
||||
##### Hints
|
||||
|
||||

|
||||
|
||||
In same cases the query editor can detect which operations would be most appropriate for a selected metric. In such cases it will show a hint next to the `+ Operations` button. Click on the hint to add the operations to your query.
|
||||
|
||||
#### Raw query
|
||||
|
||||

|
||||
|
||||
This section is shown only if the `Raw query` switch from the query editor top toolbar is set to `on`. It shows the raw query that will be created and executed by the query editor.
|
||||
|
||||
#### Options
|
||||
|
||||
Same set of option is available as in the `Code` mode. See the [Code mode options]({{< relref "#options" >}}) for details.
|
||||
|
||||
### Explain mode
|
||||
|
||||

|
||||
|
||||
Explain mode helps with understanding the query. It shows a step by step explanation of all query parts and the operations.
|
||||
|
||||
## Templating
|
||||
|
||||
|
||||
@@ -55,14 +55,6 @@ In split view, timepickers for both panels can be linked (if you change one, the
|
||||
|
||||
To close the newly created query, click on the Close Split button.
|
||||
|
||||
## Navigate between Explore and a dashboard
|
||||
|
||||
To help accelerate workflows that involve regularly switching from Explore to a dashboard and vice-versa, Grafana provides you with the ability to return to the origin dashboard after navigating to Explore from the panel's dropdown.
|
||||
|
||||
After you've navigated to Explore, you should notice a "Back" button in the Explore toolbar. Simply click it to return to the origin dashboard. To bring changes you make in Explore back to the dashboard, click the arrow next to the button to reveal a "Return to panel with changes" menu item.
|
||||
|
||||
{{< figure src="/static/img/docs/explore/explore_return_dropdown-7-4.png" class="docs-image--no-shadow" max-width= "400px" caption="Screenshot of the expanded explore return dropdown" >}}
|
||||
|
||||
## Share shortened link
|
||||
|
||||
> **Note:** Available in Grafana 7.3 and later versions.
|
||||
|
||||
@@ -16,6 +16,8 @@ You can install and run Grafana using the official Docker images. Our docker ima
|
||||
|
||||
Each edition is available in two variants: Alpine and Ubuntu. See below.
|
||||
|
||||
For documentation regarding the configuration of a docker image, refer to [configure a Grafana Docker image](https://grafana.com/docs/grafana/latest/administration/configure-docker/).
|
||||
|
||||
This topic also contains important information about [migrating from earlier Docker image versions](#migrate-from-previous-docker-containers-versions).
|
||||
|
||||
> **Note:** You can use [Grafana Cloud](https://grafana.com/products/cloud/features/#cloud-logs) to avoid the overhead of installing, maintaining, and scaling your observability stack. The free forever plan includes Grafana, 10K Prometheus series, 50 GB logs, and more.[Create a free account to get started](https://grafana.com/auth/sign-up/create-user?pg=docs-grafana-install&plcmt=in-text).
|
||||
|
||||
@@ -14,14 +14,14 @@ replace k8s.io/client-go => k8s.io/client-go v0.22.1
|
||||
replace github.com/russellhaering/goxmldsig@v1.1.0 => github.com/russellhaering/goxmldsig v1.1.1
|
||||
|
||||
require (
|
||||
cloud.google.com/go/storage v1.18.2
|
||||
cuelang.org/go v0.4.0
|
||||
cloud.google.com/go/storage v1.21.0
|
||||
cuelang.org/go v0.4.1
|
||||
github.com/Azure/azure-sdk-for-go v59.3.0+incompatible
|
||||
github.com/Azure/go-autorest/autorest v0.11.22
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f
|
||||
github.com/aws/aws-sdk-go v1.42.8
|
||||
github.com/aws/aws-sdk-go v1.43.31
|
||||
github.com/beevik/etree v1.1.0
|
||||
github.com/benbjohnson/clock v1.1.0
|
||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
|
||||
@@ -29,9 +29,9 @@ require (
|
||||
github.com/cortexproject/cortex v1.10.1-0.20211014125347-85c378182d0d
|
||||
github.com/crewjam/saml v0.4.6-0.20210521115923-29c6295245bd
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/denisenkom/go-mssqldb v0.11.0
|
||||
github.com/denisenkom/go-mssqldb v0.12.0
|
||||
github.com/dop251/goja v0.0.0-20210804101310-32956a348b49
|
||||
github.com/fatih/color v1.10.0
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/gchaincl/sqlhooks v1.3.0
|
||||
github.com/getsentry/sentry-go v0.10.0
|
||||
github.com/go-kit/kit v0.11.0 // indirect
|
||||
@@ -56,7 +56,7 @@ require (
|
||||
github.com/grafana/grafana-plugin-sdk-go v0.131.0
|
||||
github.com/grafana/loki v1.6.2-0.20211015002020-7832783b1caa
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
github.com/hashicorp/go-hclog v0.16.1
|
||||
github.com/hashicorp/go-hclog v1.0.0
|
||||
github.com/hashicorp/go-plugin v1.4.3
|
||||
github.com/hashicorp/go-version v1.3.0
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.6.0
|
||||
@@ -69,7 +69,7 @@ require (
|
||||
github.com/linkedin/goavro/v2 v2.10.0
|
||||
github.com/m3db/prometheus_remote_client_golang v0.4.4
|
||||
github.com/magefile/mage v1.12.1
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/mattn/go-isatty v0.0.14
|
||||
github.com/mattn/go-sqlite3 v1.14.7
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
|
||||
@@ -93,7 +93,7 @@ require (
|
||||
github.com/unknwon/com v1.0.1
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/vectordotdev/go-datemath v0.1.1-0.20220323213446-f3954d0b18ae
|
||||
github.com/weaveworks/common v0.0.0-20210913144402-035033b78a78
|
||||
github.com/weaveworks/common v0.0.0-20210913144402-035033b78a78 // indirect
|
||||
github.com/xorcare/pointer v1.1.0
|
||||
github.com/yudai/gojsondiff v1.0.0
|
||||
go.opentelemetry.io/collector v0.31.0
|
||||
@@ -102,19 +102,19 @@ require (
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.0.0
|
||||
go.opentelemetry.io/otel/sdk v1.0.0
|
||||
go.opentelemetry.io/otel/trace v1.6.3
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
|
||||
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29
|
||||
golang.org/x/exp v0.0.0-20210220032938-85be41e4509f
|
||||
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||
golang.org/x/net v0.0.0-20220401154927-543a649e0bdd // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
|
||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65
|
||||
golang.org/x/tools v0.1.9
|
||||
gonum.org/v1/gonum v0.11.0
|
||||
google.golang.org/api v0.60.0
|
||||
google.golang.org/grpc v1.42.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
google.golang.org/api v0.74.0
|
||||
google.golang.org/grpc v1.45.0
|
||||
google.golang.org/protobuf v1.28.0
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/ini.v1 v1.62.0
|
||||
gopkg.in/ini.v1 v1.66.2
|
||||
gopkg.in/ldap.v3 v3.1.0
|
||||
gopkg.in/mail.v2 v2.3.1
|
||||
gopkg.in/square/go-jose.v2 v2.5.1
|
||||
@@ -126,7 +126,6 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.97.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.9.1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
@@ -141,7 +140,6 @@ require (
|
||||
github.com/alecthomas/units v0.0.0-20210912230133-d1bdfacee922 // indirect
|
||||
github.com/andybalholm/brotli v1.0.3
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 // indirect
|
||||
github.com/armon/go-metrics v0.3.8 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
@@ -151,7 +149,6 @@ require (
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
||||
github.com/dennwc/varint v1.0.0 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
@@ -174,7 +171,7 @@ require (
|
||||
github.com/go-openapi/validate v0.20.2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/status v1.1.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
@@ -182,17 +179,15 @@ require (
|
||||
github.com/gomodule/redigo v2.0.0+incompatible // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/flatbuffers v2.0.0+incompatible // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.1.1
|
||||
github.com/googleapis/gax-go/v2 v2.2.0
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/grafana/grafana-google-sdk-go v0.0.0-20211104130251-b190293eaf58
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.0 // indirect
|
||||
github.com/hashicorp/go-msgpack v0.5.5 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.0 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/hashicorp/memberlist v0.2.4 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493 // indirect
|
||||
github.com/igm/sockjs-go/v3 v3.0.1 // indirect
|
||||
github.com/jessevdk/go-flags v1.5.0 // indirect
|
||||
@@ -202,11 +197,9 @@ require (
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
|
||||
github.com/mattetti/filebuffer v1.0.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/miekg/dns v1.1.43 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
||||
github.com/mna/redisc v1.3.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
@@ -224,13 +217,11 @@ require (
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20201118171849-f6a6b3f636fc // indirect
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect
|
||||
github.com/rs/cors v1.8.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
|
||||
github.com/segmentio/encoding v0.3.2
|
||||
github.com/sercand/kuberesolver v2.4.0+incompatible // indirect
|
||||
github.com/sergi/go-diff v1.0.0 // indirect
|
||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/stretchr/objx v0.2.0 // indirect
|
||||
@@ -241,44 +232,53 @@ require (
|
||||
go.mongodb.org/mongo-driver v1.7.0 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
go.uber.org/atomic v1.9.0
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 // indirect
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
|
||||
go.uber.org/goleak v1.1.11 // indirect
|
||||
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1
|
||||
google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de
|
||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/kms v1.1.0
|
||||
cloud.google.com/go/kms v1.4.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.13.2
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.4.0
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.17
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0
|
||||
github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f
|
||||
gocloud.dev v0.24.0
|
||||
github.com/grafana/thema v0.0.0-20220413232647-fc54c169b508
|
||||
gocloud.dev v0.25.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.100.2 // indirect
|
||||
github.com/armon/go-metrics v0.3.10 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/memberlist v0.3.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.5.0 // indirect
|
||||
cloud.google.com/go/iam v0.3.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.22.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.2.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 // indirect
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
|
||||
github.com/chromedp/cdproto v0.0.0-20220208224320-6efb837e6bc2 // indirect
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect
|
||||
github.com/containerd/containerd v1.5.9 // indirect
|
||||
github.com/elazarl/goproxy v0.0.0-20220115173737-adb46da277ac // indirect
|
||||
github.com/envoyproxy/go-control-plane v0.10.1 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
|
||||
github.com/getkin/kin-openapi v0.94.0 // indirect
|
||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/klauspost/compress v1.15.1 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.8 // indirect
|
||||
@@ -292,6 +292,7 @@ replace github.com/apache/thrift => github.com/apache/thrift v0.14.1
|
||||
|
||||
replace github.com/hashicorp/consul => github.com/hashicorp/consul v1.10.2
|
||||
|
||||
// TODO: remove once gocloud.dev releases 0.25.x
|
||||
// `fileblob` implementation has buggy key ordering in 0.24.0
|
||||
replace gocloud.dev v0.24.0 => github.com/google/go-cloud v0.24.1-0.20220209172924-99801bbb523a
|
||||
// Thema's thema CLI requires cobra, which eventually works its way down to go-hclog@v1.0.0.
|
||||
// Upgrading affects backend plugins: https://github.com/grafana/grafana/pull/47653#discussion_r850508593
|
||||
// No harm to Thema because it's only a dependency in its main package.
|
||||
replace github.com/hashicorp/go-hclog => github.com/hashicorp/go-hclog v0.16.1
|
||||
|
||||
@@ -30,8 +30,12 @@ cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWc
|
||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||
cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8=
|
||||
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||
cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM=
|
||||
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
|
||||
cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U=
|
||||
cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
|
||||
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
@@ -41,29 +45,41 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7
|
||||
cloud.google.com/go/bigtable v1.1.0/go.mod h1:B6ByKcIdYmhoyDzmOnQxyOhN6r05qnewYIxxG6L0/b4=
|
||||
cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o=
|
||||
cloud.google.com/go/bigtable v1.3.0/go.mod h1:z5EyKrPE8OQmeg4h5MNdKvuSnI9CCT49Ki3f23aBzio=
|
||||
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||
cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw=
|
||||
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
|
||||
cloud.google.com/go/compute v1.5.0 h1:b1zWmYuuHz7gO9kDcM/EpHGr06UgsYNRpNJzI2kFiLM=
|
||||
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
|
||||
cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c=
|
||||
cloud.google.com/go/iam v0.1.1/go.mod h1:CKqrcnI/suGpybEHxZ7BMehL0oA4LpdyJdUlTl9jVMw=
|
||||
cloud.google.com/go/iam v0.3.0 h1:exkAomrVUuzx9kWFI1wm3KI0uoDeUFPB4kKGzx6x+Gc=
|
||||
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
|
||||
cloud.google.com/go/kms v1.0.0/go.mod h1:nhUehi+w7zht2XrUfvTRNpxrfayBHqP4lu2NSywui/0=
|
||||
cloud.google.com/go/kms v1.1.0 h1:1yc4rLqCkVDS9Zvc7m+3mJ47kw0Uo5Q5+sMjcmUVUeM=
|
||||
cloud.google.com/go/kms v1.1.0/go.mod h1:WdbppnCDMDpOvoYBMn1+gNmOeEoZYqAv+HeuKARGCXI=
|
||||
cloud.google.com/go/kms v1.4.0 h1:iElbfoE61VeLhnZcGOltqL8HIly8Nhbe5t6JlH9GXjo=
|
||||
cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA=
|
||||
cloud.google.com/go/monitoring v1.1.0/go.mod h1:L81pzz7HKn14QCMaCs6NTQkdBnE87TElyanS95vIcl4=
|
||||
cloud.google.com/go/monitoring v1.4.0/go.mod h1:y6xnxfwI3hTFWOdkOaD7nfJVlwuC3/mS/5kvtT131p4=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/pubsub v1.17.1/go.mod h1:4qDxMr1WsM9+aQAz36ltDwCIM+R0QdlseyFjBuNvnss=
|
||||
cloud.google.com/go/secretmanager v1.0.0/go.mod h1:+Qkm5qxIJ5mk74xxIXA+87fseaY1JLYBcFPQoc/GQxg=
|
||||
cloud.google.com/go/pubsub v1.19.0/go.mod h1:/O9kmSe9bb9KRnIAWkzmqhPjHo6LtzGOBYd/kr06XSs=
|
||||
cloud.google.com/go/secretmanager v1.3.0/go.mod h1:+oLTkouyiYiabAQNugCeTS3PAArGiMJuBqvJnJsyH+U=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.3.0/go.mod h1:9IAwXhoyBJ7z9LcAwkj0/7NnPzYaPeZxxVp3zm+5IqA=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.18.2 h1:5NQw6tOn3eMm0oE8vTkfjau18kjL79FlMjy/CHTpmoY=
|
||||
cloud.google.com/go/storage v1.18.2/go.mod h1:AiIj7BWXyhO5gGVmYJ+S8tbkCx3yb0IMjua8Aw4naVM=
|
||||
cloud.google.com/go/storage v1.21.0 h1:HwnT2u2D309SFDHQII6m18HlrCi3jAXhUMTLOWXYH14=
|
||||
cloud.google.com/go/storage v1.21.0/go.mod h1:XmRlxkgPjlBONznT2dDUU/5XlpU2OjMnKuqnZI01LAA=
|
||||
cloud.google.com/go/trace v1.0.0/go.mod h1:4iErSByzxkyHWzzlAj63/Gmjz0NH1ASqhJguHpGcr6A=
|
||||
cloud.google.com/go/trace v1.2.0/go.mod h1:Wc8y/uYyOhPy12KEnXG9XGrvfMz5F5SrYecQlbW1rwM=
|
||||
code.cloudfoundry.org/clock v1.0.0/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8=
|
||||
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
|
||||
contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
|
||||
@@ -71,8 +87,9 @@ contrib.go.opencensus.io/exporter/ocagent v0.6.0/go.mod h1:zmKjrJcdo0aYcVS7bmEeS
|
||||
contrib.go.opencensus.io/exporter/prometheus v0.3.0/go.mod h1:rpCPVQKhiyH8oomWgm34ZmgIdZa8OVYO5WAIygPbBBE=
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.13.10/go.mod h1:I5htMbyta491eUxufwwZPQdcKvvgzMB4O9ni41YnIM8=
|
||||
contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
|
||||
cuelang.org/go v0.4.0 h1:GLJblw6m2WGGCA3k1v6Wbk9gTOt2qto48ahO2MmSd6I=
|
||||
cuelang.org/go v0.4.0/go.mod h1:tz/edkPi+T37AZcb5GlPY+WJkL6KiDlDVupKwL3vvjs=
|
||||
cuelang.org/go v0.4.1 h1:rxG2cyZzdAymrNICI0L/wagK2EitoR8Xsiiq2D7qkaQ=
|
||||
cuelang.org/go v0.4.1/go.mod h1:P09/R4UfAEzLkV9DXxwlxQnIZbkaT4uIhiEgs6Vsz2Q=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
||||
@@ -172,7 +189,6 @@ github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVF
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.9/go.mod h1:hg3/1yw0Bq87O3KvvnJoAh34/0zbP7SFizX/qN5JvjU=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
|
||||
github.com/Azure/go-autorest/autorest/azure/cli v0.4.4/go.mod h1:yAQ2b6eP/CmLPnmLvxtT1ALIY3OR1oFcCqVBi8vHiTc=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||
@@ -215,7 +231,7 @@ github.com/FZambia/eagle v0.0.1 h1:FN1yTkPihMb5nE8SrlRjoCf7T9H9bTKJFQOm6ach2YU=
|
||||
github.com/FZambia/eagle v0.0.1/go.mod h1:xq6u/JeNZ5/8mrAQ76MMhzNTodASh9FavQlCgg4j48w=
|
||||
github.com/FZambia/sentinel v1.1.0 h1:qrCBfxc8SvJihYNjBWgwUI93ZCvFe/PJIPTHKmlp8a8=
|
||||
github.com/FZambia/sentinel v1.1.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI=
|
||||
github.com/GoogleCloudPlatform/cloudsql-proxy v1.27.0/go.mod h1:bn9iHmAjogMoIPkqBGyJ9R1m9cXGCjBE/cuhBs3oEsQ=
|
||||
github.com/GoogleCloudPlatform/cloudsql-proxy v1.29.0/go.mod h1:spvB9eLJH9dutlbPSRmHvSXXHOwGRyeXh1jVdquA2G8=
|
||||
github.com/HdrHistogram/hdrhistogram-go v0.9.0/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.0.1/go.mod h1:BWJ+nMSHY3L41Zj7CA3uXnloDp7xxV0YvstAE7nKTaM=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.0 h1:6dpdDPTRoo78HxAJ6T1HfMiKSnqhgRRqzCuPshRkQ7I=
|
||||
@@ -327,8 +343,9 @@ github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQh
|
||||
github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs=
|
||||
github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-metrics v0.3.8 h1:oOxq3KPj0WhCuy50EhzwiyMyG2ovRQZpZLXQuOh2a/M=
|
||||
github.com/armon/go-metrics v0.3.8/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo=
|
||||
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
@@ -369,49 +386,51 @@ github.com/aws/aws-sdk-go v1.38.60/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2z
|
||||
github.com/aws/aws-sdk-go v1.38.68/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/aws/aws-sdk-go v1.40.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
github.com/aws/aws-sdk-go v1.40.37/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
github.com/aws/aws-sdk-go v1.42.8 h1:Tj2RP4Fas1mYchwbmw0qWLJIEATAseyp5iTa1D+LWYQ=
|
||||
github.com/aws/aws-sdk-go v1.42.8/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
github.com/aws/aws-sdk-go v1.43.31 h1:yJZIr8nMV1hXjAvvOLUFqZRJcHV7udPQBfhJqawDzI0=
|
||||
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/aws/aws-sdk-go-v2 v1.7.0/go.mod h1:tb9wi5s61kTDA5qCkcDbt3KRVV74GGslQkl/DRdX/P4=
|
||||
github.com/aws/aws-sdk-go-v2 v1.11.0 h1:HxyD62DyNhCfiFGUHqJ/xITD6rAjJ7Dm/2nLxLmO4Ag=
|
||||
github.com/aws/aws-sdk-go-v2 v1.11.0/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 h1:yVUAwvJC/0WNPbyl0nA3j1L6CW1CN8wBubCRqtG7JLI=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0/go.mod h1:Xn6sxgRuIDflLRJFj5Ev7UxABIkNbccFPV/p8itDReM=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.10.1 h1:z/ViqIjW6ZeuLWgTWMTSyZzaVWo/1cWeVf1Uu+RF01E=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.10.1/go.mod h1:auIv5pIIn3jIBHNRcVQcsczn6Pfa6Dyv80Fai0ueoJU=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.6.1 h1:A39JYth2fFCx+omN/gib/jIppx3rRnt2r7UKPq7Mh5Y=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.6.1/go.mod h1:QyvQk1IYTqBWSi1T6UgT/W8DMxBVa5pVuLFSRLLhGf8=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.0 h1:OpZjuUy8Jt3CA1WgJgBC5Bz+uOjE5Ppx4NFTRaooUuA=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.0/go.mod h1:5E1J3/TTYy6z909QNR0QnXGBpfESYGDqd3O0zqONghU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.1 h1:p9Dys1g2YdaqMalnp6AwCA+tpMMdJNGw5YYKP/u3sUk=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.1/go.mod h1:wN/mvkow08GauDwJ70jnzJ1e+hE+Q3Q7TwpYLXOe9oI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0 h1:zY8cNmbBXt3pzjgWgdIbzpQ6qxoCwt+Nx9JbrAf2mbY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0/go.mod h1:NO3Q5ZTTQtO2xIg2+xTXYDiT7knSejfeDm7WGDaOo0U=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0 h1:Z3aR/OXBnkYK9zXkNkfitHX6SmUBzSsx8VMHbH4Lvhw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0/go.mod h1:anlUzBoEWglcUxUQwZA7HQOEVEnQALVZsizAapB2hq8=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.0 h1:c10Z7fWxtJCoyc8rv06jdh9xrKnu7bAJiRaKWvTb2mU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.0/go.mod h1:6oXGy4GLpypD3uCh8wcqztigGgmhLToMfjavgh+VySg=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.2 h1:fqlCk6Iy3bnCumtrLz9r3mJ/2gUT0pJ0wLFVIdWh+JA=
|
||||
github.com/aws/aws-sdk-go-v2 v1.16.2/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1 h1:SdK4Ppk5IzLs64ZMvr6MrSficMtjY2oS0WOORXTlxwU=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.1/go.mod h1:n8Bs1ElDD2wJ9kCRTczA83gYbBmjSwZp3umc6zF4EeM=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.3 h1:5AlQD0jhVXlGzwo+VORKiUuogkG7pQcLJNzIzK7eodw=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.15.3/go.mod h1:9YL3v07Xc/ohTsxFXzan9ZpFpdTOFl4X65BAKYaz8jg=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.11.2 h1:RQQ5fzclAKJyY5TvF+fkjJEwzK4hnxQCLOu5JXzDmQo=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.11.2/go.mod h1:j8YsY9TXTm31k4eFhspiQicfXPLZ0gYXA50i4gxPE8g=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.3 h1:LWPg5zjHV9oz/myQr4wMs0gi4CjnDN/ILmyZUFYXZsU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.3/go.mod h1:uk1vhHHERfSVCUnqSqz8O48LBYDSC+k6brng09jcMOk=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.3 h1:ir7iEq78s4txFGgwcLqD6q9IIPzTQNRJXulJd9h/zQo=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.3/go.mod h1:0dHuD2HZZSiwfJSy1FO5bX1hQ1TxVV1QXXjpn3XUE44=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.9 h1:onz/VaaxZ7Z4V+WIN9Txly9XLTmoOh1oJ8XcAC3pako=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.9/go.mod h1:AnVH5pvai0pAF4lXRq0bmhbes1u9R8wTE+g+183bZNM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.3 h1:9stUQR/u2KXU6HkFJYlqnZEjBnbgrVbG6I5HN09xZh0=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.3/go.mod h1:ssOhaLpRlh88H3UmEcsBoVKq309quMvm3Ds8e9d4eJM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.10 h1:by9P+oy3P/CwggN4ClnW2D4oL91QV7pBzBICi1chZvQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.10/go.mod h1:8DcYQcz0+ZJaSxANlHIsbbi6S+zMwjwdDqwW3r9AzaE=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.5.0/go.mod h1:acH3+MQoiMzozT/ivU+DbRg7Ooo2298RdRaWcOv+4vM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0 h1:lPLbw4Gn59uoKqvOfSnkJr54XWk5Ak1NK20ZEiSWb3U=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0/go.mod h1:80NaCIH9YU3rzTTs/J/ECATjXuRqzo/wB6ukO6MZ0XY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.0 h1:qGZWS/WgiFY+Zgad2u0gwBHpJxz6Ne401JE7iQI1nKs=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.0/go.mod h1:Mq6AEc+oEjCUlBuLiK5YwW4shSOAKCQ3tXN0sQeYoBA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.0 h1:0BOlTqnNnrEO04oYKzDxMMe68t107pmIotn18HtVonY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.0/go.mod h1:xKCZ4YFSF2s4Hnb/J0TLeOsKuGzICzcElaOKNGrVnx4=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.10.0/go.mod h1:ZkHWL8m5Nw1g9yMXqpCjnIJtSDToAmNbXXZ9gj0bO7s=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.19.0 h1:5mRAms4TjSTOGYsqKYte5kHr1PzpMJSyLThjF3J+hw0=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.19.0/go.mod h1:Gwz3aVctJe6mUY9T//bcALArPUaFmNAy2rTB9qN4No8=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.10.0/go.mod h1:qAgsrzF3Z2vvV01j79fs7D75ofCMQe81/OKBJx0rjFY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sns v1.11.0/go.mod h1:LIPf3BTbSY5UeVli+x/1y2Qw1w8T9DYyp7p18Qt8Zc8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sqs v1.12.0/go.mod h1:TDqDmQnsbgL2ZMIGUf3z9xTzCMqFX7FP1geAgIlYqvA=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.15.0/go.mod h1:kJa2uHklY03rKsNSbEsToeUgWJ1PambXBtRNacorRhg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.6.0 h1:JDgKIUZOmLFu/Rv6zXLrVTWCmzA0jcTdvsT8iFIKrAI=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.6.0/go.mod h1:Q/l0ON1annSU+mc0JybDy1Gy6dnJxIcWjphO6qJPzvM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.10.0 h1:1jh8J+JjYRp+QWKOsaZt7rGUgoyrqiiVwIm+w0ymeUw=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.10.0/go.mod h1:jLKCFqS+1T4i7HDqCP9GM4Uk75YW1cS0o82LdxpMyOE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1 h1:T4pFel53bkHjL2mMo+4DKE6r6AuoZnM0fg7k1/ratr4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.1/go.mod h1:GeUru+8VzrTXV/83XyMJ80KpH8xO89VPoUileyNQ+tc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.3 h1:I0dcwWitE752hVSMrsLCxqNQ+UdEp3nACx2bYNMQq+k=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.3/go.mod h1:Seb8KNmD6kVTjwRjVEgOT5hPin6sq+v4C2ycJQDwuH8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.3 h1:Gh1Gpyh01Yvn7ilO/b/hr01WgNpaszfbKMUgqM186xQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.3/go.mod h1:wlY6SVjuwvh3TVRpTqdy4I1JpBFLX4UGeKZdWntaocw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.3 h1:BKjwCJPnANbkwQ8vzSbaZDKawwagDubrH/z/c0X+kbQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.3/go.mod h1:Bm/v2IaN6rZ+Op7zX+bOUMdL4fsrYZiD0dsjLhNKwZc=
|
||||
github.com/aws/aws-sdk-go-v2/service/kms v1.16.3/go.mod h1:QuiHPBqlOFCi4LqdSskYYAWpQlx3PKmohy+rE2F+o5g=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.3 h1:rMPtwA7zzkSQZhhz9U3/SoIDz/NZ7Q+iRn4EIO8rSyU=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.26.3/go.mod h1:g1qvDuRsJY+XghsV6zg00Z4KJ7DtFFCx8fJD2a491Ak=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.15.4/go.mod h1:PJc8s+lxyU8rrre0/4a0pn2wgwiDvOEzoOjcJUBr67o=
|
||||
github.com/aws/aws-sdk-go-v2/service/sns v1.17.4/go.mod h1:kElt+uCcXxcqFyc+bQqZPFD9DME/eC6oHBXvFzQ9Bcw=
|
||||
github.com/aws/aws-sdk-go-v2/service/sqs v1.18.3/go.mod h1:skmQo0UPvsjsuYYSYMVmrPc1HWCbHUJyrCEp+ZaLzqM=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.24.1/go.mod h1:NR/xoKjdbRJ+qx0pMR4mI+N/H1I1ynHwXnO6FowXJc0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.3 h1:frW4ikGcxfAEDfmQqWgMLp+F1n4nRo9sF39OcIb5BkQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.11.3/go.mod h1:7UQ/e69kU7LDPtY40OyoHYgRmgfGM4mgsLYtcObdveU=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.3 h1:cJGRyzCSVwZC7zZZ1xbx9m32UnrKydRYhOvcD1NYP9Q=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.16.3/go.mod h1:bfBj0iVmsUyUg4weDB4NxktD9rDGeKSVWnjTnwbx9b8=
|
||||
github.com/aws/smithy-go v1.5.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
github.com/aws/smithy-go v1.9.0 h1:c7FUdEqrQA1/UVKKCNDFQPNKGp4FQg3YW4Ck5SLTG58=
|
||||
github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
github.com/aws/smithy-go v1.11.2 h1:eG/N+CcUMAvsdffgMvjMKwfyDzIkjM6pfxMJ8Mzc6mE=
|
||||
github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM=
|
||||
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
|
||||
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
|
||||
@@ -472,7 +491,6 @@ github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq
|
||||
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/centrifugal/centrifuge v0.19.0 h1:YHws0dRpgsBiI73tRl1wwaB13gzuaI1AM4IFcQQQqcw=
|
||||
github.com/centrifugal/centrifuge v0.19.0/go.mod h1:O2elf8q3Qkie3z97wkqVqxB52pnOpPsfFUa7L88Lpy0=
|
||||
@@ -513,14 +531,14 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
|
||||
github.com/cncf/udpa/go v0.0.0-20200313221541-5f7e5dd04533/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 h1:KwaoQzs/WeUxxJqiJsZ4euOly1Az/IgZXXSxlD/UBNk=
|
||||
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cockroachdb/apd/v2 v2.0.1/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw=
|
||||
@@ -638,6 +656,7 @@ github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
@@ -662,8 +681,9 @@ github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFl
|
||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
@@ -832,8 +852,8 @@ github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW
|
||||
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/fatih/structtag v1.1.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||
@@ -1157,9 +1177,9 @@ github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0 h1:gONcHxHApDTKXDyLH/H97gEHmpu1zcnnbAaq2zgrPrs=
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
@@ -1229,8 +1249,6 @@ github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv
|
||||
github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v2.0.0+incompatible h1:dicJ2oXwypfwUGnB2/TYWYEKiuk9eYQlQO/AnOHl5mI=
|
||||
github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/go-cloud v0.24.1-0.20220209172924-99801bbb523a h1:Kw18HR30Firrm4cB1BzcVVaFrrdDlAtnrCKgHxemgMI=
|
||||
github.com/google/go-cloud v0.24.1-0.20220209172924-99801bbb523a/go.mod h1:TqAL9Q5Q8jFUfIDNbDiFbU3w0z3MQ7q4r1wm57tBhmI=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
@@ -1251,7 +1269,7 @@ github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:od
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk=
|
||||
github.com/google/go-replayers/httpreplay v1.0.0/go.mod h1:LJhKoTwS5Wy5Ld/peq8dFFG5OfJyHEz7ft+DsTUv25M=
|
||||
github.com/google/go-replayers/httpreplay v1.1.1/go.mod h1:gN9GeLIs7l6NUoVaSSnv2RiqK1NiwAmD0MrKeC9IIks=
|
||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@@ -1262,8 +1280,9 @@ github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:x
|
||||
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ=
|
||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
|
||||
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
@@ -1290,6 +1309,7 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210827144239-02619b876842/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2/go.mod h1:DavVbd41y+b7ukKDmlnPR4nGYmkWXR6vHUkjQNiHPBs=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@@ -1306,8 +1326,9 @@ github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU=
|
||||
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
|
||||
github.com/googleapis/gax-go/v2 v2.2.0 h1:s7jOdKSaksJVOxE0Y/S32otcfiP+UQ0cL8/GTKaONwE=
|
||||
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
|
||||
github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
@@ -1379,6 +1400,8 @@ github.com/grafana/loki v1.6.2-0.20211015002020-7832783b1caa/go.mod h1:0O8o/juxN
|
||||
github.com/grafana/saml v0.0.0-20211007135653-aed1b2edd86b h1:YiSGp34F4V0G08HHx1cJBf2GVgwYAkXQjzuVs1t8jYk=
|
||||
github.com/grafana/saml v0.0.0-20211007135653-aed1b2edd86b/go.mod h1:q83kyQoMD0vhy+RzFLlbw0UgHJ6TAihQpuXvdFmm4s4=
|
||||
github.com/grafana/sqlds/v2 v2.3.2/go.mod h1:34uyqPBWsEvg4V/xxh6V4uIqwu1qLfOfsmScll/ukrk=
|
||||
github.com/grafana/thema v0.0.0-20220413232647-fc54c169b508 h1:6k0scTj6kRDjn/qLigsLc9OTiMMaWkRUxjKBFowWEWg=
|
||||
github.com/grafana/thema v0.0.0-20220413232647-fc54c169b508/go.mod h1:KuqTKX9lfM87uu9vt9DS/q+REqSrAm2xYMnBBvlmevA=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
@@ -1417,8 +1440,9 @@ github.com/hashicorp/consul/api v1.7.0/go.mod h1:1NSuaUUkFaJzMasbfq/11wKYWSR67Xn
|
||||
github.com/hashicorp/consul/api v1.8.1/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk=
|
||||
github.com/hashicorp/consul/api v1.9.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
||||
github.com/hashicorp/consul/api v1.10.0/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk=
|
||||
github.com/hashicorp/consul/api v1.10.1 h1:MwZJp86nlnL+6+W1Zly4JUuVn9YHhMggBirMpHGD7kw=
|
||||
github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
||||
github.com/hashicorp/consul/api v1.11.0 h1:Hw/G8TtRvOElqxVIhBzXciiSTbapq8hZ2XKZsXk5ZCE=
|
||||
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/consul/sdk v0.4.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM=
|
||||
@@ -1432,24 +1456,19 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
|
||||
github.com/hashicorp/go-bexpr v0.1.2/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU=
|
||||
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-connlimit v0.3.0/go.mod h1:OUj9FGL1tPIhl/2RCfzYHrIiWj+VVPGNyVPnUX8AqS0=
|
||||
github.com/hashicorp/go-discover v0.0.0-20200501174627-ad1e96bde088/go.mod h1:vZu6Opqf49xX5lsFAu7iFNewkcVF1sn/wyapZh5ytlg=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v0.12.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o=
|
||||
github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.2.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g=
|
||||
github.com/hashicorp/go-memdb v1.3.1/go.mod h1:Mluclgwib3R93Hk5fxEfiRhB+6Dar64wWh71LpNSe3g=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
@@ -1505,8 +1524,9 @@ github.com/hashicorp/memberlist v0.1.5/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
||||
github.com/hashicorp/memberlist v0.2.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/memberlist v0.2.3/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/memberlist v0.2.4 h1:OOhYzSvFnkFQXm1ysE8RjXTHsqSRDyP4emusC9K7DYg=
|
||||
github.com/hashicorp/memberlist v0.2.4/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA=
|
||||
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||
github.com/hashicorp/net-rpc-msgpackrpc v0.0.0-20151116020338-a14192a58a69/go.mod h1:/z+jUGRBlwVpUZfjute9jWaF6/HuhjuFQuL1YXzVD1Q=
|
||||
github.com/hashicorp/raft v1.1.1/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
|
||||
github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8=
|
||||
@@ -1519,8 +1539,9 @@ github.com/hashicorp/serf v0.8.3/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc
|
||||
github.com/hashicorp/serf v0.8.5/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc1oal+k=
|
||||
github.com/hashicorp/serf v0.9.0/go.mod h1:YL0HO+FifKOW2u1ke99DGVu1zhcpZzNwrLIqBC7vbYU=
|
||||
github.com/hashicorp/serf v0.9.3/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
||||
github.com/hashicorp/serf v0.9.5 h1:EBWvyu9tcRszt3Bxp3KNssBMP1KuHWyO51lz9+786iM=
|
||||
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
||||
github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc=
|
||||
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
|
||||
github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
|
||||
github.com/hashicorp/vault/api v1.0.5-0.20200717191844-f687267c8086/go.mod h1:R3Umvhlxi2TN7Ex2hzOowyeNb+SfbVWI973N+ctaFMk=
|
||||
github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
|
||||
@@ -1605,10 +1626,48 @@ github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7Ua
|
||||
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
|
||||
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
|
||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
|
||||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
|
||||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
|
||||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
|
||||
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
|
||||
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
|
||||
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
|
||||
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
|
||||
github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
|
||||
github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
|
||||
github.com/jackc/pgx v3.6.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
||||
github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jaegertracing/jaeger v1.24.0/go.mod h1:mqdtFDA447va5j0UewDaAWyNlGreGQyhGxXVhbF58gQ=
|
||||
github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||
@@ -1699,8 +1758,8 @@ github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY
|
||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A=
|
||||
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
@@ -1749,10 +1808,11 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx
|
||||
github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165/go.mod h1:WZxr2/6a/Ar9bMDc2rN/LJrE/hF6bXE4LPyDSIxwAfg=
|
||||
github.com/leoluk/perflib_exporter v0.1.0/go.mod h1:rpV0lYj7lemdTm31t7zpCqYqPnw7xs86f+BaaNBVYFM=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
||||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
@@ -1801,25 +1861,31 @@ github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxq
|
||||
github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM=
|
||||
github.com/mattetti/filebuffer v1.0.1/go.mod h1:YdMURNDOttIiruleeVr6f56OrMc+MydEnTcXwtkxNVs=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
||||
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
||||
github.com/mattn/go-ieproxy v0.0.0-20191113090002-7c0f6868bffe/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
|
||||
github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E=
|
||||
github.com/mattn/go-ieproxy v0.0.3/go.mod h1:6ZpRmhBaYuBX1U2za+9rC9iCGLsSp2tftelZne7CPko=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
@@ -1896,8 +1962,8 @@ github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
||||
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1-0.20210112042008-8ebf2d61a8b4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
|
||||
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
|
||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||
github.com/mitchellh/pointerstructure v1.0.0/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
@@ -2075,6 +2141,7 @@ github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUr
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||
@@ -2272,13 +2339,16 @@ github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so=
|
||||
github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.4.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/russellhaering/goxmldsig v1.1.0/go.mod h1:QK8GhXPB3+AfuCrfo0oRISa9NfzeCpWmxeGnqEpDF9o=
|
||||
github.com/russellhaering/goxmldsig v1.1.1 h1:vI0r2osGF1A9PLvsGdPUAGwEIrKa4Pj5sesSBsebIxM=
|
||||
github.com/russellhaering/goxmldsig v1.1.1/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
|
||||
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
@@ -2286,6 +2356,7 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190810000440-0ceca61e4d75/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
@@ -2328,7 +2399,6 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
|
||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180825020608-02ddb050ef6b/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
@@ -2374,6 +2444,7 @@ github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
@@ -2381,6 +2452,7 @@ github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
|
||||
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
@@ -2393,6 +2465,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/streadway/amqp v0.0.0-20180528204448-e5adc2ada8b8/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY=
|
||||
@@ -2570,6 +2643,7 @@ github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJB
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
github.com/zenazn/goji v1.0.1/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
@@ -2594,9 +2668,12 @@ go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3C
|
||||
go.etcd.io/etcd v3.3.25+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
|
||||
go.etcd.io/etcd/api/v3 v3.5.0-alpha.0/go.mod h1:mPcW6aZJukV6Aa81LSKpBjQXTWlXB5r74ymPoSWa3Sw=
|
||||
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
|
||||
go.etcd.io/etcd/client/v2 v2.305.0-alpha.0/go.mod h1:kdV+xzCJ3luEBSIeQyB/OEKkWKd8Zkux4sbDeANrosU=
|
||||
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
|
||||
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
|
||||
go.etcd.io/etcd/client/v3 v3.5.0-alpha.0/go.mod h1:wKt7jgDgf/OfKiYmCq5WFGxOFAkVMLxiiXgLDFhECr8=
|
||||
go.etcd.io/etcd/client/v3 v3.5.0-alpha.0.0.20210225194612-fa82d11a958a/go.mod h1:wKt7jgDgf/OfKiYmCq5WFGxOFAkVMLxiiXgLDFhECr8=
|
||||
go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
|
||||
@@ -2670,14 +2747,14 @@ go.uber.org/automaxprocs v1.2.0/go.mod h1:YfO3fm683kQpzETxlTGZhGIVmXAhaw3gxeBADb
|
||||
go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q=
|
||||
go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
@@ -2687,10 +2764,12 @@ go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
|
||||
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
go4.org/intern v0.0.0-20210108033219-3eb7198706b2/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
|
||||
gocloud.dev v0.25.0 h1:Y7vDq8xj7SyM848KXf32Krda2e6jQ4CLh/mTeCSqXtk=
|
||||
gocloud.dev v0.25.0/go.mod h1:7HegHVCYZrMiU3IE1qtnzf/vRrDwLYnRNR3EhWX8x9Y=
|
||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
@@ -2702,6 +2781,7 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@@ -2732,6 +2812,7 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
@@ -2739,10 +2820,12 @@ golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
|
||||
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -2892,8 +2975,12 @@ golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 h1:DZshvxDdVoeKIbudAdFEKi+f70l51luSy/7b76ibTY0=
|
||||
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220107192237-5cfca573fb4d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220401154927-543a649e0bdd h1:zYlwaUHTmxuf6H7hwO2dgwqozQmH7zf4x+/qql4oVWc=
|
||||
golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -2916,8 +3003,10 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a h1:qfl7ob3DIEs3Ml9oLuPwY2N04gymzAW04WsUQHIClgM=
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -3086,19 +3175,29 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f h1:rlezHXNlxYWvBCzNses9Dlc7nGFaNMJeqLolcmQSSZY=
|
||||
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -3122,8 +3221,9 @@ golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs=
|
||||
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -3147,6 +3247,7 @@ golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
@@ -3159,6 +3260,7 @@ golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgw
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190813034749-528a2984e271/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190918214516-5a1a30219888/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@@ -3233,6 +3335,8 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
|
||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -3293,8 +3397,18 @@ google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqiv
|
||||
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
||||
google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E=
|
||||
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
|
||||
google.golang.org/api v0.60.0 h1:eq/zs5WPH4J9undYM9IP1O7dSr7Yh8Y0GtSCpzGzIUk=
|
||||
google.golang.org/api v0.60.0/go.mod h1:d7rl65NZAkEQ90JFzqBjcRq1TVeG5ZoGV3sSpEnnVb4=
|
||||
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
|
||||
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
|
||||
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
|
||||
google.golang.org/api v0.64.0/go.mod h1:931CdxA8Rm4t6zqTFGSsgwbAEZ2+GMYurbndwSimebM=
|
||||
google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M=
|
||||
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
|
||||
google.golang.org/api v0.68.0/go.mod h1:sOM8pTpwgflXRhz+oC8H2Dr+UcbMqkPPWNJo88Q7TH8=
|
||||
google.golang.org/api v0.69.0/go.mod h1:boanBiw+h5c3s+tBPgEzLDRHfFLWV0qXxRHz3ws7C80=
|
||||
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
|
||||
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
|
||||
google.golang.org/api v0.74.0 h1:ExR2D+5TYIrMphWgs5JCgwRhEDlPDXXrLwHHMgPHTXE=
|
||||
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -3391,13 +3505,30 @@ google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEc
|
||||
google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211016002631-37fc39342514/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211018162055-cf77aa76bad2/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211019152133-63b7e35f4404/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 h1:b9mVrqYfq3P4bCdaLg1qtBnPzUYgglsIdjZkL/fQVOE=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220204002441-d6cc3cc0770e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220211171837-173942840c17/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220216160803-4663080d8bc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
|
||||
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de h1:9Ti5SG2U4cAcluryUo/sFay3TQKoxiFMfaT0pbizU7k=
|
||||
google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
|
||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
@@ -3437,9 +3568,12 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
|
||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200910201057-6591123024b3/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
@@ -3454,8 +3588,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
@@ -3484,6 +3619,7 @@ gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8
|
||||
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
|
||||
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||
gopkg.in/gorethink/gorethink.v3 v3.0.5/go.mod h1:+3yIIHJUGMBK+wyPH+iN5TP+88ikFDfZdqTlK3Y9q8I=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
@@ -3491,8 +3627,9 @@ gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
|
||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
|
||||
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
|
||||
|
||||
@@ -180,4 +180,5 @@ export interface GrafanaConfig {
|
||||
geomapDisableCustomBaseLayer?: boolean;
|
||||
unifiedAlertingEnabled: boolean;
|
||||
angularSupportEnabled: boolean;
|
||||
feedbackLinksEnabled: boolean;
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ export interface DataQueryError {
|
||||
error?: string;
|
||||
};
|
||||
message?: string;
|
||||
status?: string;
|
||||
status?: number;
|
||||
statusText?: string;
|
||||
refId?: string;
|
||||
type?: DataQueryErrorType;
|
||||
|
||||
@@ -36,6 +36,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
||||
externalUserMngLinkName = '';
|
||||
externalUserMngInfo = '';
|
||||
allowOrgCreate = false;
|
||||
feedbackLinksEnabled = true;
|
||||
disableLoginForm = false;
|
||||
defaultDatasource = ''; // UID
|
||||
alertingEnabled = false;
|
||||
|
||||
@@ -1,434 +1,441 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"list"
|
||||
"list"
|
||||
|
||||
"github.com/grafana/grafana/cue/scuemata"
|
||||
"github.com/grafana/grafana/cue/scuemata"
|
||||
)
|
||||
|
||||
Family: scuemata.#Family & {
|
||||
lineages: [
|
||||
[
|
||||
{ // 0.0
|
||||
// Unique numeric identifier for the dashboard.
|
||||
// TODO must isolate or remove identifiers local to a Grafana instance...?
|
||||
id?: number
|
||||
// Unique dashboard identifier that can be generated by anyone. string (8-40)
|
||||
uid?: string
|
||||
// Title of dashboard.
|
||||
title?: string
|
||||
// Description of dashboard.
|
||||
description?: string
|
||||
{// 0.0
|
||||
// Unique numeric identifier for the dashboard.
|
||||
// TODO must isolate or remove identifiers local to a Grafana instance...?
|
||||
id?: number
|
||||
// Unique dashboard identifier that can be generated by anyone. string (8-40)
|
||||
uid?: string
|
||||
// Title of dashboard.
|
||||
title?: string
|
||||
// Description of dashboard.
|
||||
description?: string
|
||||
|
||||
gnetId?: string
|
||||
// Tags associated with dashboard.
|
||||
tags?: [...string]
|
||||
// Theme of dashboard.
|
||||
style: *"light" | "dark"
|
||||
// Timezone of dashboard,
|
||||
timezone?: *"browser" | "utc" | ""
|
||||
// Whether a dashboard is editable or not.
|
||||
editable: bool | *true
|
||||
// 0 for no shared crosshair or tooltip (default).
|
||||
// 1 for shared crosshair.
|
||||
// 2 for shared crosshair AND shared tooltip.
|
||||
graphTooltip: >=0 & <=2 | *0
|
||||
// Time range for dashboard, e.g. last 6 hours, last 7 days, etc
|
||||
time?: {
|
||||
from: string | *"now-6h"
|
||||
to: string | *"now"
|
||||
}
|
||||
// Timepicker metadata.
|
||||
timepicker?: {
|
||||
// Whether timepicker is collapsed or not.
|
||||
collapse: bool | *false
|
||||
// Whether timepicker is enabled or not.
|
||||
enable: bool | *true
|
||||
// Whether timepicker is visible or not.
|
||||
hidden: bool | *false
|
||||
// Selectable intervals for auto-refresh.
|
||||
refresh_intervals: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
|
||||
}
|
||||
// Templating.
|
||||
templating?: list: [...{...}]
|
||||
// Annotations.
|
||||
annotations?: list: [...{
|
||||
builtIn: number | *0
|
||||
// Datasource to use for annotation.
|
||||
datasource: string
|
||||
// Whether annotation is enabled.
|
||||
enable: bool | *true
|
||||
// Whether to hide annotation.
|
||||
hide?: bool | *false
|
||||
// Annotation icon color.
|
||||
iconColor?: string
|
||||
// Name of annotation.
|
||||
name?: string
|
||||
type: string | *"dashboard"
|
||||
// Query for annotation data.
|
||||
rawQuery?: string
|
||||
showIn: number | *0
|
||||
}]
|
||||
// Auto-refresh interval.
|
||||
refresh?: string | false
|
||||
// Version of the JSON schema, incremented each time a Grafana update brings
|
||||
// changes to said schema.
|
||||
// FIXME this is the old schema numbering system, and will be replaced by scuemata
|
||||
schemaVersion: number | *30
|
||||
// Version of the dashboard, incremented each time the dashboard is updated.
|
||||
version?: number
|
||||
panels?: [...(#Panel | #GraphPanel | #RowPanel)]
|
||||
gnetId?: string
|
||||
// Tags associated with dashboard.
|
||||
tags?: [...string]
|
||||
// Theme of dashboard.
|
||||
style: *"light" | "dark"
|
||||
// Timezone of dashboard,
|
||||
timezone?: *"browser" | "utc" | ""
|
||||
// Whether a dashboard is editable or not.
|
||||
editable: bool | *true
|
||||
// 0 for no shared crosshair or tooltip (default).
|
||||
// 1 for shared crosshair.
|
||||
// 2 for shared crosshair AND shared tooltip.
|
||||
graphTooltip: >=0 & <=2 | *0
|
||||
// Time range for dashboard, e.g. last 6 hours, last 7 days, etc
|
||||
time?: {
|
||||
from: string | *"now-6h"
|
||||
to: string | *"now"
|
||||
}
|
||||
// Timepicker metadata.
|
||||
timepicker?: {
|
||||
// Whether timepicker is collapsed or not.
|
||||
collapse: bool | *false
|
||||
// Whether timepicker is enabled or not.
|
||||
enable: bool | *true
|
||||
// Whether timepicker is visible or not.
|
||||
hidden: bool | *false
|
||||
// Selectable intervals for auto-refresh.
|
||||
refresh_intervals: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
|
||||
}
|
||||
// Templating.
|
||||
templating?: list: [...{...}]
|
||||
// Annotations.
|
||||
annotations?: list: [...{
|
||||
builtIn: number | *0
|
||||
// Datasource to use for annotation.
|
||||
datasource: {
|
||||
type?: string
|
||||
uid?: string
|
||||
}
|
||||
// Whether annotation is enabled.
|
||||
enable: bool | *true
|
||||
// Whether to hide annotation.
|
||||
hide?: bool | *false
|
||||
// Annotation icon color.
|
||||
iconColor?: string
|
||||
// Name of annotation.
|
||||
name?: string
|
||||
type: string | *"dashboard"
|
||||
// Query for annotation data.
|
||||
rawQuery?: string
|
||||
showIn: number | *0
|
||||
}]
|
||||
// Auto-refresh interval.
|
||||
refresh?: string | false
|
||||
// Version of the JSON schema, incremented each time a Grafana update brings
|
||||
// changes to said schema.
|
||||
// FIXME this is the old schema numbering system, and will be replaced by scuemata
|
||||
schemaVersion: number | *30
|
||||
// Version of the dashboard, incremented each time the dashboard is updated.
|
||||
version?: number
|
||||
panels?: [...(#Panel | #GraphPanel | #RowPanel)]
|
||||
|
||||
// TODO docs
|
||||
#FieldColorModeId: "thresholds" | "palette-classic" | "palette-saturated" | "continuous-GrYlRd" | "fixed" @cuetsy(kind="enum")
|
||||
// TODO docs
|
||||
#FieldColorModeId: "thresholds" | "palette-classic" | "palette-saturated" | "continuous-GrYlRd" | "fixed" @cuetsy(kind="enum")
|
||||
|
||||
// TODO docs
|
||||
#FieldColorSeriesByMode: "min" | "max" | "last" @cuetsy(kind="type")
|
||||
// TODO docs
|
||||
#FieldColorSeriesByMode: "min" | "max" | "last" @cuetsy(kind="type")
|
||||
|
||||
// TODO docs
|
||||
#FieldColor: {
|
||||
// The main color scheme mode
|
||||
mode: #FieldColorModeId | string
|
||||
// Stores the fixed color value if mode is fixed
|
||||
fixedColor?: string
|
||||
// Some visualizations need to know how to assign a series color from by value color schemes
|
||||
seriesBy?: #FieldColorSeriesByMode
|
||||
} @cuetsy(kind="interface")
|
||||
// TODO docs
|
||||
#FieldColor: {
|
||||
// The main color scheme mode
|
||||
mode: #FieldColorModeId | string
|
||||
// Stores the fixed color value if mode is fixed
|
||||
fixedColor?: string
|
||||
// Some visualizations need to know how to assign a series color from by value color schemes
|
||||
seriesBy?: #FieldColorSeriesByMode
|
||||
} @cuetsy(kind="interface")
|
||||
|
||||
// TODO docs
|
||||
#Threshold: {
|
||||
// TODO docs
|
||||
// FIXME the corresponding typescript field is required/non-optional, but nulls currently appear here when serializing -Infinity to JSON
|
||||
value?: number
|
||||
// TODO docs
|
||||
color: string
|
||||
// TODO docs
|
||||
// TODO are the values here enumerable into a disjunction?
|
||||
// Some seem to be listed in typescript comment
|
||||
state?: string
|
||||
} @cuetsy(kind="interface")
|
||||
// TODO docs
|
||||
#Threshold: {
|
||||
// TODO docs
|
||||
// FIXME the corresponding typescript field is required/non-optional, but nulls currently appear here when serializing -Infinity to JSON
|
||||
value?: number
|
||||
// TODO docs
|
||||
color: string
|
||||
// TODO docs
|
||||
// TODO are the values here enumerable into a disjunction?
|
||||
// Some seem to be listed in typescript comment
|
||||
state?: string
|
||||
} @cuetsy(kind="interface")
|
||||
|
||||
#ThresholdsMode: "absolute" | "percentage" @cuetsy(kind="enum")
|
||||
#ThresholdsMode: "absolute" | "percentage" @cuetsy(kind="enum")
|
||||
|
||||
#ThresholdsConfig: {
|
||||
mode: #ThresholdsMode
|
||||
#ThresholdsConfig: {
|
||||
mode: #ThresholdsMode
|
||||
|
||||
// Must be sorted by 'value', first value is always -Infinity
|
||||
steps: [...#Threshold]
|
||||
} @cuetsy(kind="interface")
|
||||
// Must be sorted by 'value', first value is always -Infinity
|
||||
steps: [...#Threshold]
|
||||
} @cuetsy(kind="interface")
|
||||
|
||||
// TODO docs
|
||||
// FIXME this is extremely underspecfied; wasn't obvious which typescript types corresponded to it
|
||||
#Transformation: {
|
||||
id: string
|
||||
options: {...}
|
||||
}
|
||||
// TODO docs
|
||||
// FIXME this is extremely underspecfied; wasn't obvious which typescript types corresponded to it
|
||||
#Transformation: {
|
||||
id: string
|
||||
options: {...}
|
||||
}
|
||||
|
||||
// Schema for panel targets is specified by datasource
|
||||
// plugins. We use a placeholder definition, which the Go
|
||||
// schema loader either left open/as-is with the Base
|
||||
// variant of the Dashboard and Panel families, or filled
|
||||
// with types derived from plugins in the Instance variant.
|
||||
// When working directly from CUE, importers can extend this
|
||||
// type directly to achieve the same effect.
|
||||
#Target: {...}
|
||||
// Schema for panel targets is specified by datasource
|
||||
// plugins. We use a placeholder definition, which the Go
|
||||
// schema loader either left open/as-is with the Base
|
||||
// variant of the Dashboard and Panel families, or filled
|
||||
// with types derived from plugins in the Instance variant.
|
||||
// When working directly from CUE, importers can extend this
|
||||
// type directly to achieve the same effect.
|
||||
#Target: {...}
|
||||
|
||||
// Dashboard panels. Panels are canonically defined inline
|
||||
// because they share a version timeline with the dashboard
|
||||
// schema; they do not evolve independently.
|
||||
#Panel: {
|
||||
// The panel plugin type id.
|
||||
type: !=""
|
||||
// Dashboard panels. Panels are canonically defined inline
|
||||
// because they share a version timeline with the dashboard
|
||||
// schema; they do not evolve independently.
|
||||
#Panel: {
|
||||
// The panel plugin type id.
|
||||
type: !=""
|
||||
|
||||
// TODO docs
|
||||
id?: number
|
||||
// TODO docs
|
||||
id?: number
|
||||
|
||||
// FIXME this almost certainly has to be changed in favor of scuemata versions
|
||||
pluginVersion?: string
|
||||
// FIXME this almost certainly has to be changed in favor of scuemata versions
|
||||
pluginVersion?: string
|
||||
|
||||
// TODO docs
|
||||
tags?: [...string]
|
||||
// TODO docs
|
||||
tags?: [...string]
|
||||
|
||||
// Internal - the exact major and minor versions of the panel plugin
|
||||
// schema. Hidden and therefore not a part of the data model, but
|
||||
// expected to be filled with panel plugin schema versions so that it's
|
||||
// possible to figure out which schema version matched on a successful
|
||||
// unification.
|
||||
// _pv: { maj: int, min: int }
|
||||
// The major and minor versions of the panel plugin for this schema.
|
||||
// TODO 2-tuple list instead of struct?
|
||||
// panelSchema?: { maj: number, min: number }
|
||||
panelSchema?: [number, number]
|
||||
// Internal - the exact major and minor versions of the panel plugin
|
||||
// schema. Hidden and therefore not a part of the data model, but
|
||||
// expected to be filled with panel plugin schema versions so that it's
|
||||
// possible to figure out which schema version matched on a successful
|
||||
// unification.
|
||||
// _pv: { maj: int, min: int }
|
||||
// The major and minor versions of the panel plugin for this schema.
|
||||
// TODO 2-tuple list instead of struct?
|
||||
// panelSchema?: { maj: number, min: number }
|
||||
panelSchema?: [number, number]
|
||||
|
||||
// TODO docs
|
||||
targets?: [...#Target]
|
||||
// TODO docs
|
||||
targets?: [...#Target]
|
||||
|
||||
// Panel title.
|
||||
title?: string
|
||||
// Description.
|
||||
description?: string
|
||||
// Whether to display the panel without a background.
|
||||
transparent: bool | *false
|
||||
// The datasource used in all targets.
|
||||
datasource?: {
|
||||
type?: string
|
||||
uid?: string
|
||||
}
|
||||
// Grid position.
|
||||
gridPos?: {
|
||||
// Panel
|
||||
h: number & >0 | *9
|
||||
// Panel
|
||||
w: number & >0 & <=24 | *12
|
||||
// Panel x
|
||||
x: number & >=0 & <24 | *0
|
||||
// Panel y
|
||||
y: number & >=0 | *0
|
||||
// true if fixed
|
||||
static?: bool
|
||||
}
|
||||
// Panel links.
|
||||
// FIXME this is temporarily specified as a closed list so
|
||||
// that validation will pass when no links are present, but
|
||||
// to force a failure as soon as it's checked against there
|
||||
// being anything in the list so it can be fixed in
|
||||
// accordance with that object
|
||||
links?: []
|
||||
// Panel title.
|
||||
title?: string
|
||||
// Description.
|
||||
description?: string
|
||||
// Whether to display the panel without a background.
|
||||
transparent: bool | *false
|
||||
// The datasource used in all targets.
|
||||
datasource?: {
|
||||
type?: string
|
||||
uid?: string
|
||||
}
|
||||
// Grid position.
|
||||
gridPos?: {
|
||||
// Panel
|
||||
h: number & >0 | *9
|
||||
// Panel
|
||||
w: number & >0 & <=24 | *12
|
||||
// Panel x
|
||||
x: number & >=0 & <24 | *0
|
||||
// Panel y
|
||||
y: number & >=0 | *0
|
||||
// true if fixed
|
||||
static?: bool
|
||||
}
|
||||
// Panel links.
|
||||
// FIXME this is temporarily specified as a closed list so
|
||||
// that validation will pass when no links are present, but
|
||||
// to force a failure as soon as it's checked against there
|
||||
// being anything in the list so it can be fixed in
|
||||
// accordance with that object
|
||||
links?: []
|
||||
|
||||
// Name of template variable to repeat for.
|
||||
repeat?: string
|
||||
// Direction to repeat in if 'repeat' is set.
|
||||
// "h" for horizontal, "v" for vertical.
|
||||
repeatDirection: *"h" | "v"
|
||||
// Name of template variable to repeat for.
|
||||
repeat?: string
|
||||
// Direction to repeat in if 'repeat' is set.
|
||||
// "h" for horizontal, "v" for vertical.
|
||||
repeatDirection: *"h" | "v"
|
||||
|
||||
// TODO docs
|
||||
maxDataPoints?: number
|
||||
// TODO docs
|
||||
maxDataPoints?: number
|
||||
|
||||
// TODO docs
|
||||
thresholds?: [...]
|
||||
// TODO docs
|
||||
thresholds?: [...]
|
||||
|
||||
// TODO docs
|
||||
timeRegions?: [...]
|
||||
// TODO docs
|
||||
timeRegions?: [...]
|
||||
|
||||
transformations: [...#Transformation]
|
||||
transformations: [...#Transformation]
|
||||
|
||||
// TODO docs
|
||||
// TODO tighter constraint
|
||||
interval?: string
|
||||
// TODO docs
|
||||
// TODO tighter constraint
|
||||
interval?: string
|
||||
|
||||
// TODO docs
|
||||
// TODO tighter constraint
|
||||
timeFrom?: string
|
||||
// TODO docs
|
||||
// TODO tighter constraint
|
||||
timeFrom?: string
|
||||
|
||||
// TODO docs
|
||||
// TODO tighter constraint
|
||||
timeShift?: string
|
||||
// TODO docs
|
||||
// TODO tighter constraint
|
||||
timeShift?: string
|
||||
|
||||
// options is specified by the PanelOptions field in panel
|
||||
// plugin schemas.
|
||||
options: {}
|
||||
// options is specified by the PanelOptions field in panel
|
||||
// plugin schemas.
|
||||
options: {}
|
||||
|
||||
fieldConfig: {
|
||||
defaults: {
|
||||
// The display value for this field. This supports template variables blank is auto
|
||||
displayName?: string
|
||||
fieldConfig: {
|
||||
defaults: {
|
||||
// The display value for this field. This supports template variables blank is auto
|
||||
displayName?: string
|
||||
|
||||
// This can be used by data sources that return and explicit naming structure for values and labels
|
||||
// When this property is configured, this value is used rather than the default naming strategy.
|
||||
displayNameFromDS?: string
|
||||
// This can be used by data sources that return and explicit naming structure for values and labels
|
||||
// When this property is configured, this value is used rather than the default naming strategy.
|
||||
displayNameFromDS?: string
|
||||
|
||||
// Human readable field metadata
|
||||
description?: string
|
||||
// Human readable field metadata
|
||||
description?: string
|
||||
|
||||
// An explict path to the field in the datasource. When the frame meta includes a path,
|
||||
// This will default to `${frame.meta.path}/${field.name}
|
||||
//
|
||||
// When defined, this value can be used as an identifier within the datasource scope, and
|
||||
// may be used to update the results
|
||||
path?: string
|
||||
// An explict path to the field in the datasource. When the frame meta includes a path,
|
||||
// This will default to `${frame.meta.path}/${field.name}
|
||||
//
|
||||
// When defined, this value can be used as an identifier within the datasource scope, and
|
||||
// may be used to update the results
|
||||
path?: string
|
||||
|
||||
// True if data source can write a value to the path. Auth/authz are supported separately
|
||||
writeable?: bool
|
||||
// True if data source can write a value to the path. Auth/authz are supported separately
|
||||
writeable?: bool
|
||||
|
||||
// True if data source field supports ad-hoc filters
|
||||
filterable?: bool
|
||||
// True if data source field supports ad-hoc filters
|
||||
filterable?: bool
|
||||
|
||||
// Numeric Options
|
||||
unit?: string
|
||||
// Numeric Options
|
||||
unit?: string
|
||||
|
||||
// Significant digits (for display)
|
||||
decimals?: number
|
||||
// Significant digits (for display)
|
||||
decimals?: number
|
||||
|
||||
min?: number
|
||||
max?: number
|
||||
min?: number
|
||||
max?: number
|
||||
|
||||
// Convert input values into a display string
|
||||
//
|
||||
// TODO this one corresponds to a complex type with
|
||||
// generics on the typescript side. Ouch. Will
|
||||
// either need special care, or we'll just need to
|
||||
// accept a very loosely specified schema. It's very
|
||||
// unlikely we'll be able to translate cue to
|
||||
// typescript generics in the general case, though
|
||||
// this particular one *may* be able to work.
|
||||
mappings?: [...{...}]
|
||||
// Convert input values into a display string
|
||||
//
|
||||
// TODO this one corresponds to a complex type with
|
||||
// generics on the typescript side. Ouch. Will
|
||||
// either need special care, or we'll just need to
|
||||
// accept a very loosely specified schema. It's very
|
||||
// unlikely we'll be able to translate cue to
|
||||
// typescript generics in the general case, though
|
||||
// this particular one *may* be able to work.
|
||||
mappings?: [...{...}]
|
||||
|
||||
// Map numeric values to states
|
||||
thresholds?: #ThresholdsConfig
|
||||
// Map numeric values to states
|
||||
thresholds?: #ThresholdsConfig
|
||||
|
||||
// // Map values to a display color
|
||||
color?: #FieldColor
|
||||
// // Map values to a display color
|
||||
color?: #FieldColor
|
||||
|
||||
// // Used when reducing field values
|
||||
// nullValueMode?: NullValueMode
|
||||
// // Used when reducing field values
|
||||
// nullValueMode?: NullValueMode
|
||||
|
||||
// // The behavior when clicking on a result
|
||||
links?: [...]
|
||||
// // The behavior when clicking on a result
|
||||
links?: [...]
|
||||
|
||||
// Alternative to empty string
|
||||
noValue?: string
|
||||
// Alternative to empty string
|
||||
noValue?: string
|
||||
|
||||
// custom is specified by the PanelFieldConfig field
|
||||
// in panel plugin schemas.
|
||||
custom?: {}
|
||||
}
|
||||
overrides: [...{
|
||||
matcher: {
|
||||
id: string | *""
|
||||
options?: _
|
||||
}
|
||||
properties: [...{
|
||||
id: string | *""
|
||||
value?: _
|
||||
}]
|
||||
}]
|
||||
}
|
||||
// Embed the disjunction of all injected panel schema, if any were injected.
|
||||
if len(compose._panelSchemas) > 0 {
|
||||
or(compose._panelSchemas) // TODO try to stick graph in here
|
||||
}
|
||||
// custom is specified by the PanelFieldConfig field
|
||||
// in panel plugin schemas.
|
||||
custom?: {}
|
||||
}
|
||||
overrides: [...{
|
||||
matcher: {
|
||||
id: string | *""
|
||||
options?: _
|
||||
}
|
||||
properties: [...{
|
||||
id: string | *""
|
||||
value?: _
|
||||
}]
|
||||
}]
|
||||
}
|
||||
// Embed the disjunction of all injected panel schema, if any were injected.
|
||||
if len(compose._panelSchemas) > 0 {
|
||||
or(compose._panelSchemas)// TODO try to stick graph in here
|
||||
}
|
||||
|
||||
// Make the plugin-composed subtrees open if the panel is
|
||||
// of unknown types. This is important in every possible case:
|
||||
// - Base (this file only): no real dashboard json
|
||||
// containing any panels would ever validate
|
||||
// - Dist (this file + core plugin schema): dashboard json containing
|
||||
// panels with any third-party panel plugins would fail to validate,
|
||||
// as well as any core plugins lacking a models.cue. The latter case
|
||||
// is not normally expected, but this is not the appropriate place
|
||||
// to enforce the invariant, anyway.
|
||||
// - Instance (this file + core + third-party plugin schema): dashboard
|
||||
// json containing panels with a third-party plugin that exists but
|
||||
// is not currently installed would fail to validate.
|
||||
if !list.Contains(compose._panelTypes, type) {
|
||||
options: {...}
|
||||
fieldConfig: defaults: custom: {...}
|
||||
...
|
||||
}
|
||||
}
|
||||
// Make the plugin-composed subtrees open if the panel is
|
||||
// of unknown types. This is important in every possible case:
|
||||
// - Base (this file only): no real dashboard json
|
||||
// containing any panels would ever validate
|
||||
// - Dist (this file + core plugin schema): dashboard json containing
|
||||
// panels with any third-party panel plugins would fail to validate,
|
||||
// as well as any core plugins lacking a models.cue. The latter case
|
||||
// is not normally expected, but this is not the appropriate place
|
||||
// to enforce the invariant, anyway.
|
||||
// - Instance (this file + core + third-party plugin schema): dashboard
|
||||
// json containing panels with a third-party plugin that exists but
|
||||
// is not currently installed would fail to validate.
|
||||
if !list.Contains(compose._panelTypes, type) {
|
||||
options: {...}
|
||||
fieldConfig: defaults: custom: {...}
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
// Row panel
|
||||
#RowPanel: {
|
||||
type: "row"
|
||||
collapsed: bool | *false
|
||||
title?: string
|
||||
// Row panel
|
||||
#RowPanel: {
|
||||
type: "row"
|
||||
collapsed: bool | *false
|
||||
title?: string
|
||||
|
||||
// Name of default datasource.
|
||||
datasource?: string
|
||||
// Name of default datasource.
|
||||
datasource: {
|
||||
type?: string
|
||||
uid?: string
|
||||
}
|
||||
|
||||
gridPos?: {
|
||||
// Panel
|
||||
h: number & >0 | *9
|
||||
// Panel
|
||||
w: number & >0 & <=24 | *12
|
||||
// Panel x
|
||||
x: number & >=0 & <24 | *0
|
||||
// Panel y
|
||||
y: number & >=0 | *0
|
||||
// true if fixed
|
||||
static?: bool
|
||||
}
|
||||
id: number
|
||||
panels: [...(#Panel | #GraphPanel)]
|
||||
// Name of template variable to repeat for.
|
||||
repeat?: string
|
||||
}
|
||||
// Support for legacy graph panels.
|
||||
#GraphPanel: {
|
||||
...
|
||||
type: "graph"
|
||||
thresholds: [...{...}]
|
||||
timeRegions?: [...{...}]
|
||||
seriesOverrides: [...{...}]
|
||||
aliasColors?: [string]: string
|
||||
bars: bool | *false
|
||||
dashes: bool | *false
|
||||
dashLength: number | *10
|
||||
fill?: number
|
||||
fillGradient?: number
|
||||
hiddenSeries: bool | *false
|
||||
legend: {...}
|
||||
lines: bool | *false
|
||||
linewidth?: number
|
||||
nullPointMode: *"null" | "connected" | "null as zero"
|
||||
percentage: bool | *false
|
||||
points: bool | *false
|
||||
pointradius?: number
|
||||
renderer: string
|
||||
spaceLength: number | *10
|
||||
stack: bool | *false
|
||||
steppedLine: bool | *false
|
||||
tooltip?: {
|
||||
shared?: bool
|
||||
sort: number | *0
|
||||
value_type: *"individual" | "cumulative"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
gridPos?: {
|
||||
// Panel
|
||||
h: number & >0 | *9
|
||||
// Panel
|
||||
w: number & >0 & <=24 | *12
|
||||
// Panel x
|
||||
x: number & >=0 & <24 | *0
|
||||
// Panel y
|
||||
y: number & >=0 | *0
|
||||
// true if fixed
|
||||
static?: bool
|
||||
}
|
||||
id: number
|
||||
panels: [...(#Panel | #GraphPanel)]
|
||||
// Name of template variable to repeat for.
|
||||
repeat?: string
|
||||
}
|
||||
|
||||
// Support for legacy graph panels.
|
||||
#GraphPanel: {
|
||||
...
|
||||
type: "graph"
|
||||
thresholds: [...{...}]
|
||||
timeRegions?: [...{...}]
|
||||
seriesOverrides: [...{...}]
|
||||
aliasColors?: [string]: string
|
||||
bars: bool | *false
|
||||
dashes: bool | *false
|
||||
dashLength: number | *10
|
||||
fill?: number
|
||||
fillGradient?: number
|
||||
hiddenSeries: bool | *false
|
||||
legend: {...}
|
||||
lines: bool | *false
|
||||
linewidth?: number
|
||||
nullPointMode: *"null" | "connected" | "null as zero"
|
||||
percentage: bool | *false
|
||||
points: bool | *false
|
||||
pointradius?: number
|
||||
renderer: string
|
||||
spaceLength: number | *10
|
||||
stack: bool | *false
|
||||
steppedLine: bool | *false
|
||||
tooltip?: {
|
||||
shared?: bool
|
||||
sort: number | *0
|
||||
value_type: *"individual" | "cumulative"
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
]
|
||||
compose: {
|
||||
// Scuemata families for all panel types that should be composed into the
|
||||
// dashboard schema.
|
||||
Panel: [string]: scuemata.#PanelFamily
|
||||
compose: {
|
||||
// Scuemata families for all panel types that should be composed into the
|
||||
// dashboard schema.
|
||||
Panel: [string]: scuemata.#PanelFamily
|
||||
|
||||
// _panelTypes: [for typ, _ in Panel {typ}]
|
||||
_panelTypes: [for typ, _ in Panel {typ}, "graph", "row"]
|
||||
_panelSchemas: [for typ, scue in Panel {
|
||||
for lv, lin in scue.lineages {
|
||||
for sv, sch in lin {
|
||||
(_mapPanel & {arg: {
|
||||
type: typ
|
||||
v: [lv, sv] // TODO add optionality for exact, at least, at most, any
|
||||
model: sch // TODO Does this need to be close()d?
|
||||
}}).out
|
||||
}
|
||||
}
|
||||
}, { type: string }]
|
||||
_mapPanel: {
|
||||
arg: {
|
||||
type: string & !=""
|
||||
v: [number, number]
|
||||
model: {...}
|
||||
}
|
||||
// Until CUE introduces the must() constraint, we have to enforce
|
||||
// that the input model is as expected by checking for unification
|
||||
// in this hidden property (see https://github.com/cue-lang/cue/issues/575).
|
||||
// If we unified arg.model with the scuemata.#PanelSchema
|
||||
// meta-schema directly, the struct openness (PanelOptions: {...})
|
||||
// would be applied to the actual schema instance in the arg. Here,
|
||||
// where we're actually putting those in the dashboard schema, want
|
||||
// those to be closed, or at least preserve closed-ness.
|
||||
_checkSchema: scuemata.#PanelSchema & arg.model
|
||||
out: {
|
||||
type: arg.type
|
||||
panelSchema: arg.v // TODO add optionality for exact, at least, at most, any
|
||||
options: arg.model.PanelOptions
|
||||
fieldConfig: defaults: custom: {}
|
||||
if arg.model.PanelFieldConfig != _|_ {
|
||||
fieldConfig: defaults: custom: arg.model.PanelFieldConfig
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// _panelTypes: [for typ, _ in Panel {typ}]
|
||||
_panelTypes: [ for typ, _ in Panel {typ}, "graph", "row"]
|
||||
_panelSchemas: [ for typ, scue in Panel {
|
||||
for lv, lin in scue.lineages {
|
||||
for sv, sch in lin {
|
||||
(_mapPanel & {arg: {
|
||||
type: typ
|
||||
v: [lv, sv] // TODO add optionality for exact, at least, at most, any
|
||||
model: sch // TODO Does this need to be close()d?
|
||||
}}).out
|
||||
}
|
||||
}
|
||||
}, {type: string}]
|
||||
_mapPanel: {
|
||||
arg: {
|
||||
type: string & !=""
|
||||
v: [number, number]
|
||||
model: {...}
|
||||
}
|
||||
// Until CUE introduces the must() constraint, we have to enforce
|
||||
// that the input model is as expected by checking for unification
|
||||
// in this hidden property (see https://github.com/cue-lang/cue/issues/575).
|
||||
// If we unified arg.model with the scuemata.#PanelSchema
|
||||
// meta-schema directly, the struct openness (PanelOptions: {...})
|
||||
// would be applied to the actual schema instance in the arg. Here,
|
||||
// where we're actually putting those in the dashboard schema, want
|
||||
// those to be closed, or at least preserve closed-ness.
|
||||
_checkSchema: scuemata.#PanelSchema & arg.model
|
||||
out: {
|
||||
type: arg.type
|
||||
panelSchema: arg.v // TODO add optionality for exact, at least, at most, any
|
||||
options: arg.model.PanelOptions
|
||||
fieldConfig: defaults: custom: {}
|
||||
if arg.model.PanelFieldConfig != _|_ {
|
||||
fieldConfig: defaults: custom: arg.model.PanelFieldConfig
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,6 @@
|
||||
"@grafana/tsconfig": "^1.2.0-rc1",
|
||||
"@mdx-js/react": "1.6.22",
|
||||
"@rollup/plugin-commonjs": "21.0.2",
|
||||
"@rollup/plugin-image": "2.1.1",
|
||||
"@rollup/plugin-node-resolve": "13.1.3",
|
||||
"@storybook/addon-a11y": "6.4.21",
|
||||
"@storybook/addon-actions": "6.4.21",
|
||||
@@ -168,6 +167,7 @@
|
||||
"rimraf": "3.0.2",
|
||||
"rollup": "2.70.1",
|
||||
"rollup-plugin-sourcemaps": "0.6.3",
|
||||
"rollup-plugin-svg-import": "^1.6.0",
|
||||
"rollup-plugin-terser": "7.0.2",
|
||||
"sass-loader": "12.6.0",
|
||||
"storybook-dark-mode": "1.0.9",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import image from '@rollup/plugin-image';
|
||||
import svg from 'rollup-plugin-svg-import';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
|
||||
const pkg = require('./package.json');
|
||||
@@ -41,7 +41,7 @@ const buildCjsPackage = ({ env }) => {
|
||||
include: /node_modules/,
|
||||
}),
|
||||
resolve(),
|
||||
image(),
|
||||
svg({ stringify: true }),
|
||||
env === 'production' && terser(),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -304,9 +304,9 @@ export const Table: FC<Props> = memo((props: Props) => {
|
||||
totalColumnsWidth={totalColumnsWidth}
|
||||
/>
|
||||
)}
|
||||
{paginationEl}
|
||||
</div>
|
||||
</CustomScrollbar>
|
||||
{paginationEl}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -184,6 +184,9 @@ export const getTableStyles = (theme: GrafanaTheme2) => {
|
||||
div:not(:only-child):first-child {
|
||||
flex-grow: 0.6;
|
||||
}
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
`,
|
||||
paginationSummary: css`
|
||||
color: ${theme.colors.text.secondary};
|
||||
@@ -191,11 +194,16 @@ export const getTableStyles = (theme: GrafanaTheme2) => {
|
||||
margin-left: auto;
|
||||
`,
|
||||
|
||||
tableContentWrapper: (totalColumnsWidth: number) => css`
|
||||
width: ${totalColumnsWidth ?? '100%'};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`,
|
||||
tableContentWrapper: (totalColumnsWidth: number) => {
|
||||
const width = totalColumnsWidth !== undefined ? `${totalColumnsWidth}px` : '100%';
|
||||
|
||||
return css`
|
||||
label: tableContentWrapper;
|
||||
width: ${width};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
},
|
||||
row: css`
|
||||
label: row;
|
||||
border-bottom: 1px solid ${borderColor};
|
||||
|
||||
@@ -69,6 +69,7 @@ export const getAvailableIcons = () =>
|
||||
'envelope',
|
||||
'exchange-alt',
|
||||
'exclamation-triangle',
|
||||
'exclamation-circle',
|
||||
'external-link-alt',
|
||||
'eye',
|
||||
'eye-slash',
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -149,6 +150,23 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
||||
Grants: []string{string(models.ROLE_VIEWER)},
|
||||
}
|
||||
|
||||
apikeyReaderRole := ac.RoleRegistration{
|
||||
Role: ac.RoleDTO{
|
||||
Version: 1,
|
||||
Name: "fixed:apikeys:reader",
|
||||
DisplayName: "APIKeys reader",
|
||||
Description: "Gives access to read api keys.",
|
||||
Group: "API Keys",
|
||||
Permissions: []ac.Permission{
|
||||
{
|
||||
Action: ac.ActionAPIKeyRead,
|
||||
Scope: ac.ScopeAPIKeysAll,
|
||||
},
|
||||
},
|
||||
},
|
||||
Grants: []string{string(models.ROLE_ADMIN)},
|
||||
}
|
||||
|
||||
apikeyWriterRole := ac.RoleRegistration{
|
||||
Role: ac.RoleDTO{
|
||||
Version: 1,
|
||||
@@ -410,7 +428,7 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
||||
orgMaintainerRole, teamsCreatorRole, teamsWriterRole, datasourcesExplorerRole,
|
||||
annotationsReaderRole, dashboardAnnotationsWriterRole, annotationsWriterRole,
|
||||
dashboardsCreatorRole, dashboardsReaderRole, dashboardsWriterRole,
|
||||
foldersCreatorRole, foldersReaderRole, foldersWriterRole, apikeyWriterRole,
|
||||
foldersCreatorRole, foldersReaderRole, foldersWriterRole, apikeyReaderRole, apikeyWriterRole,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -462,6 +480,12 @@ var teamsEditAccessEvaluator = ac.EvalAll(
|
||||
),
|
||||
)
|
||||
|
||||
// apiKeyAccessEvaluator is used to protect the "Configuration > API keys" page access
|
||||
var apiKeyAccessEvaluator = ac.EvalPermission(ac.ActionAPIKeyRead)
|
||||
|
||||
// serviceAccountAccessEvaluator is used to protect the "Configuration > Service accounts" page access
|
||||
var serviceAccountAccessEvaluator = ac.EvalPermission(serviceaccounts.ActionRead)
|
||||
|
||||
// Metadata helpers
|
||||
// getAccessControlMetadata returns the accesscontrol metadata associated with a given resource
|
||||
func (hs *HTTPServer) getAccessControlMetadata(c *models.ReqContext,
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ func (hs *HTTPServer) AdminGetStats(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Failed to get admin stats from database", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, statsQuery.Result)
|
||||
return response.JSON(http.StatusOK, statsQuery.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getAuthorizedSettings(ctx context.Context, user *models.SignedInUser, bag setting.SettingsBag) (setting.SettingsBag, error) {
|
||||
|
||||
@@ -58,7 +58,7 @@ func (hs *HTTPServer) AdminCreateUser(c *models.ReqContext) response.Response {
|
||||
Id: user.Id,
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) AdminUpdateUserPassword(c *models.ReqContext) response.Response {
|
||||
|
||||
+19
-19
@@ -54,7 +54,7 @@ func (hs *HTTPServer) GetAlertStatesForDashboard(c *models.ReqContext) response.
|
||||
return response.Error(500, "Failed to fetch alert states", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
// GET /api/alerts
|
||||
@@ -106,7 +106,7 @@ func (hs *HTTPServer) GetAlerts(c *models.ReqContext) response.Response {
|
||||
|
||||
// if we didn't find any dashboards, return empty result
|
||||
if len(dashboardIDs) == 0 {
|
||||
return response.JSON(200, []*models.AlertListItemDTO{})
|
||||
return response.JSON(http.StatusOK, []*models.AlertListItemDTO{})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ func (hs *HTTPServer) GetAlerts(c *models.ReqContext) response.Response {
|
||||
alert.Url = models.GetDashboardUrl(alert.DashboardUid, alert.DashboardSlug)
|
||||
}
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
// POST /api/alerts/test
|
||||
@@ -176,7 +176,7 @@ func (hs *HTTPServer) AlertTest(c *models.ReqContext) response.Response {
|
||||
|
||||
dtoRes.TimeMs = fmt.Sprintf("%1.3fms", res.GetDurationMs())
|
||||
|
||||
return response.JSON(200, dtoRes)
|
||||
return response.JSON(http.StatusOK, dtoRes)
|
||||
}
|
||||
|
||||
// GET /api/alerts/:id
|
||||
@@ -191,17 +191,17 @@ func (hs *HTTPServer) GetAlert(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "List alerts failed", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, &query.Result)
|
||||
return response.JSON(http.StatusOK, &query.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetAlertNotifiers(ngalertEnabled bool) func(*models.ReqContext) response.Response {
|
||||
return func(_ *models.ReqContext) response.Response {
|
||||
if ngalertEnabled {
|
||||
return response.JSON(200, notifier.GetAvailableNotifiers())
|
||||
return response.JSON(http.StatusOK, notifier.GetAvailableNotifiers())
|
||||
}
|
||||
// TODO(codesome): This wont be required in 8.0 since ngalert
|
||||
// will be enabled by default with no disabling. This is to be removed later.
|
||||
return response.JSON(200, alerting.GetNotifiers())
|
||||
return response.JSON(http.StatusOK, alerting.GetNotifiers())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ func (hs *HTTPServer) GetAlertNotificationLookup(c *models.ReqContext) response.
|
||||
result = append(result, dtos.NewAlertNotificationLookup(notification))
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetAlertNotifications(c *models.ReqContext) response.Response {
|
||||
@@ -232,7 +232,7 @@ func (hs *HTTPServer) GetAlertNotifications(c *models.ReqContext) response.Respo
|
||||
result = append(result, dtos.NewAlertNotification(notification))
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getAlertNotificationsInternal(c *models.ReqContext) ([]*models.AlertNotification, error) {
|
||||
@@ -267,7 +267,7 @@ func (hs *HTTPServer) GetAlertNotificationByID(c *models.ReqContext) response.Re
|
||||
return response.Error(404, "Alert notification not found", nil)
|
||||
}
|
||||
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
return response.JSON(http.StatusOK, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetAlertNotificationByUID(c *models.ReqContext) response.Response {
|
||||
@@ -288,7 +288,7 @@ func (hs *HTTPServer) GetAlertNotificationByUID(c *models.ReqContext) response.R
|
||||
return response.Error(404, "Alert notification not found", nil)
|
||||
}
|
||||
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
return response.JSON(http.StatusOK, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) CreateAlertNotification(c *models.ReqContext) response.Response {
|
||||
@@ -309,7 +309,7 @@ func (hs *HTTPServer) CreateAlertNotification(c *models.ReqContext) response.Res
|
||||
return response.Error(500, "Failed to create alert notification", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, dtos.NewAlertNotification(cmd.Result))
|
||||
return response.JSON(http.StatusOK, dtos.NewAlertNotification(cmd.Result))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateAlertNotification(c *models.ReqContext) response.Response {
|
||||
@@ -344,7 +344,7 @@ func (hs *HTTPServer) UpdateAlertNotification(c *models.ReqContext) response.Res
|
||||
return response.Error(500, "Failed to get alert notification", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
return response.JSON(http.StatusOK, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateAlertNotificationByUID(c *models.ReqContext) response.Response {
|
||||
@@ -376,7 +376,7 @@ func (hs *HTTPServer) UpdateAlertNotificationByUID(c *models.ReqContext) respons
|
||||
return response.Error(500, "Failed to get alert notification", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
return response.JSON(http.StatusOK, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) fillWithSecureSettingsData(ctx context.Context, cmd *models.UpdateAlertNotificationCommand) error {
|
||||
@@ -469,7 +469,7 @@ func (hs *HTTPServer) DeleteAlertNotificationByUID(c *models.ReqContext) respons
|
||||
return response.Error(500, "Failed to delete alert notification", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Notification deleted",
|
||||
"id": cmd.DeletedAlertNotificationId,
|
||||
})
|
||||
@@ -536,11 +536,11 @@ func (hs *HTTPServer) PauseAlert(c *models.ReqContext) response.Response {
|
||||
if query.Result.State != models.AlertStatePaused && !dto.Paused {
|
||||
result["state"] = "un-paused"
|
||||
result["message"] = "Alert is already un-paused"
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
} else if query.Result.State == models.AlertStatePaused && dto.Paused {
|
||||
result["state"] = models.AlertStatePaused
|
||||
result["message"] = "Alert is already paused"
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
cmd := models.PauseAlertCommand{
|
||||
@@ -562,7 +562,7 @@ func (hs *HTTPServer) PauseAlert(c *models.ReqContext) response.Response {
|
||||
|
||||
result["state"] = resp
|
||||
result["message"] = "Alert " + pausedState
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// POST /api/admin/pause-all-alerts
|
||||
@@ -592,5 +592,5 @@ func (hs *HTTPServer) PauseAllAlerts(c *models.ReqContext) response.Response {
|
||||
"alertsAffected": updateCmd.ResultCount,
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func (hs *HTTPServer) GetAnnotations(c *models.ReqContext) response.Response {
|
||||
}
|
||||
}
|
||||
|
||||
return response.JSON(200, items)
|
||||
return response.JSON(http.StatusOK, items)
|
||||
}
|
||||
|
||||
type AnnotationError struct {
|
||||
@@ -111,7 +111,7 @@ func (hs *HTTPServer) PostAnnotation(c *models.ReqContext) response.Response {
|
||||
|
||||
startID := item.Id
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Annotation added",
|
||||
"id": startID,
|
||||
})
|
||||
@@ -174,7 +174,7 @@ func (hs *HTTPServer) PostGraphiteAnnotation(c *models.ReqContext) response.Resp
|
||||
return response.Error(500, "Failed to save Graphite annotation", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Graphite annotation added",
|
||||
"id": item.Id,
|
||||
})
|
||||
@@ -433,7 +433,7 @@ func (hs *HTTPServer) GetAnnotationTags(c *models.ReqContext) response.Response
|
||||
return response.Error(500, "Failed to find annotation tags", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, annotations.GetAnnotationTagsResponse{Result: result})
|
||||
return response.JSON(http.StatusOK, annotations.GetAnnotationTagsResponse{Result: result})
|
||||
}
|
||||
|
||||
// AnnotationTypeScopeResolver provides an AttributeScopeResolver able to
|
||||
|
||||
+4
-3
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/serviceaccounts"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
@@ -62,9 +63,9 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
r.Get("/org/teams", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsRead)), hs.Index)
|
||||
r.Get("/org/teams/edit/*", authorize(reqCanAccessTeams, teamsEditAccessEvaluator), hs.Index)
|
||||
r.Get("/org/teams/new", authorize(reqCanAccessTeams, ac.EvalPermission(ac.ActionTeamsCreate)), hs.Index)
|
||||
r.Get("/org/serviceaccounts", middleware.ReqOrgAdmin, hs.Index)
|
||||
r.Get("/org/serviceaccounts/:serviceAccountId", middleware.ReqOrgAdmin, hs.Index)
|
||||
r.Get("/org/apikeys/", reqOrgAdmin, hs.Index)
|
||||
r.Get("/org/serviceaccounts", authorize(reqOrgAdmin, ac.EvalPermission(serviceaccounts.ActionRead)), hs.Index)
|
||||
r.Get("/org/serviceaccounts/:serviceAccountId", authorize(reqOrgAdmin, ac.EvalPermission(serviceaccounts.ActionRead)), hs.Index)
|
||||
r.Get("/org/apikeys/", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionAPIKeyRead)), hs.Index)
|
||||
r.Get("/dashboard/import/", reqSignedIn, hs.Index)
|
||||
r.Get("/configuration", reqGrafanaAdmin, hs.Index)
|
||||
r.Get("/admin", reqGrafanaAdmin, hs.Index)
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ func (hs *HTTPServer) GetAPIKeys(c *models.ReqContext) response.Response {
|
||||
}
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// DeleteAPIKey deletes an API key
|
||||
@@ -107,5 +107,5 @@ func (hs *HTTPServer) AddAPIKey(c *models.ReqContext) response.Response {
|
||||
Key: newKeyInfo.ClientSecret,
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ func (hs *HTTPServer) commentsGet(c *models.ReqContext) response.Response {
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "internal error", err)
|
||||
}
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"comments": items,
|
||||
})
|
||||
}
|
||||
@@ -43,7 +43,7 @@ func (hs *HTTPServer) commentsCreate(c *models.ReqContext) response.Response {
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "internal error", err)
|
||||
}
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"comment": comment,
|
||||
})
|
||||
}
|
||||
|
||||
+12
-12
@@ -73,7 +73,7 @@ func (hs *HTTPServer) TrimDashboard(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
c.TimeRequest(metrics.MApiDashboardGet)
|
||||
return response.JSON(200, dto)
|
||||
return response.JSON(http.StatusOK, dto)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetDashboard(c *models.ReqContext) response.Response {
|
||||
@@ -197,7 +197,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
c.TimeRequest(metrics.MApiDashboardGet)
|
||||
return response.JSON(200, dto)
|
||||
return response.JSON(http.StatusOK, dto)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getAnnotationPermissionsByScope(c *models.ReqContext, actions *dtos.AnnotationActions, scope string) {
|
||||
@@ -283,7 +283,7 @@ func (hs *HTTPServer) deleteDashboard(c *models.ReqContext) response.Response {
|
||||
hs.log.Error("Failed to broadcast delete info", "dashboard", dash.Uid, "error", err)
|
||||
}
|
||||
}
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"title": dash.Title,
|
||||
"message": fmt.Sprintf("Dashboard %s deleted", dash.Title),
|
||||
"id": dash.Id,
|
||||
@@ -406,7 +406,7 @@ func (hs *HTTPServer) postDashboard(c *models.ReqContext, cmd models.SaveDashboa
|
||||
}
|
||||
|
||||
c.TimeRequest(metrics.MApiDashboardSave)
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"status": "success",
|
||||
"slug": dashboard.Slug,
|
||||
"version": dashboard.Version,
|
||||
@@ -427,7 +427,7 @@ func (hs *HTTPServer) GetHomeDashboard(c *models.ReqContext) response.Response {
|
||||
|
||||
if prefsQuery.Result.HomeDashboardId == 0 && len(homePage) > 0 {
|
||||
homePageRedirect := dtos.DashboardRedirect{RedirectUri: homePage}
|
||||
return response.JSON(200, &homePageRedirect)
|
||||
return response.JSON(http.StatusOK, &homePageRedirect)
|
||||
}
|
||||
|
||||
if prefsQuery.Result.HomeDashboardId != 0 {
|
||||
@@ -436,7 +436,7 @@ func (hs *HTTPServer) GetHomeDashboard(c *models.ReqContext) response.Response {
|
||||
if err == nil {
|
||||
url := models.GetDashboardUrl(slugQuery.Result.Uid, slugQuery.Result.Slug)
|
||||
dashRedirect := dtos.DashboardRedirect{RedirectUri: url}
|
||||
return response.JSON(200, &dashRedirect)
|
||||
return response.JSON(http.StatusOK, &dashRedirect)
|
||||
}
|
||||
hs.log.Warn("Failed to get slug from database", "err", err)
|
||||
}
|
||||
@@ -472,7 +472,7 @@ func (hs *HTTPServer) GetHomeDashboard(c *models.ReqContext) response.Response {
|
||||
|
||||
hs.addGettingStartedPanelToHomeDashboard(c, dash.Dashboard)
|
||||
|
||||
return response.JSON(200, &dash)
|
||||
return response.JSON(http.StatusOK, &dash)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) addGettingStartedPanelToHomeDashboard(c *models.ReqContext, dash *simplejson.Json) {
|
||||
@@ -540,7 +540,7 @@ func (hs *HTTPServer) GetDashboardVersions(c *models.ReqContext) response.Respon
|
||||
}
|
||||
}
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
// GetDashboardVersion returns the dashboard version with the given ID.
|
||||
@@ -583,7 +583,7 @@ func (hs *HTTPServer) GetDashboardVersion(c *models.ReqContext) response.Respons
|
||||
CreatedBy: creator,
|
||||
}
|
||||
|
||||
return response.JSON(200, dashVersionMeta)
|
||||
return response.JSON(http.StatusOK, dashVersionMeta)
|
||||
}
|
||||
|
||||
// POST /api/dashboards/calculate-diff performs diffs on two dashboards
|
||||
@@ -658,10 +658,10 @@ func (hs *HTTPServer) CalculateDashboardDiff(c *models.ReqContext) response.Resp
|
||||
}
|
||||
|
||||
if options.DiffType == dashdiffs.DiffDelta {
|
||||
return response.Respond(200, result.Delta).SetHeader("Content-Type", "application/json")
|
||||
return response.Respond(http.StatusOK, result.Delta).SetHeader("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
return response.Respond(200, result.Delta).SetHeader("Content-Type", "text/html")
|
||||
return response.Respond(http.StatusOK, result.Delta).SetHeader("Content-Type", "text/html")
|
||||
}
|
||||
|
||||
// RestoreDashboardVersion restores a dashboard to the given version.
|
||||
@@ -713,5 +713,5 @@ func (hs *HTTPServer) GetDashboardTags(c *models.ReqContext) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, query.Result)
|
||||
c.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) response.
|
||||
filteredAcls = append(filteredAcls, perm)
|
||||
}
|
||||
|
||||
return response.JSON(200, filteredAcls)
|
||||
return response.JSON(http.StatusOK, filteredAcls)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext) response.Response {
|
||||
|
||||
@@ -24,7 +24,7 @@ var client = &http.Client{
|
||||
}
|
||||
|
||||
func GetSharingOptions(c *models.ReqContext) {
|
||||
c.JSON(200, util.DynMap{
|
||||
c.JSON(http.StatusOK, util.DynMap{
|
||||
"externalSnapshotURL": setting.ExternalSnapshotUrl,
|
||||
"externalSnapshotName": setting.ExternalSnapshotName,
|
||||
"externalEnabled": setting.ExternalEnabled,
|
||||
@@ -138,7 +138,7 @@ func (hs *HTTPServer) CreateDashboardSnapshot(c *models.ReqContext) response.Res
|
||||
return nil
|
||||
}
|
||||
|
||||
c.JSON(200, util.DynMap{
|
||||
c.JSON(http.StatusOK, util.DynMap{
|
||||
"key": cmd.Key,
|
||||
"deleteKey": cmd.DeleteKey,
|
||||
"url": url,
|
||||
@@ -181,7 +181,7 @@ func (hs *HTTPServer) GetDashboardSnapshot(c *models.ReqContext) response.Respon
|
||||
|
||||
metrics.MApiDashboardSnapshotGet.Inc()
|
||||
|
||||
return response.JSON(200, dto).SetHeader("Cache-Control", "public, max-age=3600")
|
||||
return response.JSON(http.StatusOK, dto).SetHeader("Cache-Control", "public, max-age=3600")
|
||||
}
|
||||
|
||||
func deleteExternalDashboardSnapshot(externalUrl string) error {
|
||||
@@ -242,7 +242,7 @@ func (hs *HTTPServer) DeleteDashboardSnapshotByDeleteKey(c *models.ReqContext) r
|
||||
return response.Error(500, "Failed to delete dashboard snapshot", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Snapshot deleted. It might take an hour before it's cleared from any CDN caches.",
|
||||
"id": query.Result.Id,
|
||||
})
|
||||
@@ -290,7 +290,7 @@ func (hs *HTTPServer) DeleteDashboardSnapshot(c *models.ReqContext) response.Res
|
||||
return response.Error(500, "Failed to delete dashboard snapshot", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Snapshot deleted. It might take an hour before it's cleared from any CDN caches.",
|
||||
"id": query.Result.Id,
|
||||
})
|
||||
@@ -333,5 +333,5 @@ func (hs *HTTPServer) SearchDashboardSnapshots(c *models.ReqContext) response.Re
|
||||
}
|
||||
}
|
||||
|
||||
return response.JSON(200, dtos)
|
||||
return response.JSON(http.StatusOK, dtos)
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ func (hs *HTTPServer) GetDataSources(c *models.ReqContext) response.Response {
|
||||
|
||||
sort.Sort(result)
|
||||
|
||||
return response.JSON(200, &result)
|
||||
return response.JSON(http.StatusOK, &result)
|
||||
}
|
||||
|
||||
// GET /api/datasources/:id
|
||||
@@ -102,7 +102,7 @@ func (hs *HTTPServer) GetDataSourceById(c *models.ReqContext) response.Response
|
||||
// Add accesscontrol metadata
|
||||
dto.AccessControl = hs.getAccessControlMetadata(c, c.OrgId, datasources.ScopePrefix, dto.UID)
|
||||
|
||||
return response.JSON(200, &dto)
|
||||
return response.JSON(http.StatusOK, &dto)
|
||||
}
|
||||
|
||||
// DELETE /api/datasources/:id
|
||||
@@ -161,7 +161,7 @@ func (hs *HTTPServer) GetDataSourceByUID(c *models.ReqContext) response.Response
|
||||
// Add accesscontrol metadata
|
||||
dto.AccessControl = hs.getAccessControlMetadata(c, c.OrgId, datasources.ScopePrefix, dto.UID)
|
||||
|
||||
return response.JSON(200, &dto)
|
||||
return response.JSON(http.StatusOK, &dto)
|
||||
}
|
||||
|
||||
// DELETE /api/datasources/uid/:uid
|
||||
@@ -193,7 +193,7 @@ func (hs *HTTPServer) DeleteDataSourceByUID(c *models.ReqContext) response.Respo
|
||||
|
||||
hs.Live.HandleDatasourceDelete(c.OrgId, ds.Uid)
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Data source deleted",
|
||||
"id": ds.Id,
|
||||
})
|
||||
@@ -227,7 +227,7 @@ func (hs *HTTPServer) DeleteDataSourceByName(c *models.ReqContext) response.Resp
|
||||
|
||||
hs.Live.HandleDatasourceDelete(c.OrgId, getCmd.Result.Uid)
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Data source deleted",
|
||||
"id": getCmd.Result.Id,
|
||||
})
|
||||
@@ -266,7 +266,7 @@ func (hs *HTTPServer) AddDataSource(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
ds := convertModelToDtos(cmd.Result)
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Datasource added",
|
||||
"id": cmd.Result.Id,
|
||||
"name": cmd.Result.Name,
|
||||
@@ -331,7 +331,7 @@ func (hs *HTTPServer) UpdateDataSource(c *models.ReqContext) response.Response {
|
||||
|
||||
hs.Live.HandleDatasourceUpdate(c.OrgId, datasourceDTO.UID)
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Datasource updated",
|
||||
"id": cmd.Id,
|
||||
"name": cmd.Name,
|
||||
@@ -409,7 +409,7 @@ func (hs *HTTPServer) GetDataSourceByName(c *models.ReqContext) response.Respons
|
||||
}
|
||||
|
||||
dto := convertModelToDtos(filtered[0])
|
||||
return response.JSON(200, &dto)
|
||||
return response.JSON(http.StatusOK, &dto)
|
||||
}
|
||||
|
||||
// Get /api/datasources/id/:name
|
||||
@@ -428,7 +428,7 @@ func (hs *HTTPServer) GetDataSourceIdByName(c *models.ReqContext) response.Respo
|
||||
Id: ds.Id,
|
||||
}
|
||||
|
||||
return response.JSON(200, &dtos)
|
||||
return response.JSON(http.StatusOK, &dtos)
|
||||
}
|
||||
|
||||
// /api/datasources/:id/resources/*
|
||||
|
||||
@@ -167,6 +167,20 @@ import (
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
|
||||
// swagger:route GET /datasources/proxy/uid/{datasource_uid}/{datasource_proxy_route} datasources datasourceProxyGETByUIDcalls
|
||||
//
|
||||
// Data source proxy GET calls.
|
||||
//
|
||||
// Proxies all calls to the actual data source.
|
||||
//
|
||||
// Responses:
|
||||
// 200:
|
||||
// 400: badRequestError
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
|
||||
// swagger:route POST /datasources/proxy/{datasource_id}/{datasource_proxy_route} datasources datasourceProxyPOSTcalls
|
||||
//
|
||||
// Data source proxy POST calls.
|
||||
@@ -182,6 +196,21 @@ import (
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
|
||||
// swagger:route POST /datasources/proxy/uid/{datasource_uid}/{datasource_proxy_route} datasources datasourceProxyPOSTByUIDcalls
|
||||
//
|
||||
// Data source proxy POST calls.
|
||||
//
|
||||
// Proxies all calls to the actual data source. The data source should support POST methods for the specific path and role as defined
|
||||
//
|
||||
// Responses:
|
||||
// 201:
|
||||
// 202:
|
||||
// 400: badRequestError
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
|
||||
// swagger:route DELETE /datasources/proxy/{datasource_id}/{datasource_proxy_route} datasources datasourceProxyDELETEcalls
|
||||
//
|
||||
// Data source proxy DELETE calls.
|
||||
@@ -196,6 +225,20 @@ import (
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
|
||||
// swagger:route DELETE /datasources/proxy/uid/{datasource_uid}/{datasource_proxy_route} datasources datasourceProxyDELETEByUIDcalls
|
||||
//
|
||||
// Data source proxy DELETE calls.
|
||||
//
|
||||
// Proxies all calls to the actual data source.
|
||||
//
|
||||
// Responses:
|
||||
// 202:
|
||||
// 400: badRequestError
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
|
||||
// swagger:route POST /tsdb/query datasources queryDatasource
|
||||
//
|
||||
// Query metrics.
|
||||
@@ -227,7 +270,7 @@ type DatasourceID struct {
|
||||
DatasourceID string `json:"datasource_id"`
|
||||
}
|
||||
|
||||
// swagger:parameters deleteDatasourceByUID getDatasourceByUID
|
||||
// swagger:parameters deleteDatasourceByUID getDatasourceByUID datasourceProxyGETByUIDcalls datasourceProxyPOSTByUIDcalls datasourceProxyDELETEByUIDcalls
|
||||
type DatasourceUID struct {
|
||||
// in:path
|
||||
// required:true
|
||||
@@ -241,7 +284,8 @@ type DatasourceName struct {
|
||||
DatasourceName string `json:"datasource_name"`
|
||||
}
|
||||
|
||||
// swagger:parameters datasourceProxyGETcalls datasourceProxyPOSTcalls datasourceProxyDELETEcalls
|
||||
// swagger:parameters datasourceProxyGETcalls datasourceProxyPOSTcalls datasourceProxyDELETEcalls datasourceProxyGETByUIDcalls
|
||||
// swagger:parameters datasourceProxyPOSTByUIDcalls datasourceProxyDELETEByUIDcalls
|
||||
type DatasourceProxyRouteParam struct {
|
||||
// in:path
|
||||
// required:true
|
||||
|
||||
+6
-6
@@ -34,7 +34,7 @@ func (hs *HTTPServer) GetFolders(c *models.ReqContext) response.Response {
|
||||
})
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response {
|
||||
@@ -44,7 +44,7 @@ func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.Id, c.OrgId, c.SignedInUser)
|
||||
return response.JSON(200, hs.toFolderDto(c.Req.Context(), g, folder))
|
||||
return response.JSON(http.StatusOK, hs.toFolderDto(c.Req.Context(), g, folder))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response {
|
||||
@@ -58,7 +58,7 @@ func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.Id, c.OrgId, c.SignedInUser)
|
||||
return response.JSON(200, hs.toFolderDto(c.Req.Context(), g, folder))
|
||||
return response.JSON(http.StatusOK, hs.toFolderDto(c.Req.Context(), g, folder))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) CreateFolder(c *models.ReqContext) response.Response {
|
||||
@@ -72,7 +72,7 @@ func (hs *HTTPServer) CreateFolder(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), folder.Id, c.OrgId, c.SignedInUser)
|
||||
return response.JSON(200, hs.toFolderDto(c.Req.Context(), g, folder))
|
||||
return response.JSON(http.StatusOK, hs.toFolderDto(c.Req.Context(), g, folder))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateFolder(c *models.ReqContext) response.Response {
|
||||
@@ -86,7 +86,7 @@ func (hs *HTTPServer) UpdateFolder(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
g := guardian.New(c.Req.Context(), cmd.Result.Id, c.OrgId, c.SignedInUser)
|
||||
return response.JSON(200, hs.toFolderDto(c.Req.Context(), g, cmd.Result))
|
||||
return response.JSON(http.StatusOK, hs.toFolderDto(c.Req.Context(), g, cmd.Result))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) DeleteFolder(c *models.ReqContext) response.Response { // temporarily adding this function to HTTPServer, will be removed from HTTPServer when librarypanels featuretoggle is removed
|
||||
@@ -103,7 +103,7 @@ func (hs *HTTPServer) DeleteFolder(c *models.ReqContext) response.Response { //
|
||||
return apierrors.ToFolderErrorResponse(err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"title": f.Title,
|
||||
"message": fmt.Sprintf("Folder %s deleted", f.Title),
|
||||
"id": f.Id,
|
||||
|
||||
@@ -55,7 +55,7 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Res
|
||||
filteredAcls = append(filteredAcls, perm)
|
||||
}
|
||||
|
||||
return response.JSON(200, filteredAcls)
|
||||
return response.JSON(http.StatusOK, filteredAcls)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Response {
|
||||
@@ -141,7 +141,7 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Res
|
||||
return response.Error(500, "Failed to create permission", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "Folder permissions updated",
|
||||
"id": folder.Id,
|
||||
"title": folder.Title,
|
||||
|
||||
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -21,7 +22,7 @@ func (hs *HTTPServer) GetFrontendSettings(c *models.ReqContext) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, settings)
|
||||
c.JSON(http.StatusOK, settings)
|
||||
}
|
||||
|
||||
// getFrontendSettingsMap returns a json object with all the settings needed for front end initialisation.
|
||||
@@ -113,6 +114,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
|
||||
"rudderstackDataPlaneUrl": setting.RudderstackDataPlaneUrl,
|
||||
"rudderstackSdkUrl": setting.RudderstackSdkUrl,
|
||||
"rudderstackConfigUrl": setting.RudderstackConfigUrl,
|
||||
"feedbackLinksEnabled": hs.Cfg.FeedbackLinksEnabled,
|
||||
"applicationInsightsConnectionString": hs.Cfg.ApplicationInsightsConnectionString,
|
||||
"applicationInsightsEndpointUrl": hs.Cfg.ApplicationInsightsEndpointUrl,
|
||||
"disableLoginForm": setting.DisableLoginForm,
|
||||
|
||||
+23
-6
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -149,8 +150,11 @@ func (hs *HTTPServer) getAppLinks(c *models.ReqContext) ([]*dtos.NavLink, error)
|
||||
}
|
||||
|
||||
func enableServiceAccount(hs *HTTPServer, c *models.ReqContext) bool {
|
||||
return (c.OrgRole == models.ROLE_ADMIN || (hs.Cfg.EditorsCanAdmin && c.OrgRole == models.ROLE_EDITOR)) &&
|
||||
hs.Features.IsEnabled(featuremgmt.FlagServiceAccounts)
|
||||
if !hs.Features.IsEnabled(featuremgmt.FlagServiceAccounts) {
|
||||
return false
|
||||
}
|
||||
hasAccess := ac.HasAccess(hs.AccessControl, c)
|
||||
return hasAccess(ac.ReqOrgAdmin, serviceAccountAccessEvaluator)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) ReqCanAdminTeams(c *models.ReqContext) bool {
|
||||
@@ -230,7 +234,7 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
|
||||
uaVisibleForOrg := hs.Cfg.UnifiedAlerting.IsEnabled() && !uaIsDisabledForOrg
|
||||
|
||||
if setting.AlertingEnabled != nil && *setting.AlertingEnabled || uaVisibleForOrg {
|
||||
navTree = append(navTree, hs.buildAlertNavLinks(c, uaVisibleForOrg)...)
|
||||
navTree = append(navTree, hs.buildAlertNavLinks(c, uaVisibleForOrg, hasEditPerm)...)
|
||||
}
|
||||
|
||||
appLinks, err := hs.getAppLinks(c)
|
||||
@@ -291,7 +295,7 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
|
||||
})
|
||||
}
|
||||
|
||||
if c.OrgRole == models.ROLE_ADMIN {
|
||||
if hasAccess(ac.ReqOrgAdmin, apiKeyAccessEvaluator) {
|
||||
configNodes = append(configNodes, &dtos.NavLink{
|
||||
Text: "API keys",
|
||||
Id: "apikeys",
|
||||
@@ -476,7 +480,7 @@ func (hs *HTTPServer) buildDashboardNavLinks(c *models.ReqContext, hasEditPerm b
|
||||
return dashboardChildNavs
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) buildAlertNavLinks(c *models.ReqContext, uaVisibleForOrg bool) []*dtos.NavLink {
|
||||
func (hs *HTTPServer) buildAlertNavLinks(c *models.ReqContext, uaVisibleForOrg bool, hasEditPerm bool) []*dtos.NavLink {
|
||||
hasAccess := ac.HasAccess(hs.AccessControl, c)
|
||||
var alertChildNavs []*dtos.NavLink
|
||||
|
||||
@@ -513,6 +517,19 @@ func (hs *HTTPServer) buildAlertNavLinks(c *models.ReqContext, uaVisibleForOrg b
|
||||
})
|
||||
}
|
||||
|
||||
if hs.Features.IsEnabled(featuremgmt.FlagNewNavigation) {
|
||||
if uaVisibleForOrg && hasEditPerm && hasAccess(ac.ReqSignedIn, ac.EvalPermission(ac.ActionAlertingRuleCreate)) {
|
||||
alertChildNavs = append(alertChildNavs, &dtos.NavLink{
|
||||
Text: "Divider", Divider: true, Id: "divider", HideFromTabs: true,
|
||||
})
|
||||
|
||||
alertChildNavs = append(alertChildNavs, &dtos.NavLink{
|
||||
Text: "Alert rule", SubTitle: "Create an alert rule", Id: "alert",
|
||||
Icon: "plus", Url: hs.Cfg.AppSubURL + "/alerting/new", HideFromTabs: true, ShowIconInNavbar: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(alertChildNavs) > 0 {
|
||||
return []*dtos.NavLink{
|
||||
{
|
||||
@@ -734,7 +751,7 @@ func (hs *HTTPServer) Index(c *models.ReqContext) {
|
||||
c.Handle(hs.Cfg, 500, "Failed to get settings", err)
|
||||
return
|
||||
}
|
||||
c.HTML(200, "index", data)
|
||||
c.HTML(http.StatusOK, "index", data)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) NotFoundHandler(c *models.ReqContext) {
|
||||
|
||||
@@ -314,7 +314,7 @@ func (hs *HTTPServer) GetUserFromLDAP(c *models.ReqContext) response.Response {
|
||||
return response.Error(http.StatusBadRequest, "Unable to find the teams for this user", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, u)
|
||||
return response.JSON(http.StatusOK, u)
|
||||
}
|
||||
|
||||
// splitName receives the full name of a user and splits it into two parts: A name and a surname.
|
||||
|
||||
+11
-15
@@ -1,6 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -146,13 +147,11 @@ func TestGetUserFromLDAPAPIEndpoint_OrgNotfound(t *testing.T) {
|
||||
|
||||
require.Equal(t, http.StatusBadRequest, sc.resp.Code)
|
||||
|
||||
expected := `
|
||||
{
|
||||
"error": "unable to find organization with ID '2'",
|
||||
"message": "An organization was not found - Please verify your LDAP configuration"
|
||||
}
|
||||
`
|
||||
assert.JSONEq(t, expected, sc.resp.Body.String())
|
||||
var res map[string]interface{}
|
||||
err := json.Unmarshal(sc.resp.Body.Bytes(), &res)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "unable to find organization with ID '2'", res["error"])
|
||||
assert.Equal(t, "An organization was not found - Please verify your LDAP configuration", res["message"])
|
||||
}
|
||||
|
||||
func TestGetUserFromLDAPAPIEndpoint(t *testing.T) {
|
||||
@@ -470,14 +469,11 @@ func TestPostSyncUserWithLDAPAPIEndpoint_WhenGrafanaAdmin(t *testing.T) {
|
||||
}, &sqlstoremock)
|
||||
assert.Equal(t, http.StatusBadRequest, sc.resp.Code)
|
||||
|
||||
expected := `
|
||||
{
|
||||
"error": "did not find a user",
|
||||
"message": "Refusing to sync grafana super admin \"ldap-daniel\" - it would be disabled"
|
||||
}
|
||||
`
|
||||
|
||||
assert.JSONEq(t, expected, sc.resp.Body.String())
|
||||
var res map[string]interface{}
|
||||
err := json.Unmarshal(sc.resp.Body.Bytes(), &res)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "did not find a user", res["error"])
|
||||
assert.Equal(t, "Refusing to sync grafana super admin \"ldap-daniel\" - it would be disabled", res["message"])
|
||||
}
|
||||
|
||||
func TestPostSyncUserWithLDAPAPIEndpoint_WhenUserNotInLDAP(t *testing.T) {
|
||||
|
||||
+4
-4
@@ -85,7 +85,7 @@ func (hs *HTTPServer) LoginView(c *models.ReqContext) {
|
||||
urlParams := c.Req.URL.Query()
|
||||
if _, disableAutoLogin := urlParams["disableAutoLogin"]; disableAutoLogin {
|
||||
hs.log.Debug("Auto login manually disabled")
|
||||
c.HTML(200, getViewIndex(), viewData)
|
||||
c.HTML(http.StatusOK, getViewIndex(), viewData)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ func (hs *HTTPServer) LoginView(c *models.ReqContext) {
|
||||
// to login again via OAuth and enter to a redirect loop
|
||||
cookies.DeleteCookie(c.Resp, loginErrorCookieName, hs.CookieOptionsFromCfg)
|
||||
viewData.Settings["loginError"] = loginError
|
||||
c.HTML(200, getViewIndex(), viewData)
|
||||
c.HTML(http.StatusOK, getViewIndex(), viewData)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ func (hs *HTTPServer) LoginView(c *models.ReqContext) {
|
||||
return
|
||||
}
|
||||
|
||||
c.HTML(200, getViewIndex(), viewData)
|
||||
c.HTML(http.StatusOK, getViewIndex(), viewData)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) tryOAuthAutoLogin(c *models.ReqContext) bool {
|
||||
@@ -167,7 +167,7 @@ func (hs *HTTPServer) tryOAuthAutoLogin(c *models.ReqContext) bool {
|
||||
|
||||
func (hs *HTTPServer) LoginAPIPing(c *models.ReqContext) response.Response {
|
||||
if c.IsSignedIn || c.IsAnonymous {
|
||||
return response.JSON(200, "Logged in")
|
||||
return response.JSON(http.StatusOK, "Logged in")
|
||||
}
|
||||
|
||||
return response.Error(401, "Unauthorized", nil)
|
||||
|
||||
+17
-24
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -241,15 +242,14 @@ func TestAPIEndpoint_Metrics_QueryMetricsFromDashboard(t *testing.T) {
|
||||
strings.NewReader(queryDatasourceInput),
|
||||
t,
|
||||
)
|
||||
|
||||
assert.Equal(t, http.StatusBadRequest, response.Code)
|
||||
assert.JSONEq(
|
||||
t,
|
||||
fmt.Sprintf(
|
||||
"{\"error\":\"%[1]s\",\"message\":\"%[1]s\"}",
|
||||
models.ErrDashboardOrPanelIdentifierNotSet,
|
||||
),
|
||||
response.Body.String(),
|
||||
)
|
||||
|
||||
var res map[string]interface{}
|
||||
err := json.Unmarshal(response.Body.Bytes(), &res)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, models.ErrDashboardOrPanelIdentifierNotSet.Error(), res["error"])
|
||||
assert.Equal(t, models.ErrDashboardOrPanelIdentifierNotSet.Error(), res["message"])
|
||||
})
|
||||
|
||||
t.Run("Cannot query without a valid orgid", func(t *testing.T) {
|
||||
@@ -261,14 +261,10 @@ func TestAPIEndpoint_Metrics_QueryMetricsFromDashboard(t *testing.T) {
|
||||
t,
|
||||
)
|
||||
assert.Equal(t, http.StatusBadRequest, response.Code)
|
||||
assert.JSONEq(
|
||||
t,
|
||||
fmt.Sprintf(
|
||||
"{\"error\":\"%[1]s\",\"message\":\"%[1]s\"}",
|
||||
models.ErrDashboardOrPanelIdentifierNotSet,
|
||||
),
|
||||
response.Body.String(),
|
||||
)
|
||||
var res map[string]interface{}
|
||||
assert.NoError(t, json.Unmarshal(response.Body.Bytes(), &res))
|
||||
assert.Equal(t, models.ErrDashboardOrPanelIdentifierNotSet.Error(), res["error"])
|
||||
assert.Equal(t, models.ErrDashboardOrPanelIdentifierNotSet.Error(), res["message"])
|
||||
})
|
||||
|
||||
t.Run("Cannot query without a valid dashboard or panel ID", func(t *testing.T) {
|
||||
@@ -280,14 +276,11 @@ func TestAPIEndpoint_Metrics_QueryMetricsFromDashboard(t *testing.T) {
|
||||
t,
|
||||
)
|
||||
assert.Equal(t, http.StatusBadRequest, response.Code)
|
||||
assert.JSONEq(
|
||||
t,
|
||||
fmt.Sprintf(
|
||||
"{\"error\":\"%[1]s\",\"message\":\"%[1]s\"}",
|
||||
models.ErrDashboardOrPanelIdentifierNotSet,
|
||||
),
|
||||
response.Body.String(),
|
||||
)
|
||||
|
||||
var res map[string]interface{}
|
||||
assert.NoError(t, json.Unmarshal(response.Body.Bytes(), &res))
|
||||
assert.Equal(t, models.ErrDashboardOrPanelIdentifierNotSet.Error(), res["error"])
|
||||
assert.Equal(t, models.ErrDashboardOrPanelIdentifierNotSet.Error(), res["message"])
|
||||
})
|
||||
|
||||
t.Run("Cannot query when ValidatedQueries is disabled", func(t *testing.T) {
|
||||
|
||||
+4
-4
@@ -54,7 +54,7 @@ func (hs *HTTPServer) GetOrgByName(c *models.ReqContext) response.Response {
|
||||
},
|
||||
}
|
||||
|
||||
return response.JSON(200, &result)
|
||||
return response.JSON(http.StatusOK, &result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getOrgHelper(ctx context.Context, orgID int64) response.Response {
|
||||
@@ -81,7 +81,7 @@ func (hs *HTTPServer) getOrgHelper(ctx context.Context, orgID int64) response.Re
|
||||
},
|
||||
}
|
||||
|
||||
return response.JSON(200, &result)
|
||||
return response.JSON(http.StatusOK, &result)
|
||||
}
|
||||
|
||||
// POST /api/orgs
|
||||
@@ -105,7 +105,7 @@ func (hs *HTTPServer) CreateOrg(c *models.ReqContext) response.Response {
|
||||
|
||||
metrics.MApiOrgCreate.Inc()
|
||||
|
||||
return response.JSON(200, &util.DynMap{
|
||||
return response.JSON(http.StatusOK, &util.DynMap{
|
||||
"orgId": cmd.Result.Id,
|
||||
"message": "Organization created",
|
||||
})
|
||||
@@ -226,5 +226,5 @@ func (hs *HTTPServer) SearchOrgs(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Failed to search orgs", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func (hs *HTTPServer) GetPendingOrgInvites(c *models.ReqContext) response.Respon
|
||||
invite.Url = setting.ToAbsUrl("invite/" + invite.Code)
|
||||
}
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) AddOrgInvite(c *models.ReqContext) response.Response {
|
||||
@@ -131,7 +131,7 @@ func (hs *HTTPServer) inviteExistingUserToOrg(c *models.ReqContext, user *models
|
||||
}
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": fmt.Sprintf("Existing Grafana user %s added to org %s", user.NameOrFallback(), c.OrgName),
|
||||
"userId": user.Id,
|
||||
})
|
||||
@@ -162,7 +162,7 @@ func (hs *HTTPServer) GetInviteInfoByCode(c *models.ReqContext) response.Respons
|
||||
return response.Error(404, "Invite not found", nil)
|
||||
}
|
||||
|
||||
return response.JSON(200, dtos.InviteInfo{
|
||||
return response.JSON(http.StatusOK, dtos.InviteInfo{
|
||||
Email: invite.Email,
|
||||
Name: invite.Name,
|
||||
Username: invite.Email,
|
||||
@@ -225,7 +225,7 @@ func (hs *HTTPServer) CompleteInvite(c *models.ReqContext) response.Response {
|
||||
metrics.MApiUserSignUpCompleted.Inc()
|
||||
metrics.MApiUserSignUpInvite.Inc()
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "User created and logged in",
|
||||
"id": user.Id,
|
||||
})
|
||||
|
||||
@@ -64,7 +64,7 @@ func (hs *HTTPServer) addOrgUserHelper(ctx context.Context, cmd models.AddOrgUse
|
||||
return response.Error(500, "Could not add user to organization", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "User added to organization",
|
||||
"userId": cmd.UserId,
|
||||
})
|
||||
@@ -83,7 +83,7 @@ func (hs *HTTPServer) GetOrgUsersForCurrentOrg(c *models.ReqContext) response.Re
|
||||
return response.Error(500, "Failed to get users for current organization", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// GET /api/org/users/lookup
|
||||
@@ -109,7 +109,7 @@ func (hs *HTTPServer) GetOrgUsersForCurrentOrgLookup(c *models.ReqContext) respo
|
||||
})
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
// GET /api/orgs/:orgId/users
|
||||
@@ -130,7 +130,7 @@ func (hs *HTTPServer) GetOrgUsers(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Failed to get users for organization", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getOrgUsersHelper(c *models.ReqContext, query *models.GetOrgUsersQuery, signedInUser *models.SignedInUser) ([]*models.OrgUserDTO, error) {
|
||||
@@ -201,7 +201,7 @@ func (hs *HTTPServer) SearchOrgUsersWithPaging(c *models.ReqContext) response.Re
|
||||
query.Result.Page = page
|
||||
query.Result.PerPage = perPage
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
// PATCH /api/org/users/:userId
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ func (hs *HTTPServer) SendResetPasswordEmail(c *models.ReqContext) response.Resp
|
||||
|
||||
if err := hs.SQLStore.GetUserByLogin(c.Req.Context(), &userQuery); err != nil {
|
||||
c.Logger.Info("Requested password reset for user that was not found", "user", userQuery.LoginOrEmail)
|
||||
return response.Error(200, "Email sent", err)
|
||||
return response.Error(http.StatusOK, "Email sent", err)
|
||||
}
|
||||
|
||||
emailCmd := models.SendResetPasswordEmailCommand{User: userQuery.Result}
|
||||
|
||||
+7
-7
@@ -54,7 +54,7 @@ func (hs *HTTPServer) SearchPlaylists(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Search failed", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, searchQuery.Result)
|
||||
return response.JSON(http.StatusOK, searchQuery.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetPlaylist(c *models.ReqContext) response.Response {
|
||||
@@ -78,7 +78,7 @@ func (hs *HTTPServer) GetPlaylist(c *models.ReqContext) response.Response {
|
||||
Items: playlistDTOs,
|
||||
}
|
||||
|
||||
return response.JSON(200, dto)
|
||||
return response.JSON(http.StatusOK, dto)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) LoadPlaylistItemDTOs(ctx context.Context, id int64) ([]models.PlaylistItemDTO, error) {
|
||||
@@ -125,7 +125,7 @@ func (hs *HTTPServer) GetPlaylistItems(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Could not load playlist items", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, playlistDTOs)
|
||||
return response.JSON(http.StatusOK, playlistDTOs)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetPlaylistDashboards(c *models.ReqContext) response.Response {
|
||||
@@ -139,7 +139,7 @@ func (hs *HTTPServer) GetPlaylistDashboards(c *models.ReqContext) response.Respo
|
||||
return response.Error(500, "Could not load dashboards", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, playlists)
|
||||
return response.JSON(http.StatusOK, playlists)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) DeletePlaylist(c *models.ReqContext) response.Response {
|
||||
@@ -153,7 +153,7 @@ func (hs *HTTPServer) DeletePlaylist(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Failed to delete playlist", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, "")
|
||||
return response.JSON(http.StatusOK, "")
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) CreatePlaylist(c *models.ReqContext) response.Response {
|
||||
@@ -167,7 +167,7 @@ func (hs *HTTPServer) CreatePlaylist(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Failed to create playlist", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, cmd.Result)
|
||||
return response.JSON(http.StatusOK, cmd.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdatePlaylist(c *models.ReqContext) response.Response {
|
||||
@@ -192,5 +192,5 @@ func (hs *HTTPServer) UpdatePlaylist(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
cmd.Result.Items = playlistDTOs
|
||||
return response.JSON(200, cmd.Result)
|
||||
return response.JSON(http.StatusOK, cmd.Result)
|
||||
}
|
||||
|
||||
+5
-5
@@ -111,7 +111,7 @@ func (hs *HTTPServer) GetPluginList(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
sort.Sort(result)
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetPluginSettingByID(c *models.ReqContext) response.Response {
|
||||
@@ -163,7 +163,7 @@ func (hs *HTTPServer) GetPluginSettingByID(c *models.ReqContext) response.Respon
|
||||
dto.HasUpdate = true
|
||||
}
|
||||
|
||||
return response.JSON(200, dto)
|
||||
return response.JSON(http.StatusOK, dto)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdatePluginSetting(c *models.ReqContext) response.Response {
|
||||
@@ -217,7 +217,7 @@ func (hs *HTTPServer) GetPluginMarkdown(c *models.ReqContext) response.Response
|
||||
}
|
||||
}
|
||||
|
||||
resp := response.Respond(200, content)
|
||||
resp := response.Respond(http.StatusOK, content)
|
||||
resp.SetHeader("Content-Type", "text/plain; charset=utf-8")
|
||||
return resp
|
||||
}
|
||||
@@ -343,7 +343,7 @@ func (hs *HTTPServer) CheckHealth(c *models.ReqContext) response.Response {
|
||||
return response.JSON(503, payload)
|
||||
}
|
||||
|
||||
return response.JSON(200, payload)
|
||||
return response.JSON(http.StatusOK, payload)
|
||||
}
|
||||
|
||||
// CallResource passes a resource call from a plugin to the backend plugin.
|
||||
@@ -354,7 +354,7 @@ func (hs *HTTPServer) CallResource(c *models.ReqContext) {
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetPluginErrorsList(_ *models.ReqContext) response.Response {
|
||||
return response.JSON(200, hs.pluginErrorResolver.PluginErrors())
|
||||
return response.JSON(http.StatusOK, hs.pluginErrorResolver.PluginErrors())
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) InstallPlugin(c *models.ReqContext) response.Response {
|
||||
|
||||
@@ -56,7 +56,7 @@ func (hs *HTTPServer) getPreferencesFor(ctx context.Context, orgID, userID, team
|
||||
dto.QueryHistory = prefsQuery.Result.JsonData.QueryHistory
|
||||
}
|
||||
|
||||
return response.JSON(200, &dto)
|
||||
return response.JSON(http.StatusOK, &dto)
|
||||
}
|
||||
|
||||
// PUT /api/user/preferences
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@ func (hs *HTTPServer) getOrgQuotasHelper(c *models.ReqContext, orgID int64) resp
|
||||
return response.Error(500, "Failed to get org quotas", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateOrgQuota(c *models.ReqContext) response.Response {
|
||||
@@ -76,7 +76,7 @@ func (hs *HTTPServer) GetUserQuotas(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Failed to get org quotas", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateUserQuota(c *models.ReqContext) response.Response {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
@@ -73,7 +74,15 @@ func (r *NormalResponse) ErrMessage() string {
|
||||
|
||||
func (r *NormalResponse) WriteTo(ctx *models.ReqContext) {
|
||||
if r.err != nil {
|
||||
ctx.Logger.Error(r.errMessage, "error", r.err, "remote_addr", ctx.RemoteAddr())
|
||||
v := map[string]interface{}{}
|
||||
traceID := tracing.TraceIDFromContext(ctx.Req.Context(), false)
|
||||
if err := json.Unmarshal(r.body.Bytes(), &v); err == nil {
|
||||
v["traceID"] = traceID
|
||||
if b, err := json.Marshal(v); err == nil {
|
||||
r.body = bytes.NewBuffer(b)
|
||||
}
|
||||
}
|
||||
ctx.Logger.Error(r.errMessage, "error", r.err, "remote_addr", ctx.RemoteAddr(), "traceID", traceID)
|
||||
}
|
||||
|
||||
header := ctx.Resp.Header()
|
||||
@@ -171,7 +180,7 @@ func JSONStreaming(status int, body interface{}) StreamingResponse {
|
||||
func Success(message string) *NormalResponse {
|
||||
resp := make(map[string]interface{})
|
||||
resp["message"] = message
|
||||
return JSON(200, resp)
|
||||
return JSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
// Error creates an error response.
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ func (hs *HTTPServer) Search(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
c.TimeRequest(metrics.MApiDashboardSearch)
|
||||
return response.JSON(200, searchQuery.Result)
|
||||
return response.JSON(http.StatusOK, searchQuery.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) ListSortOptions(c *models.ReqContext) response.Response {
|
||||
|
||||
@@ -47,7 +47,7 @@ func (hs *HTTPServer) createShortURL(c *models.ReqContext) response.Response {
|
||||
URL: url,
|
||||
}
|
||||
|
||||
return response.JSON(200, dto)
|
||||
return response.JSON(http.StatusOK, dto)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) redirectFromShortURL(c *models.ReqContext) {
|
||||
|
||||
+3
-3
@@ -18,7 +18,7 @@ import (
|
||||
|
||||
// GET /api/user/signup/options
|
||||
func GetSignUpOptions(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"verifyEmailEnabled": setting.VerifyEmailEnabled,
|
||||
"autoAssignOrg": setting.AutoAssignOrg,
|
||||
})
|
||||
@@ -64,7 +64,7 @@ func (hs *HTTPServer) SignUp(c *models.ReqContext) response.Response {
|
||||
|
||||
metrics.MApiUserSignUpStarted.Inc()
|
||||
|
||||
return response.JSON(200, util.DynMap{"status": "SignUpCreated"})
|
||||
return response.JSON(http.StatusOK, util.DynMap{"status": "SignUpCreated"})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) SignUpStep2(c *models.ReqContext) response.Response {
|
||||
@@ -135,7 +135,7 @@ func (hs *HTTPServer) SignUpStep2(c *models.ReqContext) response.Response {
|
||||
|
||||
metrics.MApiUserSignUpCompleted.Inc()
|
||||
|
||||
return response.JSON(200, apiResponse)
|
||||
return response.JSON(http.StatusOK, apiResponse)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) verifyUserSignUpEmail(ctx context.Context, email string, code string) (bool, response.Response) {
|
||||
|
||||
+6
-2
@@ -1,7 +1,11 @@
|
||||
package api
|
||||
|
||||
import "github.com/grafana/grafana/pkg/models"
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func swaggerUI(c *models.ReqContext) {
|
||||
c.HTML(200, "swagger", nil)
|
||||
c.HTML(http.StatusOK, "swagger", nil)
|
||||
}
|
||||
|
||||
+3
-3
@@ -44,7 +44,7 @@ func (hs *HTTPServer) CreateTeam(c *models.ReqContext) response.Response {
|
||||
c.Logger.Warn("Could not add creator to team because is not a real user")
|
||||
}
|
||||
}
|
||||
return response.JSON(200, &util.DynMap{
|
||||
return response.JSON(http.StatusOK, &util.DynMap{
|
||||
"teamId": team.Id,
|
||||
"message": "Team created",
|
||||
})
|
||||
@@ -151,7 +151,7 @@ func (hs *HTTPServer) SearchTeams(c *models.ReqContext) response.Response {
|
||||
query.Result.Page = page
|
||||
query.Result.PerPage = perPage
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
// UserFilter returns the user ID used in a filter when querying a team
|
||||
@@ -198,7 +198,7 @@ func (hs *HTTPServer) GetTeamByID(c *models.ReqContext) response.Response {
|
||||
query.Result.AccessControl = hs.getAccessControlMetadata(c, c.OrgId, "teams:id:", strconv.FormatInt(query.Result.Id, 10))
|
||||
|
||||
query.Result.AvatarUrl = dtos.GetGravatarUrlWithDefault(query.Result.Email, query.Result.Name)
|
||||
return response.JSON(200, &query.Result)
|
||||
return response.JSON(http.StatusOK, &query.Result)
|
||||
}
|
||||
|
||||
// GET /api/teams/:teamId/preferences
|
||||
|
||||
@@ -54,7 +54,7 @@ func (hs *HTTPServer) GetTeamMembers(c *models.ReqContext) response.Response {
|
||||
filteredMembers = append(filteredMembers, member)
|
||||
}
|
||||
|
||||
return response.JSON(200, filteredMembers)
|
||||
return response.JSON(http.StatusOK, filteredMembers)
|
||||
}
|
||||
|
||||
// POST /api/teams/:teamId/members
|
||||
@@ -89,7 +89,7 @@ func (hs *HTTPServer) AddTeamMember(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Failed to add Member to Team", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, &util.DynMap{
|
||||
return response.JSON(http.StatusOK, &util.DynMap{
|
||||
"message": "Member added to Team",
|
||||
})
|
||||
}
|
||||
|
||||
+6
-6
@@ -49,7 +49,7 @@ func (hs *HTTPServer) getUserUserProfile(c *models.ReqContext, userID int64) res
|
||||
query.Result.AccessControl = hs.getAccessControlMetadata(c, c.OrgId, "global.users:id:", strconv.FormatInt(userID, 10))
|
||||
query.Result.AvatarUrl = dtos.GetGravatarUrl(query.Result.Email)
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
// GET /api/users/lookup
|
||||
@@ -73,7 +73,7 @@ func (hs *HTTPServer) GetUserByLoginOrEmail(c *models.ReqContext) response.Respo
|
||||
UpdatedAt: user.Updated,
|
||||
CreatedAt: user.Created,
|
||||
}
|
||||
return response.JSON(200, &result)
|
||||
return response.JSON(http.StatusOK, &result)
|
||||
}
|
||||
|
||||
// POST /api/user
|
||||
@@ -176,7 +176,7 @@ func (hs *HTTPServer) getUserTeamList(ctx context.Context, orgID int64, userID i
|
||||
for _, team := range query.Result {
|
||||
team.AvatarUrl = dtos.GetGravatarUrlWithDefault(team.Email, team.Name)
|
||||
}
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
// GET /api/users/:id/orgs
|
||||
@@ -195,7 +195,7 @@ func (hs *HTTPServer) getUserOrgList(ctx context.Context, userID int64) response
|
||||
return response.Error(500, "Failed to get user organizations", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, query.Result)
|
||||
return response.JSON(http.StatusOK, query.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) validateUsingOrg(ctx context.Context, userID int64, orgID int64) bool {
|
||||
@@ -321,7 +321,7 @@ func (hs *HTTPServer) SetHelpFlag(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Failed to update help flag", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1})
|
||||
return response.JSON(http.StatusOK, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) ClearHelpFlags(c *models.ReqContext) response.Response {
|
||||
@@ -334,7 +334,7 @@ func (hs *HTTPServer) ClearHelpFlags(c *models.ReqContext) response.Response {
|
||||
return response.Error(500, "Failed to update help flag", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1})
|
||||
return response.JSON(http.StatusOK, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1})
|
||||
}
|
||||
|
||||
func GetAuthProviderLabel(authModule string) string {
|
||||
|
||||
@@ -43,7 +43,7 @@ func (hs *HTTPServer) logoutUserFromAllDevicesInternal(ctx context.Context, user
|
||||
return response.Error(500, "Failed to logout user", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "User logged out",
|
||||
})
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (hs *HTTPServer) getUserAuthTokensInternal(c *models.ReqContext, userID int
|
||||
})
|
||||
}
|
||||
|
||||
return response.JSON(200, result)
|
||||
return response.JSON(http.StatusOK, result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) revokeUserAuthTokenInternal(c *models.ReqContext, userID int64, cmd models.RevokeAuthTokenCmd) response.Response {
|
||||
@@ -144,7 +144,7 @@ func (hs *HTTPServer) revokeUserAuthTokenInternal(c *models.ReqContext, userID i
|
||||
return response.Error(500, "Failed to revoke user auth token", err)
|
||||
}
|
||||
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"message": "User auth token revoked",
|
||||
})
|
||||
}
|
||||
|
||||
@@ -114,6 +114,8 @@ func webIdentityProvider(sess client.ConfigProvider) credentials.Provider {
|
||||
roleARN := os.Getenv("AWS_ROLE_ARN")
|
||||
tokenFilepath := os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE")
|
||||
roleSessionName := os.Getenv("AWS_ROLE_SESSION_NAME")
|
||||
|
||||
// nolint:staticcheck
|
||||
return stscreds.NewWebIdentityRoleProvider(svc, roleARN, roleSessionName, tokenFilepath)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
// Coremodel contains the foundational schema declaration for dashboards.
|
||||
type Coremodel struct {
|
||||
lin thema.Lineage
|
||||
}
|
||||
|
||||
// Lineage returns the canonical dashboard Lineage.
|
||||
func (c *Coremodel) Lineage() thema.Lineage {
|
||||
return c.lin
|
||||
}
|
||||
|
||||
func (c *Coremodel) CurrentSchema() thema.Schema {
|
||||
sch, err := c.lin.Schema(currentVersion)
|
||||
if err != nil {
|
||||
// Only reachable if our own schema currentVersion does not exist, which
|
||||
// can really only happen transitionally during development
|
||||
panic(err)
|
||||
}
|
||||
return sch
|
||||
}
|
||||
|
||||
func (c *Coremodel) GoType() interface{} {
|
||||
return &model{}
|
||||
}
|
||||
|
||||
func ProvideCoremodel(lib thema.Library) (*Coremodel, error) {
|
||||
lin, err := Lineage(lib)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Coremodel{
|
||||
lin: lin,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
package dashboard
|
||||
|
||||
import "github.com/grafana/thema"
|
||||
|
||||
thema.#Lineage
|
||||
name: "dashboard"
|
||||
seqs: [
|
||||
{
|
||||
schemas: [
|
||||
{// 0.0
|
||||
// Unique numeric identifier for the dashboard.
|
||||
// TODO must isolate or remove identifiers local to a Grafana instance...?
|
||||
id?: int64
|
||||
// Unique dashboard identifier that can be generated by anyone. string (8-40)
|
||||
uid?: string
|
||||
// Title of dashboard.
|
||||
title?: string
|
||||
// Description of dashboard.
|
||||
description?: string
|
||||
|
||||
gnetId?: string
|
||||
// Tags associated with dashboard.
|
||||
tags?: [...string]
|
||||
// Theme of dashboard.
|
||||
style: *"light" | "dark"
|
||||
// Timezone of dashboard,
|
||||
timezone?: *"browser" | "utc" | ""
|
||||
// Whether a dashboard is editable or not.
|
||||
editable: bool | *true
|
||||
// 0 for no shared crosshair or tooltip (default).
|
||||
// 1 for shared crosshair.
|
||||
// 2 for shared crosshair AND shared tooltip.
|
||||
graphTooltip: uint8 & >=0 & <=2 | *0
|
||||
// Time range for dashboard, e.g. last 6 hours, last 7 days, etc
|
||||
time?: {
|
||||
from: string | *"now-6h"
|
||||
to: string | *"now"
|
||||
}
|
||||
// Timepicker metadata.
|
||||
timepicker?: {
|
||||
// Whether timepicker is collapsed or not.
|
||||
collapse: bool | *false
|
||||
// Whether timepicker is enabled or not.
|
||||
enable: bool | *true
|
||||
// Whether timepicker is visible or not.
|
||||
hidden: bool | *false
|
||||
// Selectable intervals for auto-refresh.
|
||||
refresh_intervals: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
|
||||
}
|
||||
// Templating.
|
||||
templating?: list: [...{...}]
|
||||
// Annotations.
|
||||
annotations?: list: [...{
|
||||
builtIn: uint8 | *0
|
||||
// Datasource to use for annotation.
|
||||
datasource: {
|
||||
type?: string
|
||||
uid?: string
|
||||
}
|
||||
// Whether annotation is enabled.
|
||||
enable: bool | *true
|
||||
// Whether to hide annotation.
|
||||
hide?: bool | *false
|
||||
// Annotation icon color.
|
||||
iconColor?: string
|
||||
// Name of annotation.
|
||||
name?: string
|
||||
type: string | *"dashboard"
|
||||
// Query for annotation data.
|
||||
rawQuery?: string
|
||||
showIn: uint8 | *0
|
||||
}]
|
||||
// Auto-refresh interval.
|
||||
refresh?: string | false
|
||||
// Version of the JSON schema, incremented each time a Grafana update brings
|
||||
// changes to said schema.
|
||||
// FIXME this is the old schema numbering system, and will be replaced by Thema's themaVersion
|
||||
schemaVersion: uint16 | *33
|
||||
// Version of the dashboard, incremented each time the dashboard is updated.
|
||||
version?: uint32
|
||||
panels?: [...(#Panel | #GraphPanel | #HeatmapPanel | #RowPanel)]
|
||||
|
||||
// TODO docs
|
||||
#FieldColorModeId: "thresholds" | "palette-classic" | "palette-saturated" | "continuous-GrYlRd" | "fixed" @cuetsy(kind="enum")
|
||||
|
||||
// TODO docs
|
||||
#FieldColorSeriesByMode: "min" | "max" | "last" @cuetsy(kind="type")
|
||||
|
||||
// TODO docs
|
||||
#FieldColor: {
|
||||
// The main color scheme mode
|
||||
mode: #FieldColorModeId | string
|
||||
// Stores the fixed color value if mode is fixed
|
||||
fixedColor?: string
|
||||
// Some visualizations need to know how to assign a series color from by value color schemes
|
||||
seriesBy?: #FieldColorSeriesByMode
|
||||
} @cuetsy(kind="interface")
|
||||
|
||||
// TODO docs
|
||||
#Threshold: {
|
||||
// TODO docs
|
||||
// FIXME the corresponding typescript field is required/non-optional, but nulls currently appear here when serializing -Infinity to JSON
|
||||
value?: number
|
||||
// TODO docs
|
||||
color: string
|
||||
// TODO docs
|
||||
// TODO are the values here enumerable into a disjunction?
|
||||
// Some seem to be listed in typescript comment
|
||||
state?: string
|
||||
} @cuetsy(kind="interface")
|
||||
|
||||
#ThresholdsMode: "absolute" | "percentage" @cuetsy(kind="enum")
|
||||
|
||||
#ThresholdsConfig: {
|
||||
mode: #ThresholdsMode
|
||||
|
||||
// Must be sorted by 'value', first value is always -Infinity
|
||||
steps: [...#Threshold]
|
||||
} @cuetsy(kind="interface")
|
||||
|
||||
// TODO docs
|
||||
// FIXME this is extremely underspecfied; wasn't obvious which typescript types corresponded to it
|
||||
#Transformation: {
|
||||
id: string
|
||||
options: {...}
|
||||
}
|
||||
|
||||
// Schema for panel targets is specified by datasource
|
||||
// plugins. We use a placeholder definition, which the Go
|
||||
// schema loader either left open/as-is with the Base
|
||||
// variant of the Dashboard and Panel families, or filled
|
||||
// with types derived from plugins in the Instance variant.
|
||||
// When working directly from CUE, importers can extend this
|
||||
// type directly to achieve the same effect.
|
||||
#Target: {...}
|
||||
|
||||
// Dashboard panels. Panels are canonically defined inline
|
||||
// because they share a version timeline with the dashboard
|
||||
// schema; they do not evolve independently.
|
||||
#Panel: {
|
||||
// The panel plugin type id.
|
||||
type: !=""
|
||||
|
||||
// TODO docs
|
||||
id?: uint32
|
||||
|
||||
// FIXME this almost certainly has to be changed in favor of scuemata versions
|
||||
pluginVersion?: string
|
||||
|
||||
// TODO docs
|
||||
tags?: [...string]
|
||||
|
||||
// Internal - the exact major and minor versions of the panel plugin
|
||||
// schema. Hidden and therefore not a part of the data model, but
|
||||
// expected to be filled with panel plugin schema versions so that it's
|
||||
// possible to figure out which schema version matched on a successful
|
||||
// unification.
|
||||
// _pv: { maj: int, min: int }
|
||||
// The major and minor versions of the panel plugin for this schema.
|
||||
// TODO 2-tuple list instead of struct?
|
||||
// panelSchema?: { maj: number, min: number }
|
||||
panelSchema?: [number, number]
|
||||
|
||||
// TODO docs
|
||||
targets?: [...#Target]
|
||||
|
||||
// Panel title.
|
||||
title?: string
|
||||
// Description.
|
||||
description?: string
|
||||
// Whether to display the panel without a background.
|
||||
transparent: bool | *false
|
||||
// The datasource used in all targets.
|
||||
datasource?: {
|
||||
type?: string
|
||||
uid?: string
|
||||
}
|
||||
// Grid position.
|
||||
gridPos?: {
|
||||
// Panel
|
||||
h: uint32 & >0 | *9
|
||||
// Panel
|
||||
w: uint32 & >0 & <=24 | *12
|
||||
// Panel x
|
||||
x: uint32 & >=0 & <24 | *0
|
||||
// Panel y
|
||||
y: uint32 & >=0 | *0
|
||||
// true if fixed
|
||||
static?: bool
|
||||
}
|
||||
// Panel links.
|
||||
// FIXME this is temporarily specified as a closed list so
|
||||
// that validation will pass when no links are present, but
|
||||
// to force a failure as soon as it's checked against there
|
||||
// being anything in the list so it can be fixed in
|
||||
// accordance with that object
|
||||
links?: []
|
||||
|
||||
// Name of template variable to repeat for.
|
||||
repeat?: string
|
||||
// Direction to repeat in if 'repeat' is set.
|
||||
// "h" for horizontal, "v" for vertical.
|
||||
repeatDirection: *"h" | "v"
|
||||
|
||||
// TODO docs
|
||||
maxDataPoints?: number
|
||||
|
||||
// TODO docs
|
||||
thresholds?: [...]
|
||||
|
||||
// TODO docs
|
||||
timeRegions?: [...]
|
||||
|
||||
transformations: [...#Transformation]
|
||||
|
||||
// TODO docs
|
||||
// TODO tighter constraint
|
||||
interval?: string
|
||||
|
||||
// TODO docs
|
||||
// TODO tighter constraint
|
||||
timeFrom?: string
|
||||
|
||||
// TODO docs
|
||||
// TODO tighter constraint
|
||||
timeShift?: string
|
||||
|
||||
// options is specified by the PanelOptions field in panel
|
||||
// plugin schemas.
|
||||
options: {...}
|
||||
|
||||
fieldConfig: {
|
||||
defaults: {
|
||||
// The display value for this field. This supports template variables blank is auto
|
||||
displayName?: string
|
||||
|
||||
// This can be used by data sources that return and explicit naming structure for values and labels
|
||||
// When this property is configured, this value is used rather than the default naming strategy.
|
||||
displayNameFromDS?: string
|
||||
|
||||
// Human readable field metadata
|
||||
description?: string
|
||||
|
||||
// An explict path to the field in the datasource. When the frame meta includes a path,
|
||||
// This will default to `${frame.meta.path}/${field.name}
|
||||
//
|
||||
// When defined, this value can be used as an identifier within the datasource scope, and
|
||||
// may be used to update the results
|
||||
path?: string
|
||||
|
||||
// True if data source can write a value to the path. Auth/authz are supported separately
|
||||
writeable?: bool
|
||||
|
||||
// True if data source field supports ad-hoc filters
|
||||
filterable?: bool
|
||||
|
||||
// Numeric Options
|
||||
unit?: string
|
||||
|
||||
// Significant digits (for display)
|
||||
decimals?: number
|
||||
|
||||
min?: number
|
||||
max?: number
|
||||
|
||||
// Convert input values into a display string
|
||||
//
|
||||
// TODO this one corresponds to a complex type with
|
||||
// generics on the typescript side. Ouch. Will
|
||||
// either need special care, or we'll just need to
|
||||
// accept a very loosely specified schema. It's very
|
||||
// unlikely we'll be able to translate cue to
|
||||
// typescript generics in the general case, though
|
||||
// this particular one *may* be able to work.
|
||||
mappings?: [...{...}]
|
||||
|
||||
// Map numeric values to states
|
||||
thresholds?: #ThresholdsConfig
|
||||
|
||||
// // Map values to a display color
|
||||
color?: #FieldColor
|
||||
|
||||
// // Used when reducing field values
|
||||
// nullValueMode?: NullValueMode
|
||||
|
||||
// // The behavior when clicking on a result
|
||||
links?: [...]
|
||||
|
||||
// Alternative to empty string
|
||||
noValue?: string
|
||||
|
||||
// custom is specified by the PanelFieldConfig field
|
||||
// in panel plugin schemas.
|
||||
custom?: {...}
|
||||
}
|
||||
overrides: [...{
|
||||
matcher: {
|
||||
id: string | *""
|
||||
options?: _
|
||||
}
|
||||
properties: [...{
|
||||
id: string | *""
|
||||
value?: _
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
// Row panel
|
||||
#RowPanel: {
|
||||
type: "row"
|
||||
collapsed: bool | *false
|
||||
title?: string
|
||||
|
||||
// Name of default datasource.
|
||||
datasource?: {
|
||||
type?: string
|
||||
uid?: string
|
||||
}
|
||||
|
||||
gridPos?: {
|
||||
// Panel
|
||||
h: uint32 & >0 | *9
|
||||
// Panel
|
||||
w: uint32 & >0 & <=24 | *12
|
||||
// Panel x
|
||||
x: uint32 & >=0 & <24 | *0
|
||||
// Panel y
|
||||
y: uint32 & >=0 | *0
|
||||
// true if fixed
|
||||
static?: bool
|
||||
}
|
||||
id: uint32
|
||||
panels: [...(#Panel | #GraphPanel | #HeatmapPanel)]
|
||||
// Name of template variable to repeat for.
|
||||
repeat?: string
|
||||
}
|
||||
|
||||
// Support for legacy graph and heatmap panels.
|
||||
#GraphPanel: {
|
||||
type: "graph"
|
||||
...
|
||||
}
|
||||
#HeatmapPanel: {
|
||||
type: "heatmap"
|
||||
...
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,98 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/grafana/thema"
|
||||
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed lineage.cue
|
||||
cueFS embed.FS
|
||||
|
||||
// TODO: this should be generated by Thema.
|
||||
currentVersion = thema.SV(0, 0)
|
||||
)
|
||||
|
||||
// HandoffSchemaVersion is the minimum schemaVersion for dashboards at which the
|
||||
// Thema-based dashboard schema is known to be valid.
|
||||
//
|
||||
// schemaVersion is the original version numbering system for dashboards. If a
|
||||
// dashboard is below this schemaVersion, it is necessary for the frontend
|
||||
// typescript dashboard migration logic to first run and get it past this
|
||||
// number, after which Thema can take over.
|
||||
const HandoffSchemaVersion = 36
|
||||
|
||||
// Lineage returns the Thema lineage representing Grafana dashboards. The
|
||||
// lineage is the canonical specification of the current datasource schema, all
|
||||
// prior schema versions, and the mappings that allow migration between schema
|
||||
// versions.
|
||||
//
|
||||
// This is the base variant of the schema, which does not include any composed
|
||||
// plugin schemas.
|
||||
func Lineage(lib thema.Library, opts ...thema.BindOption) (thema.Lineage, error) {
|
||||
return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "dashboard"), cueFS, lib, opts...)
|
||||
}
|
||||
|
||||
// Model is a dummy struct stand-in for dashboards.
|
||||
//
|
||||
// It exists solely to trick compgen into accepting the dashboard coremodel as valid.
|
||||
type Model struct{}
|
||||
|
||||
// model is a hacky Go struct representing a dashboard.
|
||||
//
|
||||
// This exists solely because the coremodel framework enforces that there is a Go struct to which
|
||||
// all valid Thema schema instances can be assigned, per Thema's assignability checker. See
|
||||
// https://github.com/grafana/thema/blob/main/docs/invariants.md#go-assignability for rules.
|
||||
//
|
||||
// DO NOT RELY ON THIS FOR ANYTHING REAL. It is unclear whether we will ever attempt to have a correct, complete
|
||||
// Go struct representation of dashboards, let alone compress it into a single struct.
|
||||
type model struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
GnetId string `json:"gnetId"`
|
||||
Tags []string `json:"tags"`
|
||||
Style string `json:"style"`
|
||||
Timezone string `json:"timezone"`
|
||||
Editable bool `json:"editable"`
|
||||
GraphTooltip uint8 `json:"graphTooltip"`
|
||||
Time struct {
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
} `json:"time"`
|
||||
Timepicker struct {
|
||||
Collapse bool `json:"collapse"`
|
||||
Enable bool `json:"enable"`
|
||||
Hidden bool `json:"hidden"`
|
||||
RefreshIntervals []string `json:"refresh_intervals"`
|
||||
} `json:"timepicker"`
|
||||
Templating struct {
|
||||
List []interface{} `json:"list"`
|
||||
} `json:"templating"`
|
||||
Annotations struct {
|
||||
List []struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
BuiltIn uint8 `json:"builtIn"`
|
||||
Datasource string `json:"datasource"`
|
||||
Enable bool `json:"enable"`
|
||||
Hide bool `json:"hide,omitempty"`
|
||||
IconColor string `json:"iconColor"`
|
||||
RawQuery string `json:"rawQuery,omitempty"`
|
||||
ShowIn int `json:"showIn"`
|
||||
} `json:"list"`
|
||||
} `json:"annotations"`
|
||||
Refresh interface{} `json:"refresh"` // (bool|string)
|
||||
SchemaVersion int `json:"schemaVersion"`
|
||||
Panels []interface{} `json:"panels"`
|
||||
|
||||
// //
|
||||
|
||||
Uid string `json:"uid"`
|
||||
// OrgId int64 `json:"orgId"`
|
||||
Id int64 `json:"id,omitempty"`
|
||||
Version int `json:"version"`
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
// Package cuectx provides a single, central CUE context (runtime) and Thema
|
||||
// library that can be used uniformly across Grafana, and related helper
|
||||
// functions for loading Thema lineages.
|
||||
|
||||
package cuectx
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"testing/fstest"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/cue/cuecontext"
|
||||
"github.com/grafana/thema"
|
||||
"github.com/grafana/thema/kernel"
|
||||
"github.com/grafana/thema/load"
|
||||
)
|
||||
|
||||
var ctx *cue.Context = cuecontext.New()
|
||||
var lib thema.Library = thema.NewLibrary(ctx)
|
||||
|
||||
// ProvideCUEContext is a wire service provider of a central cue.Context.
|
||||
func ProvideCUEContext() *cue.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
// ProvideThemaLibrary is a wire service provider of a central thema.Library.
|
||||
func ProvideThemaLibrary() thema.Library {
|
||||
return lib
|
||||
}
|
||||
|
||||
// JSONtoCUE attempts to decode the given []byte into a cue.Value, relying on
|
||||
// the central Grafana cue.Context provided in this package.
|
||||
//
|
||||
// The provided path argument determines the name given to the input bytes if
|
||||
// later CUE operations (e.g. Thema validation) produce errors related to the
|
||||
// returned cue.Value.
|
||||
//
|
||||
// This is a convenience function for one-off JSON decoding. It's wasteful to
|
||||
// call it repeatedly. Most use cases use cases should probably prefer making
|
||||
// their own Thema/CUE decoders.
|
||||
func JSONtoCUE(path string, b []byte) (cue.Value, error) {
|
||||
return kernel.NewJSONDecoder(path)(ctx, b)
|
||||
}
|
||||
|
||||
// LoadGrafanaInstancesWithThema loads CUE files containing a lineage
|
||||
// representing some Grafana core model schema. It is expected to be used when
|
||||
// implementing a thema.LineageFactory.
|
||||
//
|
||||
// This function primarily juggles paths to make CUE's loader happy. Provide the
|
||||
// path from the grafana root to the directory containing the lineage.cue. The
|
||||
// lineage.cue file must be the sole contents of the provided fs.FS.
|
||||
//
|
||||
// More details on underlying behavior can be found in the docs for github.com/grafana/thema/load.InstancesWithThema.
|
||||
func LoadGrafanaInstancesWithThema(
|
||||
path string,
|
||||
cueFS fs.FS,
|
||||
lib thema.Library,
|
||||
opts ...thema.BindOption,
|
||||
) (thema.Lineage, error) {
|
||||
prefix := filepath.FromSlash(path)
|
||||
fs, err := prefixWithGrafanaCUE(prefix, cueFS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inst, err := load.InstancesWithThema(fs, prefix)
|
||||
|
||||
// Need to trick loading by creating the embedded file and
|
||||
// making it look like a module in the root dir.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
val := lib.Context().BuildInstance(inst)
|
||||
|
||||
lin, err := thema.BindLineage(val, lib, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return lin, nil
|
||||
}
|
||||
|
||||
func prefixWithGrafanaCUE(prefix string, inputfs fs.FS) (fs.FS, error) {
|
||||
m := fstest.MapFS{
|
||||
filepath.Join("cue.mod", "module.cue"): &fstest.MapFile{Data: []byte(`module: "github.com/grafana/grafana"`)},
|
||||
}
|
||||
|
||||
prefix = filepath.FromSlash(prefix)
|
||||
err := fs.WalkDir(inputfs, ".", (func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := inputfs.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close() // nolint: errcheck
|
||||
|
||||
b, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m[filepath.Join(prefix, path)] = &fstest.MapFile{Data: b}
|
||||
return nil
|
||||
}))
|
||||
|
||||
return m, err
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package coremodel
|
||||
@@ -0,0 +1,25 @@
|
||||
package coremodel
|
||||
|
||||
import (
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
// Interface is the primary coremodel interface that must be implemented by all
|
||||
// Grafana coremodels. A coremodel is the foundational, canonical schema for
|
||||
// some known-at-compile-time Grafana object.
|
||||
//
|
||||
// Currently, all Coremodels are expressed as Thema lineages.
|
||||
type Interface interface {
|
||||
// Lineage should return the canonical Thema lineage for the coremodel.
|
||||
Lineage() thema.Lineage
|
||||
|
||||
// CurrentSchema should return the schema of the version that the Grafana backend
|
||||
// is currently written against. (While Grafana can accept data from all
|
||||
// older versions of the Thema schema, backend Go code is written against a
|
||||
// single version for simplicity)
|
||||
CurrentSchema() thema.Schema
|
||||
|
||||
// GoType should return a pointer to the Go struct type that corresponds to
|
||||
// the Current() schema.
|
||||
GoType() interface{}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package coremodel
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/thema"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrModelAlreadyRegistered is returned when trying to register duplicate model to Registry.
|
||||
ErrModelAlreadyRegistered = errors.New("error registering duplicate model")
|
||||
)
|
||||
|
||||
// Registry is a registry of coremodel instances.
|
||||
type Registry struct {
|
||||
lock sync.RWMutex
|
||||
models []Interface
|
||||
modelIdx map[string]Interface
|
||||
}
|
||||
|
||||
// NewRegistry returns a new Registry with the provided coremodel instances.
|
||||
func NewRegistry(models ...Interface) (*Registry, error) {
|
||||
r := &Registry{
|
||||
models: make([]Interface, 0, len(models)),
|
||||
modelIdx: make(map[string]Interface, len(models)),
|
||||
}
|
||||
|
||||
if err := r.addModels(models); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Register adds coremodels to the Registry.
|
||||
func (r *Registry) Register(models ...Interface) error {
|
||||
return r.addModels(models)
|
||||
}
|
||||
|
||||
// List returns all coremodels registered in this Registry.
|
||||
func (r *Registry) List() []Interface {
|
||||
r.lock.RLock()
|
||||
defer r.lock.RUnlock()
|
||||
|
||||
return r.models
|
||||
}
|
||||
|
||||
func (r *Registry) addModels(models []Interface) error {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
// Update model index and return an error if trying to register a duplicate.
|
||||
for _, m := range models {
|
||||
k := m.Lineage().Name()
|
||||
|
||||
// Ensure assignability first. TODO will this blow up for dashboards?
|
||||
if err := thema.AssignableTo(m.CurrentSchema(), m.GoType()); err != nil {
|
||||
return fmt.Errorf("%s schema version %v not assignable to provided Go type: %w", k, m.CurrentSchema().Version(), err)
|
||||
}
|
||||
|
||||
if _, ok := r.modelIdx[k]; ok {
|
||||
return ErrModelAlreadyRegistered
|
||||
}
|
||||
|
||||
r.modelIdx[k] = m
|
||||
}
|
||||
|
||||
// Remake model list.
|
||||
// TODO: this can be more performant (proper resizing, maybe single loop with index building, etc.).
|
||||
r.models = r.models[:0]
|
||||
for _, m := range r.modelIdx {
|
||||
r.models = append(r.models, m)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package staticregistry
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/coremodel/dashboard"
|
||||
"github.com/grafana/grafana/pkg/framework/coremodel"
|
||||
)
|
||||
|
||||
// ProvideRegistry provides a simple static Registry for coremodels.
|
||||
// Coremodels have to be manually added.
|
||||
// TODO dynamism
|
||||
func ProvideRegistry(
|
||||
dashboard *dashboard.Coremodel,
|
||||
) (*coremodel.Registry, error) {
|
||||
return coremodel.NewRegistry(
|
||||
dashboard,
|
||||
)
|
||||
}
|
||||
@@ -126,6 +126,7 @@ func (ots *Opentelemetry) Start(ctx context.Context, spanName string, opts ...tr
|
||||
opentelemetrySpan := OpentelemetrySpan{
|
||||
span: span,
|
||||
}
|
||||
ctx = context.WithValue(ctx, traceKey{}, traceValue{span.SpanContext().TraceID().String(), span.SpanContext().IsSampled()})
|
||||
return ctx, opentelemetrySpan
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
"github.com/opentracing/opentracing-go/ext"
|
||||
ol "github.com/opentracing/opentracing-go/log"
|
||||
"github.com/uber/jaeger-client-go"
|
||||
jaegercfg "github.com/uber/jaeger-client-go/config"
|
||||
"github.com/uber/jaeger-client-go/zipkin"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
@@ -52,6 +53,21 @@ func ProvideService(cfg *setting.Cfg) (Tracer, error) {
|
||||
return ots, ots.initOpentelemetryTracer()
|
||||
}
|
||||
|
||||
type traceKey struct{}
|
||||
type traceValue struct {
|
||||
ID string
|
||||
IsSampled bool
|
||||
}
|
||||
|
||||
func TraceIDFromContext(c context.Context, requireSampled bool) string {
|
||||
v := c.Value(traceKey{})
|
||||
// Return traceID if a) it is present and b) it is sampled when requireSampled param is true
|
||||
if trace, ok := v.(traceValue); ok && (!requireSampled || trace.IsSampled) {
|
||||
return trace.ID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Opentracing struct {
|
||||
enabled bool
|
||||
address string
|
||||
@@ -172,6 +188,9 @@ func (ts *Opentracing) Run(ctx context.Context) error {
|
||||
func (ts *Opentracing) Start(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, Span) {
|
||||
span, ctx := opentracing.StartSpanFromContext(ctx, spanName)
|
||||
opentracingSpan := OpentracingSpan{span: span}
|
||||
if sctx, ok := span.Context().(jaeger.SpanContext); ok {
|
||||
ctx = context.WithValue(ctx, traceKey{}, traceValue{sctx.TraceID().String(), sctx.IsSampled()})
|
||||
}
|
||||
return ctx, opentracingSpan
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
cw "github.com/weaveworks/common/tracing"
|
||||
)
|
||||
|
||||
func Logger(cfg *setting.Cfg) web.Handler {
|
||||
@@ -58,8 +58,8 @@ func Logger(cfg *setting.Cfg) web.Handler {
|
||||
"referer", req.Referer(),
|
||||
}
|
||||
|
||||
traceID, exist := cw.ExtractTraceID(ctx.Req.Context())
|
||||
if exist {
|
||||
traceID := tracing.TraceIDFromContext(ctx.Req.Context(), false)
|
||||
if traceID != "" {
|
||||
logParams = append(logParams, "traceID", traceID)
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
NavTree: []*dtos.NavLink{},
|
||||
}
|
||||
t.Log("Calling HTML", "data", data)
|
||||
c.HTML(200, "index-template", data)
|
||||
c.HTML(http.StatusOK, "index-template", data)
|
||||
t.Log("Returned HTML with code 200")
|
||||
}
|
||||
sc.fakeReq("GET", "/").exec()
|
||||
@@ -616,7 +616,7 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func(
|
||||
t.Log("Returning JSON OK")
|
||||
resp := make(map[string]interface{})
|
||||
resp["message"] = "OK"
|
||||
c.JSON(200, resp)
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ func rateLimiterScenario(t *testing.T, desc string, rps int, burst int, fn rateL
|
||||
defaultHandler := func(c *models.ReqContext) {
|
||||
resp := make(map[string]interface{})
|
||||
resp["message"] = "OK"
|
||||
c.JSON(200, resp)
|
||||
c.JSON(http.StatusOK, resp)
|
||||
}
|
||||
currentTime := time.Now()
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
cw "github.com/weaveworks/common/tracing"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -80,7 +80,7 @@ func RequestMetrics(features featuremgmt.FeatureToggles) web.Handler {
|
||||
// since they dont make much sense. We should remove them later.
|
||||
histogram := httpRequestDurationHistogram.
|
||||
WithLabelValues(handler, code, req.Method)
|
||||
if traceID, ok := cw.ExtractSampledTraceID(c.Req.Context()); ok {
|
||||
if traceID := tracing.TraceIDFromContext(c.Req.Context(), true); traceID != "" {
|
||||
// Need to type-convert the Observer to an
|
||||
// ExemplarObserver. This will always work for a
|
||||
// HistogramVec.
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -51,9 +52,11 @@ func (ctx *ReqContext) IsApiRequest() bool {
|
||||
|
||||
func (ctx *ReqContext) JsonApiErr(status int, message string, err error) {
|
||||
resp := make(map[string]interface{})
|
||||
traceID := tracing.TraceIDFromContext(ctx.Req.Context(), false)
|
||||
|
||||
if err != nil {
|
||||
ctx.Logger.Error(message, "error", err)
|
||||
resp["traceID"] = traceID
|
||||
ctx.Logger.Error(message, "error", err, "traceID", traceID)
|
||||
if setting.Env != setting.Prod {
|
||||
resp["error"] = err.Error()
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"cuelang.org/go/cue/errors"
|
||||
"cuelang.org/go/cue/load"
|
||||
cuejson "cuelang.org/go/pkg/encoding/json"
|
||||
"github.com/grafana/grafana/pkg/coremodel/dashboard"
|
||||
"github.com/grafana/grafana/pkg/schema"
|
||||
"github.com/laher/mergefs"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -48,7 +49,6 @@ var doTestAgainstDevenv = func(sch schema.VersionedCueSchema, validdir string, f
|
||||
b, err := os.Open(path)
|
||||
require.NoError(t, err, "failed to open dashboard file")
|
||||
|
||||
// Only try to validate dashboards with schemaVersion >= 30
|
||||
jtree := make(map[string]interface{})
|
||||
byt, err := io.ReadAll(b)
|
||||
if err != nil {
|
||||
@@ -59,9 +59,9 @@ var doTestAgainstDevenv = func(sch schema.VersionedCueSchema, validdir string, f
|
||||
t.Logf("no schemaVersion in %s", path)
|
||||
return nil
|
||||
} else {
|
||||
if !(oldschemav.(float64) > 32) {
|
||||
if !(oldschemav.(float64) > dashboard.HandoffSchemaVersion-1) {
|
||||
if testing.Verbose() {
|
||||
t.Logf("schemaVersion is %v, older than 33, skipping %s", oldschemav, path)
|
||||
t.Logf("schemaVersion is %v, older than %v, skipping %s", oldschemav, dashboard.HandoffSchemaVersion-1, path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+10
-1
@@ -6,11 +6,15 @@ package server
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api"
|
||||
"github.com/grafana/grafana/pkg/api/avatar"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/coremodel/dashboard"
|
||||
"github.com/grafana/grafana/pkg/cuectx"
|
||||
"github.com/grafana/grafana/pkg/expr"
|
||||
cmreg "github.com/grafana/grafana/pkg/framework/coremodel/staticregistry"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient/httpclientprovider"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
@@ -64,13 +68,13 @@ import (
|
||||
plugindashboardsservice "github.com/grafana/grafana/pkg/services/plugindashboards/service"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsettings"
|
||||
pluginSettings "github.com/grafana/grafana/pkg/services/pluginsettings/service"
|
||||
"github.com/grafana/grafana/pkg/services/preference/prefimpl"
|
||||
"github.com/grafana/grafana/pkg/services/query"
|
||||
"github.com/grafana/grafana/pkg/services/queryhistory"
|
||||
"github.com/grafana/grafana/pkg/services/quota"
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
"github.com/grafana/grafana/pkg/services/schemaloader"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/searchV2"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
secretsDatabase "github.com/grafana/grafana/pkg/services/secrets/database"
|
||||
@@ -235,9 +239,14 @@ var wireBasicSet = wire.NewSet(
|
||||
wire.Bind(new(alerting.DashAlertExtractor), new(*alerting.DashAlertExtractorService)),
|
||||
comments.ProvideService,
|
||||
guardian.ProvideService,
|
||||
prefimpl.ProvideService,
|
||||
avatar.ProvideAvatarCacheServer,
|
||||
authproxy.ProvideAuthProxy,
|
||||
statscollector.ProvideService,
|
||||
dashboard.ProvideCoremodel,
|
||||
cmreg.ProvideRegistry,
|
||||
cuectx.ProvideCUEContext,
|
||||
cuectx.ProvideThemaLibrary,
|
||||
)
|
||||
|
||||
var wireSet = wire.NewSet(
|
||||
|
||||
@@ -55,9 +55,7 @@ const (
|
||||
// for the HipChatNotifier
|
||||
func NewHipChatNotifier(model *models.AlertNotification, _ alerting.GetDecryptedValueFn, ns notifications.Service) (alerting.Notifier, error) {
|
||||
url := model.Settings.Get("url").MustString()
|
||||
if strings.HasSuffix(url, "/") {
|
||||
url = url[:len(url)-1]
|
||||
}
|
||||
url = strings.TrimSuffix(url, "/")
|
||||
if url == "" {
|
||||
return nil, alerting.ValidationError{Reason: "Could not find url property in settings"}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
cw "github.com/weaveworks/common/tracing"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -98,8 +97,8 @@ func (h *ContextHandler) Middleware(mContext *web.Context) {
|
||||
mContext.Req = mContext.Req.WithContext(context.WithValue(mContext.Req.Context(), reqContextKey{}, reqContext))
|
||||
mContext.Map(mContext.Req)
|
||||
|
||||
traceID, exists := cw.ExtractTraceID(mContext.Req.Context())
|
||||
if exists {
|
||||
traceID := tracing.TraceIDFromContext(mContext.Req.Context(), false)
|
||||
if traceID != "" {
|
||||
reqContext.Logger = reqContext.Logger.New("traceID", traceID)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package featuremgmt
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@@ -157,7 +158,7 @@ func (fm *FeatureManager) HandleGetSettings(c *models.ReqContext) {
|
||||
|
||||
res["info"] = vv
|
||||
|
||||
response.JSON(200, res).WriteTo(c)
|
||||
response.JSON(http.StatusOK, res).WriteTo(c)
|
||||
}
|
||||
|
||||
// WithFeatures is used to define feature toggles for testing.
|
||||
|
||||
@@ -35,7 +35,7 @@ func (l *LibraryElementService) createHandler(c *models.ReqContext) response.Res
|
||||
return toLibraryElementError(err, "Failed to create library element")
|
||||
}
|
||||
|
||||
return response.JSON(200, LibraryElementResponse{Result: element})
|
||||
return response.JSON(http.StatusOK, LibraryElementResponse{Result: element})
|
||||
}
|
||||
|
||||
// deleteHandler handles DELETE /api/library-elements/:uid.
|
||||
@@ -45,7 +45,7 @@ func (l *LibraryElementService) deleteHandler(c *models.ReqContext) response.Res
|
||||
return toLibraryElementError(err, "Failed to delete library element")
|
||||
}
|
||||
|
||||
return response.JSON(200, DeleteLibraryElementResponse{
|
||||
return response.JSON(http.StatusOK, DeleteLibraryElementResponse{
|
||||
Message: "Library element deleted",
|
||||
ID: id,
|
||||
})
|
||||
@@ -58,7 +58,7 @@ func (l *LibraryElementService) getHandler(c *models.ReqContext) response.Respon
|
||||
return toLibraryElementError(err, "Failed to get library element")
|
||||
}
|
||||
|
||||
return response.JSON(200, LibraryElementResponse{Result: element})
|
||||
return response.JSON(http.StatusOK, LibraryElementResponse{Result: element})
|
||||
}
|
||||
|
||||
// getAllHandler handles GET /api/library-elements/.
|
||||
@@ -78,7 +78,7 @@ func (l *LibraryElementService) getAllHandler(c *models.ReqContext) response.Res
|
||||
return toLibraryElementError(err, "Failed to get library elements")
|
||||
}
|
||||
|
||||
return response.JSON(200, LibraryElementSearchResponse{Result: elementsResult})
|
||||
return response.JSON(http.StatusOK, LibraryElementSearchResponse{Result: elementsResult})
|
||||
}
|
||||
|
||||
// patchHandler handles PATCH /api/library-elements/:uid
|
||||
@@ -93,7 +93,7 @@ func (l *LibraryElementService) patchHandler(c *models.ReqContext) response.Resp
|
||||
return toLibraryElementError(err, "Failed to update library element")
|
||||
}
|
||||
|
||||
return response.JSON(200, LibraryElementResponse{Result: element})
|
||||
return response.JSON(http.StatusOK, LibraryElementResponse{Result: element})
|
||||
}
|
||||
|
||||
// getConnectionsHandler handles GET /api/library-panels/:uid/connections/.
|
||||
@@ -103,7 +103,7 @@ func (l *LibraryElementService) getConnectionsHandler(c *models.ReqContext) resp
|
||||
return toLibraryElementError(err, "Failed to get connections")
|
||||
}
|
||||
|
||||
return response.JSON(200, LibraryElementConnectionsResponse{Result: connections})
|
||||
return response.JSON(http.StatusOK, LibraryElementConnectionsResponse{Result: connections})
|
||||
}
|
||||
|
||||
// getByNameHandler handles GET /api/library-elements/name/:name/.
|
||||
@@ -113,7 +113,7 @@ func (l *LibraryElementService) getByNameHandler(c *models.ReqContext) response.
|
||||
return toLibraryElementError(err, "Failed to get library element")
|
||||
}
|
||||
|
||||
return response.JSON(200, LibraryElementArrayResponse{Result: elements})
|
||||
return response.JSON(http.StatusOK, LibraryElementArrayResponse{Result: elements})
|
||||
}
|
||||
|
||||
func toLibraryElementError(err error, message string) response.Response {
|
||||
|
||||
@@ -1042,14 +1042,14 @@ func (g *GrafanaLive) HandleListHTTP(c *models.ReqContext) response.Response {
|
||||
info := streamChannelListResponse{
|
||||
Channels: channels,
|
||||
}
|
||||
return response.JSONStreaming(200, info)
|
||||
return response.JSONStreaming(http.StatusOK, info)
|
||||
}
|
||||
|
||||
// HandleInfoHTTP special http response for
|
||||
func (g *GrafanaLive) HandleInfoHTTP(ctx *models.ReqContext) response.Response {
|
||||
path := web.Params(ctx.Req)["*"]
|
||||
if path == "grafana/dashboards/gitops" {
|
||||
return response.JSON(200, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"active": g.GrafanaScope.Dashboards.HasGitOpsObserver(ctx.SignedInUser.OrgId),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -48,4 +48,4 @@ Scopes must have an order to ensure consistency and ease of search, this helps u
|
||||
- [CHANGE] Prometheus Compatible API: Use float-like values for `api/prometheus/grafana/api/v1/alerts` and `api/prometheus/grafana/api/v1/rules` instead of the evaluation string #47216
|
||||
- [BUGFIX] (Legacy) Templates: Parse notification templates using all the matches of the alert rule when going from `Alerting` to `OK` in legacy alerting #47355
|
||||
- [BUGFIX] Scheduler: Fix state manager to support OK option of `AlertRule.ExecErrState` #47670
|
||||
- [ENHANCEMENT] Templates: Enable the use of classic condition values in templates #46971
|
||||
- [ENHANCEMENT] Templates: Enable the use of classic condition values in templates #46971
|
||||
|
||||
@@ -91,7 +91,7 @@ func (api *API) RegisterAPIEndpoints(m *metrics.API) {
|
||||
api.RegisterAlertmanagerApiEndpoints(NewForkedAM(
|
||||
api.DatasourceCache,
|
||||
NewLotexAM(proxy, logger),
|
||||
&AlertmanagerSrv{store: api.AlertingStore, mam: api.MultiOrgAlertmanager, secrets: api.SecretsService, log: logger, ac: api.AccessControl},
|
||||
&AlertmanagerSrv{crypto: api.MultiOrgAlertmanager.Crypto, log: logger, ac: api.AccessControl, mam: api.MultiOrgAlertmanager},
|
||||
), m)
|
||||
// Register endpoints for proxying to Prometheus-compatible backends.
|
||||
api.RegisterPrometheusApiEndpoints(NewForkedProm(
|
||||
|
||||
@@ -2,7 +2,6 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -15,10 +14,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
@@ -29,11 +26,10 @@ const (
|
||||
)
|
||||
|
||||
type AlertmanagerSrv struct {
|
||||
mam *notifier.MultiOrgAlertmanager
|
||||
secrets secrets.Service
|
||||
store AlertingStore
|
||||
log log.Logger
|
||||
ac accesscontrol.AccessControl
|
||||
log log.Logger
|
||||
ac accesscontrol.AccessControl
|
||||
mam *notifier.MultiOrgAlertmanager
|
||||
crypto notifier.Crypto
|
||||
}
|
||||
|
||||
type UnknownReceiverError struct {
|
||||
@@ -44,81 +40,6 @@ func (e UnknownReceiverError) Error() string {
|
||||
return fmt.Sprintf("unknown receiver: %s", e.UID)
|
||||
}
|
||||
|
||||
func (srv AlertmanagerSrv) loadSecureSettings(ctx context.Context, orgId int64, receivers []*apimodels.PostableApiReceiver) error {
|
||||
// Get the last known working configuration
|
||||
query := ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: orgId}
|
||||
if err := srv.store.GetLatestAlertmanagerConfiguration(ctx, &query); err != nil {
|
||||
// If we don't have a configuration there's nothing for us to know and we should just continue saving the new one
|
||||
if !errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
|
||||
return fmt.Errorf("failed to get latest configuration: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
currentReceiverMap := make(map[string]*apimodels.PostableGrafanaReceiver)
|
||||
if query.Result != nil {
|
||||
currentConfig, err := notifier.Load([]byte(query.Result.AlertmanagerConfiguration))
|
||||
// If the current config is un-loadable, treat it as if it never existed. Providing a new, valid config should be able to "fix" this state.
|
||||
if err != nil {
|
||||
srv.log.Warn("Last known alertmanager configuration was invalid. Overwriting...")
|
||||
} else {
|
||||
currentReceiverMap = currentConfig.GetGrafanaReceiverMap()
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the previously known secure settings
|
||||
for i, r := range receivers {
|
||||
for j, gr := range r.PostableGrafanaReceivers.GrafanaManagedReceivers {
|
||||
if gr.UID == "" { // new receiver
|
||||
continue
|
||||
}
|
||||
|
||||
cgmr, ok := currentReceiverMap[gr.UID]
|
||||
if !ok {
|
||||
// it tries to update a receiver that didn't previously exist
|
||||
return UnknownReceiverError{UID: gr.UID}
|
||||
}
|
||||
|
||||
// frontend sends only the secure settings that have to be updated
|
||||
// therefore we have to copy from the last configuration only those secure settings not included in the request
|
||||
for key := range cgmr.SecureSettings {
|
||||
_, ok := gr.SecureSettings[key]
|
||||
if !ok {
|
||||
decryptedValue, err := srv.getDecryptedSecret(cgmr, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decrypt stored secure setting: %s: %w", key, err)
|
||||
}
|
||||
|
||||
if receivers[i].PostableGrafanaReceivers.GrafanaManagedReceivers[j].SecureSettings == nil {
|
||||
receivers[i].PostableGrafanaReceivers.GrafanaManagedReceivers[j].SecureSettings = make(map[string]string, len(cgmr.SecureSettings))
|
||||
}
|
||||
|
||||
receivers[i].PostableGrafanaReceivers.GrafanaManagedReceivers[j].SecureSettings[key] = decryptedValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (srv AlertmanagerSrv) getDecryptedSecret(r *apimodels.PostableGrafanaReceiver, key string) (string, error) {
|
||||
storedValue, ok := r.SecureSettings[key]
|
||||
if !ok {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
decodeValue, err := base64.StdEncoding.DecodeString(storedValue)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
decryptedValue, err := srv.secrets.Decrypt(context.Background(), decodeValue)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(decryptedValue), nil
|
||||
}
|
||||
|
||||
func (srv AlertmanagerSrv) RouteGetAMStatus(c *models.ReqContext) response.Response {
|
||||
am, errResp := srv.AlertmanagerFor(c.OrgId)
|
||||
if errResp != nil {
|
||||
@@ -192,59 +113,14 @@ func (srv AlertmanagerSrv) RouteDeleteSilence(c *models.ReqContext) response.Res
|
||||
}
|
||||
|
||||
func (srv AlertmanagerSrv) RouteGetAlertingConfig(c *models.ReqContext) response.Response {
|
||||
query := ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: c.OrgId}
|
||||
if err := srv.store.GetLatestAlertmanagerConfiguration(c.Req.Context(), &query); err != nil {
|
||||
config, err := srv.mam.GetAlertmanagerConfiguration(c.Req.Context(), c.OrgId)
|
||||
if err != nil {
|
||||
if errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
|
||||
return ErrResp(http.StatusNotFound, err, "")
|
||||
}
|
||||
return ErrResp(http.StatusInternalServerError, err, "failed to get latest configuration")
|
||||
return ErrResp(http.StatusInternalServerError, err, err.Error())
|
||||
}
|
||||
|
||||
cfg, err := notifier.Load([]byte(query.Result.AlertmanagerConfiguration))
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "failed to unmarshal alertmanager configuration")
|
||||
}
|
||||
|
||||
result := apimodels.GettableUserConfig{
|
||||
TemplateFiles: cfg.TemplateFiles,
|
||||
AlertmanagerConfig: apimodels.GettableApiAlertingConfig{
|
||||
Config: cfg.AlertmanagerConfig.Config,
|
||||
},
|
||||
}
|
||||
for _, recv := range cfg.AlertmanagerConfig.Receivers {
|
||||
receivers := make([]*apimodels.GettableGrafanaReceiver, 0, len(recv.PostableGrafanaReceivers.GrafanaManagedReceivers))
|
||||
for _, pr := range recv.PostableGrafanaReceivers.GrafanaManagedReceivers {
|
||||
secureFields := make(map[string]bool, len(pr.SecureSettings))
|
||||
for k := range pr.SecureSettings {
|
||||
decryptedValue, err := srv.getDecryptedSecret(pr, k)
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "failed to decrypt stored secure setting: %s", k)
|
||||
}
|
||||
if decryptedValue == "" {
|
||||
continue
|
||||
}
|
||||
secureFields[k] = true
|
||||
}
|
||||
gr := apimodels.GettableGrafanaReceiver{
|
||||
UID: pr.UID,
|
||||
Name: pr.Name,
|
||||
Type: pr.Type,
|
||||
DisableResolveMessage: pr.DisableResolveMessage,
|
||||
Settings: pr.Settings,
|
||||
SecureFields: secureFields,
|
||||
}
|
||||
receivers = append(receivers, &gr)
|
||||
}
|
||||
gettableApiReceiver := apimodels.GettableApiReceiver{
|
||||
GettableGrafanaReceivers: apimodels.GettableGrafanaReceivers{
|
||||
GrafanaManagedReceivers: receivers,
|
||||
},
|
||||
}
|
||||
gettableApiReceiver.Name = recv.Name
|
||||
result.AlertmanagerConfig.Receivers = append(result.AlertmanagerConfig.Receivers, &gettableApiReceiver)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, result)
|
||||
return response.JSON(http.StatusOK, config)
|
||||
}
|
||||
|
||||
func (srv AlertmanagerSrv) RouteGetAMAlertGroups(c *models.ReqContext) response.Response {
|
||||
@@ -334,41 +210,26 @@ func (srv AlertmanagerSrv) RouteGetSilences(c *models.ReqContext) response.Respo
|
||||
}
|
||||
|
||||
func (srv AlertmanagerSrv) RoutePostAlertingConfig(c *models.ReqContext, body apimodels.PostableUserConfig) response.Response {
|
||||
// Get the last known working configuration
|
||||
query := ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: c.OrgId}
|
||||
if err := srv.store.GetLatestAlertmanagerConfiguration(c.Req.Context(), &query); err != nil {
|
||||
// If we don't have a configuration there's nothing for us to know and we should just continue saving the new one
|
||||
if !errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
|
||||
return ErrResp(http.StatusInternalServerError, err, "failed to get latest configuration")
|
||||
}
|
||||
err := srv.mam.ApplyAlertmanagerConfiguration(c.Req.Context(), c.OrgId, body)
|
||||
if err == nil {
|
||||
return response.JSON(http.StatusAccepted, util.DynMap{"message": "configuration created"})
|
||||
}
|
||||
var unknownReceiverError notifier.UnknownReceiverError
|
||||
if errors.As(err, &unknownReceiverError) {
|
||||
return ErrResp(http.StatusBadRequest, unknownReceiverError, "")
|
||||
}
|
||||
var configRejectedError notifier.AlertmanagerConfigRejectedError
|
||||
if errors.As(err, &configRejectedError) {
|
||||
return ErrResp(http.StatusBadRequest, configRejectedError, "")
|
||||
}
|
||||
if errors.Is(err, notifier.ErrNoAlertmanagerForOrg) {
|
||||
return response.Error(http.StatusNotFound, err.Error(), err)
|
||||
}
|
||||
if errors.Is(err, notifier.ErrAlertmanagerNotReady) {
|
||||
return response.Error(http.StatusConflict, err.Error(), err)
|
||||
}
|
||||
|
||||
if err := srv.loadSecureSettings(c.Req.Context(), c.OrgId, body.AlertmanagerConfig.Receivers); err != nil {
|
||||
var unknownReceiverError UnknownReceiverError
|
||||
if errors.As(err, &unknownReceiverError) {
|
||||
return ErrResp(http.StatusBadRequest, err, "")
|
||||
}
|
||||
return ErrResp(http.StatusInternalServerError, err, "")
|
||||
}
|
||||
|
||||
if err := body.ProcessConfig(srv.secrets.Encrypt); err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "failed to post process Alertmanager configuration")
|
||||
}
|
||||
|
||||
am, errResp := srv.AlertmanagerFor(c.OrgId)
|
||||
if errResp != nil {
|
||||
// It's okay if the alertmanager isn't ready yet, we're changing its config anyway.
|
||||
if !errors.Is(errResp.Err(), notifier.ErrAlertmanagerNotReady) {
|
||||
return errResp
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.SaveAndApplyConfig(c.Req.Context(), &body); err != nil {
|
||||
srv.log.Error("unable to save and apply alertmanager configuration", "err", err)
|
||||
return ErrResp(http.StatusBadRequest, err, "failed to save and apply Alertmanager configuration")
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusAccepted, util.DynMap{"message": "configuration created"})
|
||||
return ErrResp(http.StatusInternalServerError, err, "")
|
||||
}
|
||||
|
||||
func (srv AlertmanagerSrv) RoutePostAMAlerts(_ *models.ReqContext, _ apimodels.PostableAlerts) response.Response {
|
||||
@@ -376,7 +237,7 @@ func (srv AlertmanagerSrv) RoutePostAMAlerts(_ *models.ReqContext, _ apimodels.P
|
||||
}
|
||||
|
||||
func (srv AlertmanagerSrv) RoutePostTestReceivers(c *models.ReqContext, body apimodels.TestReceiversConfigBodyParams) response.Response {
|
||||
if err := srv.loadSecureSettings(c.Req.Context(), c.OrgId, body.Receivers); err != nil {
|
||||
if err := srv.crypto.LoadSecureSettings(c.Req.Context(), c.OrgId, body.Receivers); err != nil {
|
||||
var unknownReceiverError UnknownReceiverError
|
||||
if errors.As(err, &unknownReceiverError) {
|
||||
return ErrResp(http.StatusBadRequest, err, "")
|
||||
@@ -384,7 +245,7 @@ func (srv AlertmanagerSrv) RoutePostTestReceivers(c *models.ReqContext, body api
|
||||
return ErrResp(http.StatusInternalServerError, err, "")
|
||||
}
|
||||
|
||||
if err := body.ProcessConfig(srv.secrets.Encrypt); err != nil {
|
||||
if err := body.ProcessConfig(srv.crypto.Encrypt); err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "failed to post process Alertmanager configuration")
|
||||
}
|
||||
|
||||
@@ -514,7 +375,6 @@ func (srv AlertmanagerSrv) AlertmanagerFor(orgID int64) (Alertmanager, *response
|
||||
if errors.Is(err, notifier.ErrNoAlertmanagerForOrg) {
|
||||
return nil, response.Error(http.StatusNotFound, err.Error(), err)
|
||||
}
|
||||
|
||||
if errors.Is(err, notifier.ErrAlertmanagerNotReady) {
|
||||
return am, response.Error(http.StatusConflict, err.Error(), err)
|
||||
}
|
||||
|
||||
@@ -357,7 +357,8 @@ func createSut(t *testing.T, accessControl accesscontrol.AccessControl) Alertman
|
||||
accessControl = acMock.New().WithDisabled()
|
||||
}
|
||||
log := log.NewNopLogger()
|
||||
return AlertmanagerSrv{mam: mam, store: &configStore, secrets: secrets, ac: accessControl, log: log}
|
||||
crypto := notifier.NewCrypto(secrets, &configStore, log)
|
||||
return AlertmanagerSrv{mam: mam, crypto: crypto, ac: accessControl, log: log}
|
||||
}
|
||||
|
||||
func createAmConfigRequest(t *testing.T) apimodels.PostableUserConfig {
|
||||
@@ -395,7 +396,7 @@ func createMultiOrgAlertmanager(t *testing.T) *notifier.MultiOrgAlertmanager {
|
||||
}, // do not poll in tests.
|
||||
}
|
||||
|
||||
mam, err := notifier.NewMultiOrgAlertmanager(cfg, &configStore, &orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
mam, err := notifier.NewMultiOrgAlertmanager(cfg, &configStore, &orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService)
|
||||
require.NoError(t, err)
|
||||
err = mam.LoadAndSyncAlertmanagersForOrgs(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -355,23 +355,25 @@ func (srv RulerSrv) updateAlertRulesInGroup(c *models.ReqContext, namespace *mod
|
||||
logger.Debug("updating database with the authorized changes", "add", len(authorizedChanges.New), "update", len(authorizedChanges.New), "delete", len(authorizedChanges.Delete))
|
||||
|
||||
if len(authorizedChanges.Update) > 0 || len(authorizedChanges.New) > 0 {
|
||||
upsert := make([]store.UpsertRule, 0, len(authorizedChanges.Update)+len(authorizedChanges.New))
|
||||
updates := make([]store.UpdateRule, 0, len(authorizedChanges.Update))
|
||||
inserts := make([]ngmodels.AlertRule, 0, len(authorizedChanges.New))
|
||||
for _, update := range authorizedChanges.Update {
|
||||
logger.Debug("updating rule", "rule_uid", update.New.UID, "diff", update.Diff.String())
|
||||
upsert = append(upsert, store.UpsertRule{
|
||||
updates = append(updates, store.UpdateRule{
|
||||
Existing: update.Existing,
|
||||
New: *update.New,
|
||||
})
|
||||
}
|
||||
for _, rule := range authorizedChanges.New {
|
||||
upsert = append(upsert, store.UpsertRule{
|
||||
Existing: nil,
|
||||
New: *rule,
|
||||
})
|
||||
inserts = append(inserts, *rule)
|
||||
}
|
||||
err = srv.store.UpsertAlertRules(tranCtx, upsert)
|
||||
err = srv.store.InsertAlertRules(tranCtx, inserts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add or update rules: %w", err)
|
||||
return fmt.Errorf("failed to add rules: %w", err)
|
||||
}
|
||||
err = srv.store.UpdateAlertRules(tranCtx, updates)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update rules: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
@@ -712,6 +713,8 @@ type Route struct {
|
||||
GroupWait *model.Duration `yaml:"group_wait,omitempty" json:"group_wait,omitempty"`
|
||||
GroupInterval *model.Duration `yaml:"group_interval,omitempty" json:"group_interval,omitempty"`
|
||||
RepeatInterval *model.Duration `yaml:"repeat_interval,omitempty" json:"repeat_interval,omitempty"`
|
||||
|
||||
Provenance models.Provenance `yaml:"provenance,omitempty" json:"provenance,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface for Route. This is a copy of alertmanager's upstream except it removes validation on the label key.
|
||||
|
||||
@@ -99,7 +99,7 @@ func (ng *AlertNG) init() error {
|
||||
|
||||
decryptFn := ng.SecretsService.GetDecryptedValue
|
||||
multiOrgMetrics := ng.Metrics.GetMultiOrgAlertmanagerMetrics()
|
||||
ng.MultiOrgAlertmanager, err = notifier.NewMultiOrgAlertmanager(ng.Cfg, store, store, ng.KVStore, decryptFn, multiOrgMetrics, ng.NotificationService, log.New("ngalert.multiorg.alertmanager"))
|
||||
ng.MultiOrgAlertmanager, err = notifier.NewMultiOrgAlertmanager(ng.Cfg, store, store, ng.KVStore, decryptFn, multiOrgMetrics, ng.NotificationService, log.New("ngalert.multiorg.alertmanager"), ng.SecretsService)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package notifier
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
)
|
||||
|
||||
type UnknownReceiverError struct {
|
||||
UID string
|
||||
}
|
||||
|
||||
func (e UnknownReceiverError) Error() string {
|
||||
return fmt.Sprintf("unknown receiver: %s", e.UID)
|
||||
}
|
||||
|
||||
type AlertmanagerConfigRejectedError struct {
|
||||
Inner error
|
||||
}
|
||||
|
||||
func (e AlertmanagerConfigRejectedError) Error() string {
|
||||
return fmt.Sprintf("failed to save and apply Alertmanager configuration: %s", e.Inner.Error())
|
||||
}
|
||||
|
||||
type configurationStore interface {
|
||||
GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error
|
||||
}
|
||||
|
||||
func (moa *MultiOrgAlertmanager) GetAlertmanagerConfiguration(ctx context.Context, org int64) (definitions.GettableUserConfig, error) {
|
||||
query := models.GetLatestAlertmanagerConfigurationQuery{OrgID: org}
|
||||
err := moa.configStore.GetLatestAlertmanagerConfiguration(ctx, &query)
|
||||
if err != nil {
|
||||
return definitions.GettableUserConfig{}, fmt.Errorf("failed to get latest configuration: %w", err)
|
||||
}
|
||||
cfg, err := Load([]byte(query.Result.AlertmanagerConfiguration))
|
||||
if err != nil {
|
||||
return definitions.GettableUserConfig{}, fmt.Errorf("failed to unmarshal alertmanager configuration: %w", err)
|
||||
}
|
||||
|
||||
result := definitions.GettableUserConfig{
|
||||
TemplateFiles: cfg.TemplateFiles,
|
||||
AlertmanagerConfig: definitions.GettableApiAlertingConfig{
|
||||
Config: cfg.AlertmanagerConfig.Config,
|
||||
},
|
||||
}
|
||||
|
||||
for _, recv := range cfg.AlertmanagerConfig.Receivers {
|
||||
receivers := make([]*definitions.GettableGrafanaReceiver, 0, len(recv.PostableGrafanaReceivers.GrafanaManagedReceivers))
|
||||
for _, pr := range recv.PostableGrafanaReceivers.GrafanaManagedReceivers {
|
||||
secureFields := make(map[string]bool, len(pr.SecureSettings))
|
||||
for k := range pr.SecureSettings {
|
||||
decryptedValue, err := moa.Crypto.getDecryptedSecret(pr, k)
|
||||
if err != nil {
|
||||
return definitions.GettableUserConfig{}, fmt.Errorf("failed to decrypt stored secure setting: %w", err)
|
||||
}
|
||||
if decryptedValue == "" {
|
||||
continue
|
||||
}
|
||||
secureFields[k] = true
|
||||
}
|
||||
gr := definitions.GettableGrafanaReceiver{
|
||||
UID: pr.UID,
|
||||
Name: pr.Name,
|
||||
Type: pr.Type,
|
||||
DisableResolveMessage: pr.DisableResolveMessage,
|
||||
Settings: pr.Settings,
|
||||
SecureFields: secureFields,
|
||||
}
|
||||
receivers = append(receivers, &gr)
|
||||
}
|
||||
gettableApiReceiver := definitions.GettableApiReceiver{
|
||||
GettableGrafanaReceivers: definitions.GettableGrafanaReceivers{
|
||||
GrafanaManagedReceivers: receivers,
|
||||
},
|
||||
}
|
||||
gettableApiReceiver.Name = recv.Name
|
||||
result.AlertmanagerConfig.Receivers = append(result.AlertmanagerConfig.Receivers, &gettableApiReceiver)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (moa *MultiOrgAlertmanager) ApplyAlertmanagerConfiguration(ctx context.Context, org int64, config definitions.PostableUserConfig) error {
|
||||
// Get the last known working configuration
|
||||
query := models.GetLatestAlertmanagerConfigurationQuery{OrgID: org}
|
||||
if err := moa.configStore.GetLatestAlertmanagerConfiguration(ctx, &query); err != nil {
|
||||
// If we don't have a configuration there's nothing for us to know and we should just continue saving the new one
|
||||
if !errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
|
||||
return fmt.Errorf("failed to get latest configuration %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := moa.Crypto.LoadSecureSettings(ctx, org, config.AlertmanagerConfig.Receivers); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := config.ProcessConfig(moa.Crypto.Encrypt); err != nil {
|
||||
return fmt.Errorf("failed to post process Alertmanager configuration: %w", err)
|
||||
}
|
||||
|
||||
am, err := moa.AlertmanagerFor(org)
|
||||
if err != nil {
|
||||
// It's okay if the alertmanager isn't ready yet, we're changing its config anyway.
|
||||
if !errors.Is(err, ErrAlertmanagerNotReady) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := am.SaveAndApplyConfig(ctx, &config); err != nil {
|
||||
moa.logger.Error("unable to save and apply alertmanager configuration", "err", err)
|
||||
return AlertmanagerConfigRejectedError{err}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package notifier
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
)
|
||||
|
||||
// Crypto allows decryption of Alertmanager Configuration and encryption of arbitrary payloads.
|
||||
type Crypto interface {
|
||||
LoadSecureSettings(ctx context.Context, orgId int64, receivers []*definitions.PostableApiReceiver) error
|
||||
Encrypt(ctx context.Context, payload []byte, opt secrets.EncryptionOptions) ([]byte, error)
|
||||
|
||||
getDecryptedSecret(r *definitions.PostableGrafanaReceiver, key string) (string, error)
|
||||
}
|
||||
|
||||
// alertmanagerCrypto implements decryption of Alertmanager configuration and encryption of arbitrary payloads based on Grafana's encryptions.
|
||||
type alertmanagerCrypto struct {
|
||||
secrets secrets.Service
|
||||
configs configurationStore
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func NewCrypto(secrets secrets.Service, configs configurationStore, log log.Logger) Crypto {
|
||||
return &alertmanagerCrypto{
|
||||
secrets: secrets,
|
||||
configs: configs,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
// LoadSecureSettings adds the corresponding unencrypted secrets stored to the list of input receivers.
|
||||
func (c *alertmanagerCrypto) LoadSecureSettings(ctx context.Context, orgId int64, receivers []*definitions.PostableApiReceiver) error {
|
||||
// Get the last known working configuration.
|
||||
query := models.GetLatestAlertmanagerConfigurationQuery{OrgID: orgId}
|
||||
if err := c.configs.GetLatestAlertmanagerConfiguration(ctx, &query); err != nil {
|
||||
// If we don't have a configuration there's nothing for us to know and we should just continue saving the new one.
|
||||
if !errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
|
||||
return fmt.Errorf("failed to get latest configuration: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
currentReceiverMap := make(map[string]*definitions.PostableGrafanaReceiver)
|
||||
if query.Result != nil {
|
||||
currentConfig, err := Load([]byte(query.Result.AlertmanagerConfiguration))
|
||||
// If the current config is un-loadable, treat it as if it never existed. Providing a new, valid config should be able to "fix" this state.
|
||||
if err != nil {
|
||||
c.log.Warn("Last known alertmanager configuration was invalid. Overwriting...")
|
||||
} else {
|
||||
currentReceiverMap = currentConfig.GetGrafanaReceiverMap()
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the previously known secure settings.
|
||||
for i, r := range receivers {
|
||||
for j, gr := range r.PostableGrafanaReceivers.GrafanaManagedReceivers {
|
||||
if gr.UID == "" { // new receiver
|
||||
continue
|
||||
}
|
||||
|
||||
cgmr, ok := currentReceiverMap[gr.UID]
|
||||
if !ok {
|
||||
// It tries to update a receiver that didn't previously exist
|
||||
return UnknownReceiverError{UID: gr.UID}
|
||||
}
|
||||
|
||||
// Frontend sends only the secure settings that have to be updated
|
||||
// Therefore we have to copy from the last configuration only those secure settings not included in the request
|
||||
for key := range cgmr.SecureSettings {
|
||||
_, ok := gr.SecureSettings[key]
|
||||
if !ok {
|
||||
decryptedValue, err := c.getDecryptedSecret(cgmr, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decrypt stored secure setting: %s: %w", key, err)
|
||||
}
|
||||
|
||||
if receivers[i].PostableGrafanaReceivers.GrafanaManagedReceivers[j].SecureSettings == nil {
|
||||
receivers[i].PostableGrafanaReceivers.GrafanaManagedReceivers[j].SecureSettings = make(map[string]string, len(cgmr.SecureSettings))
|
||||
}
|
||||
|
||||
receivers[i].PostableGrafanaReceivers.GrafanaManagedReceivers[j].SecureSettings[key] = decryptedValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *alertmanagerCrypto) getDecryptedSecret(r *definitions.PostableGrafanaReceiver, key string) (string, error) {
|
||||
storedValue, ok := r.SecureSettings[key]
|
||||
if !ok {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
decodeValue, err := base64.StdEncoding.DecodeString(storedValue)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
decryptedValue, err := c.secrets.Decrypt(context.Background(), decodeValue)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(decryptedValue), nil
|
||||
}
|
||||
|
||||
// Encrypt delegates encryption to secrets.Service.
|
||||
func (c *alertmanagerCrypto) Encrypt(ctx context.Context, payload []byte, opt secrets.EncryptionOptions) ([]byte, error) {
|
||||
return c.secrets.Encrypt(ctx, payload, opt)
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier/channels"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
|
||||
"github.com/prometheus/alertmanager/cluster"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -29,6 +30,8 @@ var (
|
||||
)
|
||||
|
||||
type MultiOrgAlertmanager struct {
|
||||
Crypto Crypto
|
||||
|
||||
alertmanagersMtx sync.RWMutex
|
||||
alertmanagers map[int64]*Alertmanager
|
||||
|
||||
@@ -51,9 +54,11 @@ type MultiOrgAlertmanager struct {
|
||||
|
||||
func NewMultiOrgAlertmanager(cfg *setting.Cfg, configStore store.AlertingStore, orgStore store.OrgStore,
|
||||
kvStore kvstore.KVStore, decryptFn channels.GetDecryptedValueFn, m *metrics.MultiOrgAlertmanager,
|
||||
ns notifications.Service, l log.Logger,
|
||||
ns notifications.Service, l log.Logger, s secrets.Service,
|
||||
) (*MultiOrgAlertmanager, error) {
|
||||
moa := &MultiOrgAlertmanager{
|
||||
Crypto: NewCrypto(s, configStore, l),
|
||||
|
||||
logger: l,
|
||||
settings: cfg,
|
||||
alertmanagers: map[int64]*Alertmanager{},
|
||||
|
||||
@@ -44,7 +44,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgs(t *testing.T) {
|
||||
DisabledOrgs: map[int64]struct{}{5: {}},
|
||||
}, // do not poll in tests.
|
||||
}
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService)
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -168,7 +168,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgsWithFailures(t *testing.T)
|
||||
DefaultConfiguration: setting.GetAlertmanagerDefaultConfiguration(),
|
||||
}, // do not poll in tests.
|
||||
}
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService)
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -218,7 +218,7 @@ func TestMultiOrgAlertmanager_AlertmanagerFor(t *testing.T) {
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
reg := prometheus.NewPedanticRegistry()
|
||||
m := metrics.NewNGAlert(reg)
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService)
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
@@ -1015,7 +1015,7 @@ func setupScheduler(t *testing.T, rs store.RuleStore, is store.InstanceStore, ac
|
||||
m := metrics.NewNGAlert(registry)
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
decryptFn := secretsService.GetDecryptedValue
|
||||
moa, err := notifier.NewMultiOrgAlertmanager(&setting.Cfg{}, ¬ifier.FakeConfigStore{}, ¬ifier.FakeOrgStore{}, ¬ifier.FakeKVStore{}, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"))
|
||||
moa, err := notifier.NewMultiOrgAlertmanager(&setting.Cfg{}, ¬ifier.FakeConfigStore{}, ¬ifier.FakeOrgStore{}, ¬ifier.FakeKVStore{}, decryptFn, m.GetMultiOrgAlertmanagerMetrics(), nil, log.New("testlogger"), secretsService)
|
||||
require.NoError(t, err)
|
||||
|
||||
schedCfg := SchedulerCfg{
|
||||
|
||||
@@ -27,7 +27,7 @@ type UpdateRuleGroupCmd struct {
|
||||
RuleGroupConfig apimodels.PostableRuleGroupConfig
|
||||
}
|
||||
|
||||
type UpsertRule struct {
|
||||
type UpdateRule struct {
|
||||
Existing *ngmodels.AlertRule
|
||||
New ngmodels.AlertRule
|
||||
}
|
||||
@@ -42,7 +42,8 @@ type RuleStore interface {
|
||||
GetAlertRules(ctx context.Context, query *ngmodels.GetAlertRulesQuery) error
|
||||
GetUserVisibleNamespaces(context.Context, int64, *models.SignedInUser) (map[string]*models.Folder, error)
|
||||
GetNamespaceByTitle(context.Context, string, int64, *models.SignedInUser, bool) (*models.Folder, error)
|
||||
UpsertAlertRules(ctx context.Context, rule []UpsertRule) error
|
||||
InsertAlertRules(ctx context.Context, rule []ngmodels.AlertRule) error
|
||||
UpdateAlertRules(ctx context.Context, rule []UpdateRule) error
|
||||
}
|
||||
|
||||
func getAlertRuleByUID(sess *sqlstore.DBSession, alertRuleUID string, orgID int64) (*ngmodels.AlertRule, error) {
|
||||
@@ -107,52 +108,87 @@ func (st DBstore) GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAler
|
||||
})
|
||||
}
|
||||
|
||||
// UpsertAlertRules is a handler for creating/updating alert rules.
|
||||
func (st DBstore) UpsertAlertRules(ctx context.Context, rules []UpsertRule) error {
|
||||
// InsertAlertRules is a handler for creating/updating alert rules.
|
||||
func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRule) error {
|
||||
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
newRules := make([]ngmodels.AlertRule, 0, len(rules))
|
||||
ruleVersions := make([]ngmodels.AlertRuleVersion, 0, len(rules))
|
||||
for i := range rules {
|
||||
r := rules[i]
|
||||
uid, err := GenerateNewAlertRuleUID(sess, r.OrgID, r.Title)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate UID for alert rule %q: %w", r.Title, err)
|
||||
}
|
||||
r.UID = uid
|
||||
r.Version = 1
|
||||
if err := st.validateAlertRule(r); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := (&r).PreSave(TimeNow); err != nil {
|
||||
return err
|
||||
}
|
||||
newRules = append(newRules, r)
|
||||
ruleVersions = append(ruleVersions, ngmodels.AlertRuleVersion{
|
||||
RuleOrgID: r.OrgID,
|
||||
RuleUID: r.UID,
|
||||
RuleNamespaceUID: r.NamespaceUID,
|
||||
RuleGroup: r.RuleGroup,
|
||||
ParentVersion: 0,
|
||||
Version: r.Version,
|
||||
Created: r.Updated,
|
||||
Condition: r.Condition,
|
||||
Title: r.Title,
|
||||
Data: r.Data,
|
||||
IntervalSeconds: r.IntervalSeconds,
|
||||
NoDataState: r.NoDataState,
|
||||
ExecErrState: r.ExecErrState,
|
||||
For: r.For,
|
||||
Annotations: r.Annotations,
|
||||
Labels: r.Labels,
|
||||
})
|
||||
}
|
||||
if len(newRules) > 0 {
|
||||
if _, err := sess.Insert(&newRules); err != nil {
|
||||
if st.SQLStore.Dialect.IsUniqueConstraintViolation(err) {
|
||||
return ngmodels.ErrAlertRuleUniqueConstraintViolation
|
||||
}
|
||||
return fmt.Errorf("failed to create new rules: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ruleVersions) > 0 {
|
||||
if _, err := sess.Insert(&ruleVersions); err != nil {
|
||||
return fmt.Errorf("failed to create new rule versions: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateAlertRules is a handler for creating/updating alert rules.
|
||||
func (st DBstore) UpdateAlertRules(ctx context.Context, rules []UpdateRule) error {
|
||||
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
newRules := make([]ngmodels.AlertRule, 0, len(rules))
|
||||
ruleVersions := make([]ngmodels.AlertRuleVersion, 0, len(rules))
|
||||
for _, r := range rules {
|
||||
var parentVersion int64
|
||||
switch r.Existing {
|
||||
case nil: // new rule
|
||||
uid, err := GenerateNewAlertRuleUID(sess, r.New.OrgID, r.New.Title)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate UID for alert rule %q: %w", r.New.Title, err)
|
||||
}
|
||||
r.New.UID = uid
|
||||
r.New.Version = 1
|
||||
|
||||
if err := st.validateAlertRule(r.New); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := (&r.New).PreSave(TimeNow); err != nil {
|
||||
return err
|
||||
}
|
||||
newRules = append(newRules, r.New)
|
||||
default:
|
||||
r.New.ID = r.Existing.ID
|
||||
r.New.Version = r.Existing.Version + 1
|
||||
|
||||
if err := st.validateAlertRule(r.New); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := (&r.New).PreSave(TimeNow); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// no way to update multiple rules at once
|
||||
if _, err := sess.ID(r.Existing.ID).AllCols().Update(r.New); err != nil {
|
||||
if st.SQLStore.Dialect.IsUniqueConstraintViolation(err) {
|
||||
return ngmodels.ErrAlertRuleUniqueConstraintViolation
|
||||
}
|
||||
return fmt.Errorf("failed to update rule [%s] %s: %w", r.New.UID, r.New.Title, err)
|
||||
}
|
||||
parentVersion = r.Existing.Version
|
||||
r.New.ID = r.Existing.ID
|
||||
r.New.Version = r.Existing.Version + 1
|
||||
if err := st.validateAlertRule(r.New); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := (&r.New).PreSave(TimeNow); err != nil {
|
||||
return err
|
||||
}
|
||||
// no way to update multiple rules at once
|
||||
if _, err := sess.ID(r.Existing.ID).AllCols().Update(r.New); err != nil {
|
||||
if st.SQLStore.Dialect.IsUniqueConstraintViolation(err) {
|
||||
return ngmodels.ErrAlertRuleUniqueConstraintViolation
|
||||
}
|
||||
return fmt.Errorf("failed to update rule [%s] %s: %w", r.New.UID, r.New.Title, err)
|
||||
}
|
||||
parentVersion = r.Existing.Version
|
||||
ruleVersions = append(ruleVersions, ngmodels.AlertRuleVersion{
|
||||
RuleOrgID: r.New.OrgID,
|
||||
RuleUID: r.New.UID,
|
||||
@@ -172,7 +208,6 @@ func (st DBstore) UpsertAlertRules(ctx context.Context, rules []UpsertRule) erro
|
||||
Labels: r.New.Labels,
|
||||
})
|
||||
}
|
||||
|
||||
if len(newRules) > 0 {
|
||||
if _, err := sess.Insert(&newRules); err != nil {
|
||||
if st.SQLStore.Dialect.IsUniqueConstraintViolation(err) {
|
||||
@@ -181,13 +216,11 @@ func (st DBstore) UpsertAlertRules(ctx context.Context, rules []UpsertRule) erro
|
||||
return fmt.Errorf("failed to create new rules: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ruleVersions) > 0 {
|
||||
if _, err := sess.Insert(&ruleVersions); err != nil {
|
||||
return fmt.Errorf("failed to create new rule versions: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -228,7 +228,17 @@ func (f *FakeRuleStore) GetNamespaceByTitle(_ context.Context, title string, org
|
||||
return nil, fmt.Errorf("not found")
|
||||
}
|
||||
|
||||
func (f *FakeRuleStore) UpsertAlertRules(_ context.Context, q []UpsertRule) error {
|
||||
func (f *FakeRuleStore) UpdateAlertRules(_ context.Context, q []UpdateRule) error {
|
||||
f.mtx.Lock()
|
||||
defer f.mtx.Unlock()
|
||||
f.RecordedOps = append(f.RecordedOps, q)
|
||||
if err := f.Hook(q); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeRuleStore) InsertAlertRules(_ context.Context, q []models.AlertRule) error {
|
||||
f.mtx.Lock()
|
||||
defer f.mtx.Unlock()
|
||||
f.RecordedOps = append(f.RecordedOps, q)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user