Skip to content

Commit b6de01d

Browse files
committed
feat: add 'datadog_metrics' data source
This addresses issue #3213 by adding a `datadog_metrics` data source for interacting with the [search metrics API](https://docs.datadoghq.com/api/latest/metrics/#search-metrics). The data source offers a way to dynamically search & fetch metrics, then use the results to drive other Terraform configurations. Signed-off-by: Mike Ball <[email protected]>
1 parent 550ab90 commit b6de01d

File tree

7 files changed

+263
-0
lines changed

7 files changed

+263
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package fwprovider
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV1"
9+
"github.com/hashicorp/terraform-plugin-framework/datasource"
10+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
11+
"github.com/hashicorp/terraform-plugin-framework/types"
12+
13+
"github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils"
14+
)
15+
16+
var (
17+
_ datasource.DataSource = &datadogMetricsDataSource{}
18+
)
19+
20+
type datadogMetricsModel struct {
21+
ID types.String `tfsdk:"id"`
22+
Query types.String `tfsdk:"query"`
23+
Metrics types.List `tfsdk:"metrics"`
24+
}
25+
26+
type datadogMetricsDataSource struct {
27+
Api *datadogV1.MetricsApi
28+
Auth context.Context
29+
}
30+
31+
func NewDatadogMetricsDataSource() datasource.DataSource {
32+
return &datadogMetricsDataSource{}
33+
}
34+
35+
func (d *datadogMetricsDataSource) Configure(_ context.Context, request datasource.ConfigureRequest, response *datasource.ConfigureResponse) {
36+
providerData, _ := request.ProviderData.(*FrameworkProvider)
37+
d.Api = providerData.DatadogApiInstances.GetMetricsApiV1()
38+
d.Auth = providerData.Auth
39+
}
40+
41+
func (d *datadogMetricsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
42+
resp.TypeName = "metrics"
43+
}
44+
45+
func (d *datadogMetricsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
46+
resp.Schema = schema.Schema{
47+
Description: "Use this data source to list metrics for use in other resources.",
48+
Attributes: map[string]schema.Attribute{
49+
"id": utils.ResourceIDAttribute(),
50+
"query": schema.StringAttribute{
51+
Description: "The search query to use when listing metrics.",
52+
Required: true,
53+
},
54+
// Computed values
55+
"metrics": schema.ListAttribute{
56+
Description: "The metrics returned by the search query.",
57+
Computed: true,
58+
ElementType: types.StringType,
59+
},
60+
},
61+
}
62+
}
63+
64+
func (d *datadogMetricsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
65+
var state datadogMetricsModel
66+
67+
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...)
68+
if resp.Diagnostics.HasError() {
69+
return
70+
}
71+
ddResp, _, err := d.Api.ListMetrics(d.Auth, state.Query.ValueString())
72+
if err != nil {
73+
resp.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error listing metrics"))
74+
return
75+
}
76+
77+
results := ddResp.GetResults()
78+
metrics := results.GetMetrics()
79+
80+
d.updateState(ctx, &state, metrics)
81+
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
82+
}
83+
84+
func (d *datadogMetricsDataSource) updateState(ctx context.Context, state *datadogMetricsModel, metrics []string) {
85+
hashingData := fmt.Sprintf("%s:%s", state.Query.ValueString(), strings.Join(metrics, ":"))
86+
87+
state.ID = types.StringValue(utils.ConvertToSha256(hashingData))
88+
state.Metrics, _ = types.ListValueFrom(ctx, types.StringType, metrics)
89+
}

