4
4
package tfe
5
5
6
6
import (
7
+ "bytes"
7
8
"context"
8
9
"fmt"
9
10
"net/url"
11
+ "strings"
10
12
"time"
11
13
)
12
14
@@ -25,6 +27,8 @@ type Explorer interface {
25
27
QueryProviders (ctx context.Context , organization string , options ExplorerQueryOptions ) (* ExplorerProviderViewList , error )
26
28
// Query information about Terraform version usage within an organization.
27
29
QueryTerraformVersions (ctx context.Context , organization string , options ExplorerQueryOptions ) (* ExplorerTerraformVersionViewList , error )
30
+ // Download a full, unpaged export of query results in CSV format.
31
+ ExportToCSV (ctx context.Context , organization string , options ExplorerQueryOptions ) ([]byte , error )
28
32
}
29
33
30
34
type explorer struct {
@@ -69,7 +73,7 @@ type ExplorerQueryFilter struct {
69
73
Value string
70
74
}
71
75
72
- func (eqf * ExplorerQueryFilter ) toQueryParam () (string , string ) {
76
+ func (eqf * ExplorerQueryFilter ) toKeyValue () (string , string ) {
73
77
key := fmt .Sprintf ("filter[%d][%s][%s][0]" , eqf .Index , eqf .Name , eqf .Operator )
74
78
return key , eqf .Value
75
79
}
@@ -78,13 +82,30 @@ func (eqf *ExplorerQueryFilter) toQueryParam() (string, string) {
78
82
type ExplorerQueryOptions struct {
79
83
ListOptions
80
84
81
- View ExplorerViewType `url:"type"`
82
- Sort string `url:"sort,omitempty"`
83
- Fields string `url:"fields,omitempty"`
85
+ View ExplorerViewType `url:"type"`
86
+ Sort string `url:"sort,omitempty"`
84
87
88
+ Fields []string `url:"-"`
85
89
Filters []* ExplorerQueryFilter `url:"-"`
86
90
}
87
91
92
+ func (eqo * ExplorerQueryOptions ) extractFilters () map [string ][]string {
93
+ filterParams := make (map [string ][]string )
94
+ for _ , filter := range eqo .Filters {
95
+ if filter != nil {
96
+ k , v := filter .toKeyValue ()
97
+ filterParams [k ] = []string {v }
98
+ }
99
+ }
100
+
101
+ // Append the fields query param, ensuring the correct view type is specified
102
+ if len (eqo .Fields ) > 0 {
103
+ fieldsKey := fmt .Sprintf ("fields[%s]" , eqo .View )
104
+ filterParams [fieldsKey ] = []string {strings .Join (eqo .Fields , "," )}
105
+ }
106
+ return filterParams
107
+ }
108
+
88
109
// WorkspaceView represents information about a workspace in the target
89
110
// organization and any current runs associated with that workspace.
90
111
type WorkspaceView struct {
@@ -251,16 +272,32 @@ func (e *explorer) QueryTerraformVersions(ctx context.Context, organization stri
251
272
return eql , nil
252
273
}
253
274
254
- func (e * explorer ) buildExplorerQueryRequest (organization string , options ExplorerQueryOptions ) (* ClientRequest , error ) {
255
- filterParams := make (map [string ][]string )
256
- u := fmt .Sprintf ("organizations/%s/explorer" , url .QueryEscape (organization ))
275
+ // ExportToCSV performs an Explorer query and exports the results to CSV format.
276
+ // https://developer.hashicorp.com/terraform/cloud-docs/api-docs/explorer#export-data-as-csv
277
+ func (e * explorer ) ExportToCSV (ctx context.Context , organization string , options ExplorerQueryOptions ) ([]byte , error ) {
278
+ filterParams := options .extractFilters ()
257
279
258
- for _ , filter := range options .Filters {
259
- if filter != nil {
260
- k , v := filter .toQueryParam ()
261
- filterParams [k ] = []string {v }
262
- }
280
+ u := fmt .Sprintf ("organizations/%s/explorer/export/csv" , url .QueryEscape (organization ))
281
+ req , err := e .client .NewRequestWithAdditionalQueryParams ("GET" , u , options , filterParams )
282
+ if err != nil {
283
+ return nil , err
263
284
}
264
285
286
+ // Override accept header
287
+ req .retryableRequest .Header .Set ("Accept" , "*/*" )
288
+
289
+ buf := & bytes.Buffer {}
290
+ err = req .Do (ctx , buf )
291
+ if err != nil {
292
+ return nil , err
293
+ }
294
+
295
+ return buf .Bytes (), nil
296
+ }
297
+
298
+ func (e * explorer ) buildExplorerQueryRequest (organization string , options ExplorerQueryOptions ) (* ClientRequest , error ) {
299
+ filterParams := options .extractFilters ()
300
+
301
+ u := fmt .Sprintf ("organizations/%s/explorer" , url .QueryEscape (organization ))
265
302
return e .client .NewRequestWithAdditionalQueryParams ("GET" , u , options , filterParams )
266
303
}
0 commit comments