diff --git a/digitalocean/datasource_digitalocean_droplet.go b/digitalocean/datasource_digitalocean_droplet.go index 8eae84786..24d87f427 100644 --- a/digitalocean/datasource_digitalocean_droplet.go +++ b/digitalocean/datasource_digitalocean_droplet.go @@ -50,7 +50,7 @@ func dataSourceDigitalOceanDropletRead(ctx context.Context, d *schema.ResourceDa foundDroplet = *droplet } else if v, ok := d.GetOk("tag"); ok { - dropletList, err := getDigitalOceanDroplets(meta) + dropletList, err := getDigitalOceanDroplets(meta, nil) if err != nil { return diag.FromErr(err) } @@ -62,7 +62,7 @@ func dataSourceDigitalOceanDropletRead(ctx context.Context, d *schema.ResourceDa foundDroplet = *droplet } else if v, ok := d.GetOk("name"); ok { - dropletList, err := getDigitalOceanDroplets(meta) + dropletList, err := getDigitalOceanDroplets(meta, nil) if err != nil { return diag.FromErr(err) } @@ -78,7 +78,7 @@ func dataSourceDigitalOceanDropletRead(ctx context.Context, d *schema.ResourceDa return diag.Errorf("Error: specify either a name, tag, or id to use to look up the droplet") } - flattenedDroplet, err := flattenDigitalOceanDroplet(foundDroplet, meta) + flattenedDroplet, err := flattenDigitalOceanDroplet(foundDroplet, meta, nil) if err != nil { return diag.FromErr(err) } diff --git a/digitalocean/datasource_digitalocean_image.go b/digitalocean/datasource_digitalocean_image.go index ab2c63d26..11a88b1c7 100644 --- a/digitalocean/datasource_digitalocean_image.go +++ b/digitalocean/datasource_digitalocean_image.go @@ -108,7 +108,7 @@ func dataSourceDigitalOceanImageRead(ctx context.Context, d *schema.ResourceData return diag.Errorf("Illegal state: one of id, name, or slug must be set") } - flattenedImage, err := flattenDigitalOceanImage(*foundImage, meta) + flattenedImage, err := flattenDigitalOceanImage(*foundImage, meta, nil) if err != nil { return diag.FromErr(err) } diff --git a/digitalocean/datasource_digitalocean_project.go b/digitalocean/datasource_digitalocean_project.go index 17cb4adfc..6c6e0a47b 100644 --- a/digitalocean/datasource_digitalocean_project.go +++ b/digitalocean/datasource_digitalocean_project.go @@ -38,7 +38,7 @@ func dataSourceDigitalOceanProjectRead(ctx context.Context, d *schema.ResourceDa } foundProject = thisProject } else if name, ok := d.GetOk("name"); ok { - projects, err := getDigitalOceanProjects(meta) + projects, err := getDigitalOceanProjects(meta, nil) if err != nil { return diag.Errorf("Unable to load projects: %s", err) } @@ -70,7 +70,7 @@ func dataSourceDigitalOceanProjectRead(ctx context.Context, d *schema.ResourceDa return diag.Errorf("No project found.") } - flattenedProject, err := flattenDigitalOceanProject(*foundProject, meta) + flattenedProject, err := flattenDigitalOceanProject(*foundProject, meta, nil) if err != nil { return diag.FromErr(err) } diff --git a/digitalocean/datasource_digitalocean_records.go b/digitalocean/datasource_digitalocean_records.go new file mode 100644 index 000000000..578513d60 --- /dev/null +++ b/digitalocean/datasource_digitalocean_records.go @@ -0,0 +1,23 @@ +package digitalocean + +import ( + "github.com/digitalocean/terraform-provider-digitalocean/internal/datalist" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceDigitalOceanRecords() *schema.Resource { + dataListConfig := &datalist.ResourceConfig{ + RecordSchema: recordsSchema(), + ResultAttributeName: "records", + ExtraQuerySchema: map[string]*schema.Schema{ + "domain": { + Type: schema.TypeString, + Required: true, + }, + }, + FlattenRecord: flattenDigitalOceanRecord, + GetRecords: getDigitalOceanRecords, + } + + return datalist.NewResource(dataListConfig) +} diff --git a/digitalocean/datasource_digitalocean_records_test.go b/digitalocean/datasource_digitalocean_records_test.go new file mode 100644 index 000000000..86595fd7e --- /dev/null +++ b/digitalocean/datasource_digitalocean_records_test.go @@ -0,0 +1,70 @@ +package digitalocean + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "testing" +) + +func TestAccDataSourceDigitalOceanRecords_Basic(t *testing.T) { + name1 := fmt.Sprintf("foobar-test-terraform-%s.com", acctest.RandString(10)) + + resourcesConfig := fmt.Sprintf(` +resource "digitalocean_domain" "foo" { + name = "%s" +} + +resource "digitalocean_record" "mail" { + name = "mail" + domain = digitalocean_domain.foo.name + type = "MX" + priority = 10 + value = "mail.example.com." +} + +resource "digitalocean_record" "www" { + name = "www" + domain = digitalocean_domain.foo.name + type = "A" + value = "192.168.1.1" +} +`, name1) + + datasourceConfig := fmt.Sprintf(` +data "digitalocean_records" "result" { + domain = "%s" + filter { + key = "type" + values = ["A"] + } +} +`, name1) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: resourcesConfig, + }, + { + Config: resourcesConfig + datasourceConfig, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.digitalocean_records.result", "records.#", "1"), + resource.TestCheckResourceAttr("data.digitalocean_records.result", "records.0.domain", name1), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.id", "digitalocean_record.www", "id"), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.name", "digitalocean_record.www", "name"), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.type", "digitalocean_record.www", "type"), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.value", "digitalocean_record.www", "value"), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.priority", "digitalocean_record.www", "priority"), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.port", "digitalocean_record.www", "port"), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.ttl", "digitalocean_record.www", "ttl"), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.weight", "digitalocean_record.www", "weight"), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.flags", "digitalocean_record.www", "flags"), + resource.TestCheckResourceAttrPair("data.digitalocean_records.result", "records.0.tag", "digitalocean_record.www", "tag"), + ), + }, + }, + }) +} diff --git a/digitalocean/datasource_digitalocean_region.go b/digitalocean/datasource_digitalocean_region.go index a6b21d75f..1dc6f5364 100644 --- a/digitalocean/datasource_digitalocean_region.go +++ b/digitalocean/datasource_digitalocean_region.go @@ -42,7 +42,7 @@ func dataSourceDigitalOceanRegion() *schema.Resource { } func dataSourceDigitalOceanRegionRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - regions, err := getDigitalOceanRegions(meta) + regions, err := getDigitalOceanRegions(meta, nil) if err != nil { return diag.Errorf("Unable to load regions: %s", err) } @@ -61,7 +61,7 @@ func dataSourceDigitalOceanRegionRead(ctx context.Context, d *schema.ResourceDat return diag.Errorf("Region does not exist: %s", slug) } - flattenedRegion, err := flattenRegion(*regionForSlug, meta) + flattenedRegion, err := flattenRegion(*regionForSlug, meta, nil) if err != nil { return nil } diff --git a/digitalocean/datasource_digitalocean_sizes.go b/digitalocean/datasource_digitalocean_sizes.go index 0d6076e95..c27bc5c14 100644 --- a/digitalocean/datasource_digitalocean_sizes.go +++ b/digitalocean/datasource_digitalocean_sizes.go @@ -58,7 +58,7 @@ func dataSourceDigitalOceanSizes() *schema.Resource { return datalist.NewResource(dataListConfig) } -func getDigitalOceanSizes(meta interface{}) ([]interface{}, error) { +func getDigitalOceanSizes(meta interface{}, extra map[string]interface{}) ([]interface{}, error) { client := meta.(*CombinedConfig).godoClient() sizes := []interface{}{} @@ -93,7 +93,7 @@ func getDigitalOceanSizes(meta interface{}) ([]interface{}, error) { return sizes, nil } -func flattenDigitalOceanSize(size, meta interface{}) (map[string]interface{}, error) { +func flattenDigitalOceanSize(size, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) { s := size.(godo.Size) flattenedSize := map[string]interface{}{} diff --git a/digitalocean/datasource_digitalocean_spaces_bucket.go b/digitalocean/datasource_digitalocean_spaces_bucket.go index 6b5894598..2ccff9e81 100644 --- a/digitalocean/datasource_digitalocean_spaces_bucket.go +++ b/digitalocean/datasource_digitalocean_spaces_bucket.go @@ -60,7 +60,7 @@ func dataSourceDigitalOceanSpacesBucketRead(ctx context.Context, d *schema.Resou region: region, } - flattenedBucket, err := flattenSpacesBucket(&metadata, meta) + flattenedBucket, err := flattenSpacesBucket(&metadata, meta, nil) if err != nil { return diag.FromErr(err) } diff --git a/digitalocean/datasource_digitalocean_tags.go b/digitalocean/datasource_digitalocean_tags.go index 0ff0351d7..dc56dde6d 100644 --- a/digitalocean/datasource_digitalocean_tags.go +++ b/digitalocean/datasource_digitalocean_tags.go @@ -42,7 +42,7 @@ func dataSourceDigitalOceanTags() *schema.Resource { return datalist.NewResource(dataListConfig) } -func getDigitalOceanTags(meta interface{}) ([]interface{}, error) { +func getDigitalOceanTags(meta interface{}, extra map[string]interface{}) ([]interface{}, error) { client := meta.(*CombinedConfig).godoClient() tagsList := []interface{}{} @@ -77,7 +77,7 @@ func getDigitalOceanTags(meta interface{}) ([]interface{}, error) { return tagsList, nil } -func flattenDigitalOceanTag(tag, meta interface{}) (map[string]interface{}, error) { +func flattenDigitalOceanTag(tag, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) { t := tag.(godo.Tag) flattenedTag := map[string]interface{}{} diff --git a/digitalocean/domains.go b/digitalocean/domains.go index 57f12505e..e8f5049cd 100644 --- a/digitalocean/domains.go +++ b/digitalocean/domains.go @@ -25,7 +25,7 @@ func domainSchema() map[string]*schema.Schema { } } -func getDigitalOceanDomains(meta interface{}) ([]interface{}, error) { +func getDigitalOceanDomains(meta interface{}, extra map[string]interface{}) ([]interface{}, error) { client := meta.(*CombinedConfig).godoClient() opts := &godo.ListOptions{ @@ -61,7 +61,7 @@ func getDigitalOceanDomains(meta interface{}) ([]interface{}, error) { return allDomains, nil } -func flattenDigitalOceanDomain(rawDomain, meta interface{}) (map[string]interface{}, error) { +func flattenDigitalOceanDomain(rawDomain, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) { domain := rawDomain.(godo.Domain) flattenedDomain := map[string]interface{}{ diff --git a/digitalocean/droplets.go b/digitalocean/droplets.go index 9e7b97dab..891fed4ca 100644 --- a/digitalocean/droplets.go +++ b/digitalocean/droplets.go @@ -113,7 +113,7 @@ func dropletSchema() map[string]*schema.Schema { } } -func getDigitalOceanDroplets(meta interface{}) ([]interface{}, error) { +func getDigitalOceanDroplets(meta interface{}, extra map[string]interface{}) ([]interface{}, error) { client := meta.(*CombinedConfig).godoClient() opts := &godo.ListOptions{ @@ -149,7 +149,7 @@ func getDigitalOceanDroplets(meta interface{}) ([]interface{}, error) { return dropletList, nil } -func flattenDigitalOceanDroplet(rawDroplet, meta interface{}) (map[string]interface{}, error) { +func flattenDigitalOceanDroplet(rawDroplet, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) { droplet := rawDroplet.(godo.Droplet) flattenedDroplet := map[string]interface{}{ diff --git a/digitalocean/images.go b/digitalocean/images.go index c62c281f7..58b63e170 100644 --- a/digitalocean/images.go +++ b/digitalocean/images.go @@ -77,7 +77,7 @@ func imageSchema() map[string]*schema.Schema { } } -func getDigitalOceanImages(meta interface{}) ([]interface{}, error) { +func getDigitalOceanImages(meta interface{}, extra map[string]interface{}) ([]interface{}, error) { client := meta.(*CombinedConfig).godoClient() return listDigitalOceanImages(client.Images.List) } @@ -115,7 +115,7 @@ func listDigitalOceanImages(listImages imageListFunc) ([]interface{}, error) { return allImages, nil } -func flattenDigitalOceanImage(rawImage interface{}, meta interface{}) (map[string]interface{}, error) { +func flattenDigitalOceanImage(rawImage interface{}, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) { image, ok := rawImage.(godo.Image) if !ok { return nil, fmt.Errorf("Unable to convert to godo.Image") diff --git a/digitalocean/projects.go b/digitalocean/projects.go index 61898ada6..6d2af0b28 100644 --- a/digitalocean/projects.go +++ b/digitalocean/projects.go @@ -50,7 +50,7 @@ func projectSchema() map[string]*schema.Schema { } } -func getDigitalOceanProjects(meta interface{}) ([]interface{}, error) { +func getDigitalOceanProjects(meta interface{}, extra map[string]interface{}) ([]interface{}, error) { client := meta.(*CombinedConfig).godoClient() var allProjects []interface{} @@ -86,7 +86,7 @@ func getDigitalOceanProjects(meta interface{}) ([]interface{}, error) { return allProjects, nil } -func flattenDigitalOceanProject(rawProject interface{}, meta interface{}) (map[string]interface{}, error) { +func flattenDigitalOceanProject(rawProject interface{}, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) { client := meta.(*CombinedConfig).godoClient() project, ok := rawProject.(godo.Project) diff --git a/digitalocean/provider.go b/digitalocean/provider.go index a5c246a76..0443df425 100644 --- a/digitalocean/provider.go +++ b/digitalocean/provider.go @@ -62,6 +62,7 @@ func Provider() *schema.Provider { "digitalocean_project": dataSourceDigitalOceanProject(), "digitalocean_projects": dataSourceDigitalOceanProjects(), "digitalocean_record": dataSourceDigitalOceanRecord(), + "digitalocean_records": dataSourceDigitalOceanRecords(), "digitalocean_region": dataSourceDigitalOceanRegion(), "digitalocean_regions": dataSourceDigitalOceanRegions(), "digitalocean_sizes": dataSourceDigitalOceanSizes(), diff --git a/digitalocean/records.go b/digitalocean/records.go new file mode 100644 index 000000000..8f5f2e181 --- /dev/null +++ b/digitalocean/records.go @@ -0,0 +1,125 @@ +package digitalocean + +import ( + "context" + "fmt" + "github.com/digitalocean/godo" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func recordsSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "id": { + Type: schema.TypeInt, + Description: "ID of the record", + }, + "domain": { + Type: schema.TypeString, + Description: "domain of the name record", + }, + "name": { + Type: schema.TypeString, + Description: "name of the record", + }, + "type": { + Type: schema.TypeString, + Description: "type of the name record", + }, + "value": { + Type: schema.TypeString, + Description: "name record data", + }, + "priority": { + Type: schema.TypeInt, + Description: "priority of the name record", + }, + "port": { + Type: schema.TypeInt, + Description: "port of the name record", + }, + "ttl": { + Type: schema.TypeInt, + Description: "ttl of the name record", + }, + "weight": { + Type: schema.TypeInt, + Description: "weight of the name record", + }, + "flags": { + Type: schema.TypeInt, + Description: "flags of the name record", + }, + "tag": { + Type: schema.TypeString, + Description: "tag of the name record", + }, + } +} + +func getDigitalOceanRecords(meta interface{}, extra map[string]interface{}) ([]interface{}, error) { + client := meta.(*CombinedConfig).godoClient() + + domain, ok := extra["domain"].(string) + if !ok { + return nil, fmt.Errorf("unable to find `domain` key from query data") + } + + var allRecords []interface{} + + opts := &godo.ListOptions{ + Page: 1, + PerPage: 200, + } + + for { + records, resp, err := client.Domains.Records(context.Background(), domain, opts) + if err != nil { + return nil, fmt.Errorf("Error retrieving records: %s", err) + } + + for _, record := range records { + allRecords = append(allRecords, record) + } + + if resp.Links == nil || resp.Links.IsLastPage() { + break + } + + page, err := resp.Links.CurrentPage() + if err != nil { + return nil, fmt.Errorf("Error retrieving projects: %s", err) + } + + opts.Page = page + 1 + } + + return allRecords, nil +} + +func flattenDigitalOceanRecord(rawRecord interface{}, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) { + domain, ok := extra["domain"].(string) + if !ok { + return nil, fmt.Errorf("unable to find `domain` key from query data") + } + + record, ok := rawRecord.(godo.DomainRecord) + if !ok { + return nil, fmt.Errorf("unable to convert to godo.DomainRecord") + } + + flattenedRecord := map[string]interface{}{ + "id": record.ID, + "domain": domain, + "name": record.Name, + "type": record.Type, + "value": record.Data, + "priority": record.Priority, + "port": record.Port, + "ttl": record.TTL, + "weight": record.Weight, + "flags": record.Flags, + "tag": record.Tag, + } + + return flattenedRecord, nil +} diff --git a/digitalocean/regions.go b/digitalocean/regions.go index df4808741..ebed2d0ea 100644 --- a/digitalocean/regions.go +++ b/digitalocean/regions.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func getDigitalOceanRegions(meta interface{}) ([]interface{}, error) { +func getDigitalOceanRegions(meta interface{}, extra map[string]interface{}) ([]interface{}, error) { client := meta.(*CombinedConfig).godoClient() allRegions := []interface{}{} @@ -44,7 +44,7 @@ func getDigitalOceanRegions(meta interface{}) ([]interface{}, error) { return allRegions, nil } -func flattenRegion(rawRegion, meta interface{}) (map[string]interface{}, error) { +func flattenRegion(rawRegion, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) { region := rawRegion.(godo.Region) flattenedRegion := map[string]interface{}{} diff --git a/digitalocean/spaces_buckets.go b/digitalocean/spaces_buckets.go index 8e30f7735..42fe9b844 100644 --- a/digitalocean/spaces_buckets.go +++ b/digitalocean/spaces_buckets.go @@ -50,7 +50,7 @@ func getSpacesBucketsInRegion(meta interface{}, region string) ([]*s3.Bucket, er return output.Buckets, nil } -func getDigitalOceanBuckets(meta interface{}) ([]interface{}, error) { +func getDigitalOceanBuckets(meta interface{}, extra map[string]interface{}) ([]interface{}, error) { // The DigitalOcean API does not currently return what regions have Spaces available. Thus, this // function hard-codes the regions in which Spaces operates. // @@ -78,7 +78,7 @@ func getDigitalOceanBuckets(meta interface{}) ([]interface{}, error) { return buckets, nil } -func flattenSpacesBucket(rawBucketMetadata, meta interface{}) (map[string]interface{}, error) { +func flattenSpacesBucket(rawBucketMetadata, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) { bucketMetadata := rawBucketMetadata.(*bucketMetadataStruct) name := bucketMetadata.name diff --git a/docs/data-sources/records.md b/docs/data-sources/records.md new file mode 100644 index 000000000..bf6d4985f --- /dev/null +++ b/docs/data-sources/records.md @@ -0,0 +1,76 @@ +--- +page_title: "DigitalOcean: digitalocean_records" +--- + +# digitalocean_record + +Retrieve information about all DNS records within a domain, with the ability to filter and sort the results. +If no filters are specified, all records will be returned. + +## Example Usage + +Get data for all MX records in a domain: + +```hcl +data "digitalocean_records" "example" { + domain = "example.com" + filter { + key = "type" + values = ["MX"] + } +} + +output "mail_servers" { + value = join(",", data.digitalocean_records.example.records) +} +``` + +## Argument Reference + +The following arguments are supported: + +* `domain` - (Required) The domain name to search for DNS records + +* `filter` - (Optional) Filter the results. + The `filter` block is documented below. + +* `sort` - (Optional) Sort the results. + The `sort` block is documented below. + +`filter` supports the following arguments: + +* `key` - (Required) Filter the projects by this key. This may be one of `domain`, `flags`, `name`, `port`, + `priority`, `tag`, `ttl`, `type`, `value`, or `weight`. + +* `values` - (Required) A list of values to match against the `key` field. Only retrieves projects + where the `key` field takes on one or more of the values provided here. + +* `match_by` - (Optional) One of `exact` (default), `re`, or `substring`. For string-typed fields, specify `re` to + match by using the `values` as regular expressions, or specify `substring` to match by treating the `values` as + substrings to find within the string field. + +* `all` - (Optional) Set to `true` to require that a field match all of the `values` instead of just one or more of + them. This is useful when matching against multi-valued fields such as lists or sets where you want to ensure + that all of the `values` are present in the list or set. + +`sort` supports the following arguments: + +* `key` - (Required) Sort the projects by this key. This may be one of `domain`, `flags`, `name`, `port`, + `priority`, `tag`, `ttl`, `type`, `value`, or `weight`. +* `direction` - (Required) The sort direction. This may be either `asc` or `desc`. + +## Attributes Reference + +The following attributes are exported: + +* `id`: The ID of the record. +* `domain`: Domain of the DNS record. +* `name`: The name of the DNS record. +* `type`: The type of the DNS record. +* `value`: Variable data depending on record type. For example, the "data" value for an A record would be the IPv4 address to which the domain will be mapped. For a CAA record, it would contain the domain name of the CA being granted permission to issue certificates. +* `priority`: The priority for SRV and MX records. +* `port`: The port for SRV records. +* `ttl`: This value is the time to live for the record, in seconds. This defines the time frame that clients can cache queried information before a refresh should be requested. +* `weight`: The weight for SRV records. +* `flags`: An unsigned integer between 0-255 used for CAA records. +* `tag`: The parameter tag for CAA records. diff --git a/internal/datalist/schema.go b/internal/datalist/schema.go index 1f6f7af52..a720d3caf 100644 --- a/internal/datalist/schema.go +++ b/internal/datalist/schema.go @@ -21,12 +21,15 @@ type ResourceConfig struct { // Given a record returned from the GetRecords function, flatten the record to a // map acceptable to the Set method on schema.ResourceData. - FlattenRecord func(record, meta interface{}) (map[string]interface{}, error) + FlattenRecord func(record, meta interface{}, extra map[string]interface{}) (map[string]interface{}, error) // Return all of the records on which the data list resource should operate. // The `meta` argument is the same meta argument passed into the resource's Read // function. - GetRecords func(meta interface{}) ([]interface{}, error) + GetRecords func(meta interface{}, extra map[string]interface{}) ([]interface{}, error) + + // Extra parameters to expose on the datasource alongside `filter` and `sort`. + ExtraQuerySchema map[string]*schema.Schema } // Returns a new "data list" resource given the specified configuration. This @@ -53,32 +56,43 @@ func NewResource(config *ResourceConfig) *schema.Resource { filterKeys := computeFilterKeys(recordSchema) sortKeys := computeSortKeys(recordSchema) - return &schema.Resource{ - ReadContext: dataListResourceRead(config), - Schema: map[string]*schema.Schema{ - "filter": filterSchema(filterKeys), - "sort": sortSchema(sortKeys), - config.ResultAttributeName: { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: recordSchema, - }, + datasourceSchema := map[string]*schema.Schema{ + "filter": filterSchema(filterKeys), + "sort": sortSchema(sortKeys), + config.ResultAttributeName: { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: recordSchema, }, }, } + + for key, value := range config.ExtraQuerySchema { + datasourceSchema[key] = value + } + + return &schema.Resource{ + ReadContext: dataListResourceRead(config), + Schema: datasourceSchema, + } } func dataListResourceRead(config *ResourceConfig) schema.ReadContextFunc { return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - records, err := config.GetRecords(meta) + extra := map[string]interface{}{} + for key, _ := range config.ExtraQuerySchema { + extra[key] = d.Get(key) + } + + records, err := config.GetRecords(meta, extra) if err != nil { return diag.Errorf("Unable to load records: %s", err) } flattenedRecords := make([]map[string]interface{}, len(records)) for i, record := range records { - flattenedRecord, err := config.FlattenRecord(record, meta) + flattenedRecord, err := config.FlattenRecord(record, meta, extra) if err != nil { return diag.FromErr(err) }