@@ -6,6 +6,7 @@ package tfe
6
6
import (
7
7
"context"
8
8
"fmt"
9
+ "io"
9
10
"net/url"
10
11
"time"
11
12
)
@@ -31,6 +32,9 @@ type QueryRuns interface {
31
32
// ReadWithOptions reads a query run by its ID using the options supplied
32
33
ReadWithOptions (ctx context.Context , queryRunID string , options * QueryRunReadOptions ) (* QueryRun , error )
33
34
35
+ // Logs retrieves the logs of a query run.
36
+ Logs (ctx context.Context , queryRunID string ) (io.Reader , error )
37
+
34
38
// Cancel a query run by its ID.
35
39
Cancel (ctx context.Context , runID string ) error
36
40
@@ -46,18 +50,17 @@ type QueryRunCreateOptions struct {
46
50
// https://jsonapi.org/format/#crud-creating
47
51
Type string `jsonapi:"primary,queries"`
48
52
49
- // TerraformVersion specifies the Terraform version to use in this run.
50
- // Only valid for plan-only runs; must be a valid Terraform version available to the organization.
53
+ // TerraformVersion specifies the Terraform version to use in this query run.
51
54
TerraformVersion * string `jsonapi:"attr,terraform-version,omitempty"`
52
55
53
56
Source QueryRunSource `jsonapi:"attr,source"`
54
57
55
- // Specifies the configuration version to use for this run. If the
58
+ // Specifies the configuration version to use for this query run. If the
56
59
// configuration version object is omitted, the run will be created using the
57
60
// workspace's latest configuration version.
58
61
ConfigurationVersion * ConfigurationVersion `jsonapi:"relation,configuration-version"`
59
62
60
- // Specifies the workspace where the run will be executed.
63
+ // Specifies the workspace where the query run will be executed.
61
64
Workspace * Workspace `jsonapi:"relation,workspace"`
62
65
63
66
// Variables allows you to specify terraform input variables for
@@ -82,6 +85,19 @@ type QueryRunIncludeOpt string
82
85
// QueryRunSource represents the available sources for query runs.
83
86
type QueryRunSource string
84
87
88
+ // QueryRunStatus is the query run state
89
+ type QueryRunStatus string
90
+
91
+ // List all available run statuses.
92
+ const (
93
+ QueryRunCanceled QueryRunStatus = "canceled"
94
+ QueryRunErrored QueryRunStatus = "errored"
95
+ QueryRunPending QueryRunStatus = "pending"
96
+ QueryRunQueuing QueryRunStatus = "queued"
97
+ QueryRunRunning QueryRunStatus = "running"
98
+ QueryRunFinished QueryRunStatus = "queuing_apply"
99
+ )
100
+
85
101
// List all available run sources.
86
102
const (
87
103
QueryRunSourceAPI QueryRunSource = "tfe-api"
@@ -116,13 +132,14 @@ type QueryRunReadOptions struct {
116
132
117
133
// QueryRun represents a Terraform Enterprise query run.
118
134
type QueryRun struct {
119
- ID string `jsonapi:"primary,queries"`
120
- CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
121
- Source RunSource `jsonapi:"attr,source"`
122
- Status RunStatus `jsonapi:"attr,status"`
123
- StatusTimestamps * RunStatusTimestamps `jsonapi:"attr,status-timestamps"`
124
- TerraformVersion string `jsonapi:"attr,terraform-version"`
125
- Variables []* RunVariableAttr `jsonapi:"attr,variables"`
135
+ ID string `jsonapi:"primary,queries"`
136
+ CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
137
+ Source QueryRunSource `jsonapi:"attr,source"`
138
+ Status QueryRunStatus `jsonapi:"attr,status"`
139
+ StatusTimestamps * QueryRunStatusTimestamps `jsonapi:"attr,status-timestamps"`
140
+ TerraformVersion string `jsonapi:"attr,terraform-version"`
141
+ Variables []* RunVariableAttr `jsonapi:"attr,variables"`
142
+ LogReadURL string `jsonapi:"attr,log-read-url"`
126
143
127
144
// Relations
128
145
ConfigurationVersion * ConfigurationVersion `jsonapi:"relation,configuration-version"`
@@ -206,6 +223,49 @@ func (r *queryRuns) ReadWithOptions(ctx context.Context, queryRunID string, opti
206
223
return & run , nil
207
224
}
208
225
226
+ func (r * queryRuns ) Logs (ctx context.Context , queryRunID string ) (io.Reader , error ) {
227
+ if ! validStringID (& queryRunID ) {
228
+ return nil , ErrInvalidQueryRunID
229
+ }
230
+
231
+ // Get the query to make sure it exists.
232
+ q , err := r .Read (ctx , queryRunID )
233
+ if err != nil {
234
+ return nil , err
235
+ }
236
+
237
+ // Return an error if the log URL is empty.
238
+ if q .LogReadURL == "" {
239
+ return nil , fmt .Errorf ("query %s does not have a log URL" , queryRunID )
240
+ }
241
+
242
+ u , err := url .Parse (q .LogReadURL )
243
+ if err != nil {
244
+ return nil , fmt .Errorf ("invalid log URL: %w" , err )
245
+ }
246
+
247
+ done := func () (bool , error ) {
248
+ p , err := r .Read (ctx , q .ID )
249
+ if err != nil {
250
+ return false , err
251
+ }
252
+
253
+ switch p .Status {
254
+ case QueryRunCanceled , QueryRunErrored , QueryRunFinished :
255
+ return true , nil
256
+ default :
257
+ return false , nil
258
+ }
259
+ }
260
+
261
+ return & LogReader {
262
+ client : r .client ,
263
+ ctx : ctx ,
264
+ done : done ,
265
+ logURL : u ,
266
+ }, nil
267
+ }
268
+
209
269
func (r * queryRuns ) Cancel (ctx context.Context , queryRunID string ) error {
210
270
if queryRunID == "" {
211
271
return ErrInvalidQueryRunID
0 commit comments