Skip to content

Commit abb549f

Browse files
Support Loki datasource attributes (#397)
`maxLines` + `derivedFields` Needs grafana/grafana-api-golang-client#65 Closes #375 and #144
1 parent bbb20e9 commit abb549f

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

docs/resources/data_source.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ Optional:
114114
- **default_bucket** (String) (InfluxDB) The default bucket for the data source.
115115
- **default_project** (String) (Stackdriver) The default project for the data source.
116116
- **default_region** (String) (CloudWatch, Athena) The default region for the data source.
117+
- **derived_field** (Block List) (Loki) See https://grafana.com/docs/grafana/latest/datasources/loki/#derived-fields (see [below for nested schema](#nestedblock--json_data--derived_field))
117118
- **encrypt** (String) (MSSQL) Connection SSL encryption handling: 'disable', 'false' or 'true'.
118119
- **es_version** (String) (Elasticsearch) Elasticsearch semantic version (Grafana v8.0+).
119120
- **external_id** (String) (CloudWatch, Athena) If you are assuming a role in another account, that has been created with an external ID, specify the external ID here.
@@ -125,6 +126,7 @@ Optional:
125126
- **log_message_field** (String) (Elasticsearch) Which field should be used as the log message.
126127
- **max_concurrent_shard_requests** (Number) (Elasticsearch) Maximum number of concurrent shard requests.
127128
- **max_idle_conns** (Number) (MySQL, PostgreSQL and MSSQL) Maximum number of connections in the idle connection pool (Grafana v5.4+).
129+
- **max_lines** (Number) (Loki) Upper limit for the number of log lines returned by Loki
128130
- **max_open_conns** (Number) (MySQL, PostgreSQL and MSSQL) Maximum number of open connections to the database (Grafana v5.4+).
129131
- **org_slug** (String) (Sentry) Organization slug.
130132
- **organization** (String) (InfluxDB) An organization is a workspace for a group of users. All dashboards, tasks, buckets, members, etc., belong to an organization.
@@ -151,6 +153,17 @@ Optional:
151153
- **version** (String) (InfluxDB) InfluxQL or Flux.
152154
- **workgroup** (String) (Athena) Workgroup to use.
153155

156+
<a id="nestedblock--json_data--derived_field"></a>
157+
### Nested Schema for `json_data.derived_field`
158+
159+
Optional:
160+
161+
- **datasource_uid** (String)
162+
- **matcher_regex** (String)
163+
- **name** (String)
164+
- **url** (String)
165+
166+
154167

155168
<a id="nestedblock--secure_json_data"></a>
156169
### Nested Schema for `secure_json_data`

grafana/resource_data_source.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,31 @@ source selected (via the 'type' argument).
145145
Optional: true,
146146
Description: "(CloudWatch, Athena) The default region for the data source.",
147147
},
148+
"derived_field": {
149+
Type: schema.TypeList,
150+
Elem: &schema.Resource{
151+
Schema: map[string]*schema.Schema{
152+
"name": {
153+
Type: schema.TypeString,
154+
Optional: true,
155+
},
156+
"matcher_regex": {
157+
Type: schema.TypeString,
158+
Optional: true,
159+
},
160+
"url": {
161+
Type: schema.TypeString,
162+
Optional: true,
163+
},
164+
"datasource_uid": {
165+
Type: schema.TypeString,
166+
Optional: true,
167+
},
168+
},
169+
},
170+
Optional: true,
171+
Description: "(Loki) See https://grafana.com/docs/grafana/latest/datasources/loki/#derived-fields",
172+
},
148173
"encrypt": {
149174
Type: schema.TypeString,
150175
Optional: true,
@@ -212,6 +237,11 @@ source selected (via the 'type' argument).
212237
Optional: true,
213238
Description: "(MySQL, PostgreSQL and MSSQL) Maximum number of connections in the idle connection pool (Grafana v5.4+).",
214239
},
240+
"max_lines": {
241+
Type: schema.TypeInt,
242+
Optional: true,
243+
Description: "(Loki) Upper limit for the number of log lines returned by Loki ",
244+
},
215245
"max_open_conns": {
216246
Type: schema.TypeInt,
217247
Optional: true,
@@ -579,6 +609,17 @@ func makeDataSource(d *schema.ResourceData) (*gapi.DataSource, error) {
579609
}
580610

581611
func makeJSONData(d *schema.ResourceData) gapi.JSONData {
612+
var derivedFields []gapi.LokiDerivedField
613+
for _, field := range d.Get("json_data.0.derived_field").([]interface{}) {
614+
derivedField := field.(map[string]interface{})
615+
derivedFields = append(derivedFields, gapi.LokiDerivedField{
616+
Name: derivedField["name"].(string),
617+
MatcherRegex: derivedField["matcher_regex"].(string),
618+
URL: derivedField["url"].(string),
619+
DatasourceUID: derivedField["datasource_uid"].(string),
620+
})
621+
}
622+
582623
return gapi.JSONData{
583624
AssumeRoleArn: d.Get("json_data.0.assume_role_arn").(string),
584625
AuthType: d.Get("json_data.0.auth_type").(string),
@@ -591,6 +632,7 @@ func makeJSONData(d *schema.ResourceData) gapi.JSONData {
591632
DefaultBucket: d.Get("json_data.0.default_bucket").(string),
592633
DefaultProject: d.Get("json_data.0.default_project").(string),
593634
DefaultRegion: d.Get("json_data.0.default_region").(string),
635+
DerivedFields: derivedFields,
594636
Encrypt: d.Get("json_data.0.encrypt").(string),
595637
EsVersion: d.Get("json_data.0.es_version").(string),
596638
ExternalID: d.Get("json_data.0.external_id").(string),
@@ -601,6 +643,7 @@ func makeJSONData(d *schema.ResourceData) gapi.JSONData {
601643
LogMessageField: d.Get("json_data.0.log_message_field").(string),
602644
MaxConcurrentShardRequests: int64(d.Get("json_data.0.max_concurrent_shard_requests").(int)),
603645
MaxIdleConns: int64(d.Get("json_data.0.max_idle_conns").(int)),
646+
MaxLines: d.Get("json_data.0.max_lines").(int),
604647
MaxOpenConns: int64(d.Get("json_data.0.max_open_conns").(int)),
605648
Organization: d.Get("json_data.0.organization").(string),
606649
OrgSlug: d.Get("json_data.0.org_slug").(string),

grafana/resource_data_source_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,61 @@ func TestAccDataSource_basic(t *testing.T) {
2222
attrChecks map[string]string
2323
additionalChecks []resource.TestCheckFunc
2424
}{
25+
{
26+
resource: "grafana_data_source.loki",
27+
config: `
28+
resource "grafana_data_source" "tempo" {
29+
name = "Tempo Linked to Loki"
30+
type = "tempo"
31+
}
32+
33+
resource "grafana_data_source" "loki" {
34+
type = "loki"
35+
name = "loki"
36+
url = "http://acc-test.invalid/"
37+
json_data {
38+
max_lines = 2022
39+
40+
derived_field {
41+
name = "WithoutDatasource"
42+
matcher_regex = "(?:traceID|trace_id)=(\\w+)"
43+
url = "example.com/$${__value.raw}"
44+
}
45+
46+
derived_field {
47+
name = "WithDatasource"
48+
matcher_regex = "(?:traceID|trace_id)=(\\w+)"
49+
url = "$${__value.raw}"
50+
datasource_uid = grafana_data_source.tempo.uid
51+
}
52+
}
53+
}
54+
`,
55+
attrChecks: map[string]string{
56+
"type": "loki",
57+
"name": "loki",
58+
"url": "http://acc-test.invalid/",
59+
"json_data.0.max_lines": "2022",
60+
"json_data.0.derived_field.0.name": "WithoutDatasource",
61+
"json_data.0.derived_field.0.matcher_regex": "(?:traceID|trace_id)=(\\w+)",
62+
"json_data.0.derived_field.0.url": "example.com/${__value.raw}",
63+
"json_data.0.derived_field.1.name": "WithDatasource",
64+
"json_data.0.derived_field.1.matcher_regex": "(?:traceID|trace_id)=(\\w+)",
65+
"json_data.0.derived_field.1.url": "${__value.raw}",
66+
},
67+
additionalChecks: []resource.TestCheckFunc{
68+
func(s *terraform.State) error {
69+
// Check datasource IDs
70+
if dataSource.JSONData.DerivedFields[0].DatasourceUID != "" {
71+
return fmt.Errorf("expected empty datasource_uid")
72+
}
73+
if !uidRegexp.MatchString(dataSource.JSONData.DerivedFields[1].DatasourceUID) {
74+
return fmt.Errorf("expected valid datasource_uid")
75+
}
76+
return nil
77+
},
78+
},
79+
},
2580
{
2681
resource: "grafana_data_source.testdata",
2782
config: `

0 commit comments

Comments
 (0)