datadog/fwprovider/framework_provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ var Datasources = []func() datasource.DataSource{
110110
NewDatadogMetricActiveTagsAndAggregationsDataSource,
111111
NewDatadogMetricMetadataDataSource,
112112
NewDatadogMetricTagsDataSource,
113+
NewDatadogMetricsDataSource,
113114
NewDatadogPowerpackDataSource,
114115
NewDatadogServiceAccountDatasource,
115116
NewDatadogSoftwareCatalogDataSource,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2025-09-06T06:43:56.810887-04:00
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
version: 2
3+
interactions:
4+
- id: 0
5+
request:
6+
proto: HTTP/1.1
7+
proto_major: 1
8+
proto_minor: 1
9+
content_length: 0
10+
transfer_encoding: []
11+
trailer: {}
12+
host: api.datadoghq.com
13+
remote_addr: ""
14+
request_uri: ""
15+
body: ""
16+
form: {}
17+
headers:
18+
Accept:
19+
- application/json
20+
url: https://api.datadoghq.com/api/v1/search?q=foo.
21+
method: GET
22+
response:
23+
proto: HTTP/1.1
24+
proto_major: 1
25+
proto_minor: 1
26+
transfer_encoding:
27+
- chunked
28+
trailer: {}
29+
content_length: -1
30+
uncompressed: true
31+
body: |
32+
{"results":{"metrics":["foo.bar","foo.baz"],"hosts":[]}}
33+
headers:
34+
Content-Type:
35+
- application/json
36+
status: 200 OK
37+
code: 200
38+
duration: 237.101791ms
39+
- id: 1
40+
request:
41+
proto: HTTP/1.1
42+
proto_major: 1
43+
proto_minor: 1
44+
content_length: 0
45+
transfer_encoding: []
46+
trailer: {}
47+
host: api.datadoghq.com
48+
remote_addr: ""
49+
request_uri: ""
50+
body: ""
51+
form: {}
52+
headers:
53+
Accept:
54+
- application/json
55+
url: https://api.datadoghq.com/api/v1/search?q=foo.
56+
method: GET
57+
response:
58+
proto: HTTP/1.1
59+
proto_major: 1
60+
proto_minor: 1
61+
transfer_encoding:
62+
- chunked
63+
trailer: {}
64+
content_length: -1
65+
uncompressed: true
66+
body: |
67+
{"results":{"metrics":["foo.bar","foo.baz"],"hosts":[]}}
68+
headers:
69+
Content-Type:
70+
- application/json
71+
status: 200 OK
72+
code: 200
73+
duration: 237.101791ms
74+
- id: 2
75+
request:
76+
proto: HTTP/1.1
77+
proto_major: 1
78+
proto_minor: 1
79+
content_length: 0
80+
transfer_encoding: []
81+
trailer: {}
82+
host: api.datadoghq.com
83+
remote_addr: ""
84+
request_uri: ""
85+
body: ""
86+
form: {}
87+
headers:
88+
Accept:
89+
- application/json
90+
url: https://api.datadoghq.com/api/v1/search?q=foo.
91+
method: GET
92+
response:
93+
proto: HTTP/1.1
94+
proto_major: 1
95+
proto_minor: 1
96+
transfer_encoding:
97+
- chunked
98+
trailer: {}
99+
content_length: -1
100+
uncompressed: true
101+
body: |
102+
{"results":{"metrics":["foo.bar","foo.baz"],"hosts":[]}}
103+
headers:
104+
Content-Type:
105+
- application/json
106+
status: 200 OK
107+
code: 200
108+
duration: 237.101791ms
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
9+
)
10+
11+
func TestAccDatadogMetricsDatasource(t *testing.T) {
12+
t.Parallel()
13+
_, _, accProviders := testAccFrameworkMuxProviders(context.Background(), t)
14+
query := "foo."
15+
16+
resource.Test(t, resource.TestCase{
17+
PreCheck: func() { testAccPreCheck(t) },
18+
ProtoV5ProviderFactories: accProviders,
19+
Steps: []resource.TestStep{
20+
{
21+
Config: testAccDatasourceMetricsConfig(query),
22+
Check: resource.ComposeTestCheckFunc(
23+
resource.TestCheckResourceAttr("data.datadog_metrics.foo", "query", query),
24+
resource.TestCheckResourceAttr("data.datadog_metrics.foo", "metrics.0", "foo.bar"),
25+
resource.TestCheckResourceAttr("data.datadog_metrics.foo", "metrics.1", "foo.baz"),
26+
),
27+
},
28+
},
29+
})
30+
}
31+
32+
func testAccDatasourceMetricsConfig(query string) string {
33+
return fmt.Sprintf(`
34+
data "datadog_metrics" "foo" {
35+
query = "%s"
36+
}
37+
`, query)
38+
}

datadog/tests/provider_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ var testFiles2EndpointTags = map[string]string{
8080
"tests/data_source_datadog_metric_active_tags_and_aggregations_test": "metrics",
8181
"tests/data_source_datadog_metric_metadata_test": "metrics",
8282
"tests/data_source_datadog_metric_tags_test": "metrics",
83+
"tests/data_source_datadog_metrics_test": "metrics",
8384
"tests/data_source_datadog_monitor_test": "monitors",
8485
"tests/data_source_datadog_monitors_test": "monitors",
8586
"tests/data_source_datadog_permissions_test": "permissions",

docs/data-sources/metrics.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "datadog_metrics Data Source - terraform-provider-datadog"
4+
subcategory: ""
5+
description: |-
6+
Use this data source to list metrics for use in other resources.
7+
---
8+
9+
# datadog_metrics (Data Source)
10+
11+
Use this data source to list metrics for use in other resources.
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `query` (String) The search query to use when listing metrics.
21+
22+
### Read-Only
23+
24+
- `id` (String) The ID of this resource.
25+
- `metrics` (List of String) The metrics returned by the search query.

0 commit comments

Comments
 (0)