mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
govendor: update go-tfe
This commit is contained in:
parent
5522500777
commit
4b9f17d967
131
vendor/github.com/hashicorp/go-tfe/apply.go
generated
vendored
Normal file
131
vendor/github.com/hashicorp/go-tfe/apply.go
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
package tfe
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Compile-time proof of interface implementation.
|
||||||
|
var _ Applies = (*applies)(nil)
|
||||||
|
|
||||||
|
// Applies describes all the apply related methods that the Terraform
|
||||||
|
// Enterprise API supports.
|
||||||
|
//
|
||||||
|
// TFE API docs: https://www.terraform.io/docs/enterprise/api/apply.html
|
||||||
|
type Applies interface {
|
||||||
|
// Read an apply by its ID.
|
||||||
|
Read(ctx context.Context, applyID string) (*Apply, error)
|
||||||
|
|
||||||
|
// Logs retrieves the logs of an apply.
|
||||||
|
Logs(ctx context.Context, applyID string) (io.Reader, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// applies implements Applys.
|
||||||
|
type applies struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyStatus represents an apply state.
|
||||||
|
type ApplyStatus string
|
||||||
|
|
||||||
|
//List all available apply statuses.
|
||||||
|
const (
|
||||||
|
ApplyCanceled ApplyStatus = "canceled"
|
||||||
|
ApplyCreated ApplyStatus = "created"
|
||||||
|
ApplyErrored ApplyStatus = "errored"
|
||||||
|
ApplyFinished ApplyStatus = "finished"
|
||||||
|
ApplyMFAWaiting ApplyStatus = "mfa_waiting"
|
||||||
|
ApplyPending ApplyStatus = "pending"
|
||||||
|
ApplyQueued ApplyStatus = "queued"
|
||||||
|
ApplyRunning ApplyStatus = "running"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Apply represents a Terraform Enterprise apply.
|
||||||
|
type Apply struct {
|
||||||
|
ID string `jsonapi:"primary,applies"`
|
||||||
|
LogReadURL string `jsonapi:"attr,log-read-url"`
|
||||||
|
ResourceAdditions int `jsonapi:"attr,resource-additions"`
|
||||||
|
ResourceChanges int `jsonapi:"attr,resource-changes"`
|
||||||
|
ResourceDestructions int `jsonapi:"attr,resource-destructions"`
|
||||||
|
Status ApplyStatus `jsonapi:"attr,status"`
|
||||||
|
StatusTimestamps *ApplyStatusTimestamps `jsonapi:"attr,status-timestamps"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyStatusTimestamps holds the timestamps for individual apply statuses.
|
||||||
|
type ApplyStatusTimestamps struct {
|
||||||
|
CanceledAt time.Time `json:"canceled-at"`
|
||||||
|
ErroredAt time.Time `json:"errored-at"`
|
||||||
|
FinishedAt time.Time `json:"finished-at"`
|
||||||
|
ForceCanceledAt time.Time `json:"force-canceled-at"`
|
||||||
|
QueuedAt time.Time `json:"queued-at"`
|
||||||
|
StartedAt time.Time `json:"started-at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read an apply by its ID.
|
||||||
|
func (s *applies) Read(ctx context.Context, applyID string) (*Apply, error) {
|
||||||
|
if !validStringID(&applyID) {
|
||||||
|
return nil, errors.New("Invalid value for apply ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf("applies/%s", url.QueryEscape(applyID))
|
||||||
|
req, err := s.client.newRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a := &Apply{}
|
||||||
|
err = s.client.do(ctx, req, a)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logs retrieves the logs of an apply.
|
||||||
|
func (s *applies) Logs(ctx context.Context, applyID string) (io.Reader, error) {
|
||||||
|
if !validStringID(&applyID) {
|
||||||
|
return nil, errors.New("Invalid value for apply ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the apply to make sure it exists.
|
||||||
|
a, err := s.Read(ctx, applyID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an error if the log URL is empty.
|
||||||
|
if a.LogReadURL == "" {
|
||||||
|
return nil, fmt.Errorf("Apply %s does not have a log URL", applyID)
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse(a.LogReadURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Invalid log URL: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
done := func() (bool, error) {
|
||||||
|
a, err := s.Read(ctx, a.ID)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch a.Status {
|
||||||
|
case ApplyCanceled, ApplyErrored, ApplyFinished:
|
||||||
|
return true, nil
|
||||||
|
default:
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &LogReader{
|
||||||
|
client: s.client,
|
||||||
|
ctx: ctx,
|
||||||
|
done: done,
|
||||||
|
logURL: u,
|
||||||
|
}, nil
|
||||||
|
}
|
91
vendor/github.com/hashicorp/go-tfe/logreader.go
generated
vendored
Normal file
91
vendor/github.com/hashicorp/go-tfe/logreader.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package tfe
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LogReader implements io.Reader for streaming logs.
|
||||||
|
type LogReader struct {
|
||||||
|
client *Client
|
||||||
|
ctx context.Context
|
||||||
|
done func() (bool, error)
|
||||||
|
logURL *url.URL
|
||||||
|
offset int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *LogReader) Read(l []byte) (int, error) {
|
||||||
|
if written, err := r.read(l); err != io.ErrNoProgress {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop until we can any data, the context is canceled or the
|
||||||
|
// run is finsished. If we would return right away without any
|
||||||
|
// data, we could and up causing a io.ErrNoProgress error.
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-r.ctx.Done():
|
||||||
|
return 0, r.ctx.Err()
|
||||||
|
case <-time.After(500 * time.Millisecond):
|
||||||
|
if written, err := r.read(l); err != io.ErrNoProgress {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *LogReader) read(l []byte) (int, error) {
|
||||||
|
// Update the query string.
|
||||||
|
r.logURL.RawQuery = fmt.Sprintf("limit=%d&offset=%d", len(l), r.offset)
|
||||||
|
|
||||||
|
// Create a new request.
|
||||||
|
req, err := http.NewRequest("GET", r.logURL.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
req = req.WithContext(r.ctx)
|
||||||
|
|
||||||
|
// Retrieve the next chunk.
|
||||||
|
resp, err := r.client.http.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// Basic response checking.
|
||||||
|
if err := checkResponseCode(resp); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the retrieved chunk.
|
||||||
|
written, err := resp.Body.Read(l)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
// Ignore io.EOF errors returned when reading from the response
|
||||||
|
// body as this indicates the end of the chunk and not the end
|
||||||
|
// of the logfile.
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we need to continue the loop and wait 500 miliseconds
|
||||||
|
// before checking if there is a new chunk available or that the
|
||||||
|
// run is finished and we are done reading all chunks.
|
||||||
|
if written == 0 {
|
||||||
|
done, err := r.done()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if done {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
return 0, io.ErrNoProgress
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the offset for the next read.
|
||||||
|
r.offset += int64(written)
|
||||||
|
|
||||||
|
return written, nil
|
||||||
|
}
|
98
vendor/github.com/hashicorp/go-tfe/oauth_client.go
generated
vendored
98
vendor/github.com/hashicorp/go-tfe/oauth_client.go
generated
vendored
@ -17,8 +17,17 @@ var _ OAuthClients = (*oAuthClients)(nil)
|
|||||||
// TFE API docs:
|
// TFE API docs:
|
||||||
// https://www.terraform.io/docs/enterprise/api/oauth-clients.html
|
// https://www.terraform.io/docs/enterprise/api/oauth-clients.html
|
||||||
type OAuthClients interface {
|
type OAuthClients interface {
|
||||||
// Create a VCS connection between an organization and a VCS provider.
|
// List all the OAuth clients for a given organization.
|
||||||
|
List(ctx context.Context, organization string, options OAuthClientListOptions) (*OAuthClientList, error)
|
||||||
|
|
||||||
|
// Create an OAuth client to connect an organization and a VCS provider.
|
||||||
Create(ctx context.Context, organization string, options OAuthClientCreateOptions) (*OAuthClient, error)
|
Create(ctx context.Context, organization string, options OAuthClientCreateOptions) (*OAuthClient, error)
|
||||||
|
|
||||||
|
// Read an OAuth client by its ID.
|
||||||
|
Read(ctx context.Context, oAuthClientID string) (*OAuthClient, error)
|
||||||
|
|
||||||
|
// Delete an OAuth client by its ID.
|
||||||
|
Delete(ctx context.Context, oAuthClientID string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// oAuthClients implements OAuthClients.
|
// oAuthClients implements OAuthClients.
|
||||||
@ -40,6 +49,12 @@ const (
|
|||||||
ServiceProviderGitlabEE ServiceProviderType = "gitlab_enterprise_edition"
|
ServiceProviderGitlabEE ServiceProviderType = "gitlab_enterprise_edition"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OAuthClientList represents a list of OAuth clients.
|
||||||
|
type OAuthClientList struct {
|
||||||
|
*Pagination
|
||||||
|
Items []*OAuthClient
|
||||||
|
}
|
||||||
|
|
||||||
// OAuthClient represents a connection between an organization and a VCS
|
// OAuthClient represents a connection between an organization and a VCS
|
||||||
// provider.
|
// provider.
|
||||||
type OAuthClient struct {
|
type OAuthClient struct {
|
||||||
@ -56,7 +71,34 @@ type OAuthClient struct {
|
|||||||
|
|
||||||
// Relations
|
// Relations
|
||||||
Organization *Organization `jsonapi:"relation,organization"`
|
Organization *Organization `jsonapi:"relation,organization"`
|
||||||
OAuthToken []*OAuthToken `jsonapi:"relation,oauth-token"`
|
OAuthTokens []*OAuthToken `jsonapi:"relation,oauth-tokens"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// OAuthClientListOptions represents the options for listing
|
||||||
|
// OAuth clients.
|
||||||
|
type OAuthClientListOptions struct {
|
||||||
|
ListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// List all the OAuth clients for a given organization.
|
||||||
|
func (s *oAuthClients) List(ctx context.Context, organization string, options OAuthClientListOptions) (*OAuthClientList, error) {
|
||||||
|
if !validStringID(&organization) {
|
||||||
|
return nil, errors.New("Invalid value for organization")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf("organizations/%s/oauth-clients", url.QueryEscape(organization))
|
||||||
|
req, err := s.client.newRequest("GET", u, &options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ocl := &OAuthClientList{}
|
||||||
|
err = s.client.do(ctx, req, ocl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ocl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OAuthClientCreateOptions represents the options for creating an OAuth client.
|
// OAuthClientCreateOptions represents the options for creating an OAuth client.
|
||||||
@ -70,11 +112,8 @@ type OAuthClientCreateOptions struct {
|
|||||||
// The homepage of your VCS provider.
|
// The homepage of your VCS provider.
|
||||||
HTTPURL *string `jsonapi:"attr,http-url"`
|
HTTPURL *string `jsonapi:"attr,http-url"`
|
||||||
|
|
||||||
// The key you were given by your VCS provider.
|
// The token string you were given by your VCS provider.
|
||||||
Key *string `jsonapi:"attr,key"`
|
OAuthToken *string `jsonapi:"attr,oauth-token-string"`
|
||||||
|
|
||||||
// The secret you were given by your VCS provider.
|
|
||||||
Secret *string `jsonapi:"attr,secret"`
|
|
||||||
|
|
||||||
// The VCS provider being connected with.
|
// The VCS provider being connected with.
|
||||||
ServiceProvider *ServiceProviderType `jsonapi:"attr,service-provider"`
|
ServiceProvider *ServiceProviderType `jsonapi:"attr,service-provider"`
|
||||||
@ -87,11 +126,8 @@ func (o OAuthClientCreateOptions) valid() error {
|
|||||||
if !validString(o.HTTPURL) {
|
if !validString(o.HTTPURL) {
|
||||||
return errors.New("HTTPURL is required")
|
return errors.New("HTTPURL is required")
|
||||||
}
|
}
|
||||||
if !validString(o.Key) {
|
if !validString(o.OAuthToken) {
|
||||||
return errors.New("Key is required")
|
return errors.New("OAuthToken is required")
|
||||||
}
|
|
||||||
if !validString(o.Secret) {
|
|
||||||
return errors.New("Secret is required")
|
|
||||||
}
|
}
|
||||||
if o.ServiceProvider == nil {
|
if o.ServiceProvider == nil {
|
||||||
return errors.New("ServiceProvider is required")
|
return errors.New("ServiceProvider is required")
|
||||||
@ -99,7 +135,7 @@ func (o OAuthClientCreateOptions) valid() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a VCS connection between an organization and a VCS provider.
|
// Create an OAuth client to connect an organization and a VCS provider.
|
||||||
func (s *oAuthClients) Create(ctx context.Context, organization string, options OAuthClientCreateOptions) (*OAuthClient, error) {
|
func (s *oAuthClients) Create(ctx context.Context, organization string, options OAuthClientCreateOptions) (*OAuthClient, error) {
|
||||||
if !validStringID(&organization) {
|
if !validStringID(&organization) {
|
||||||
return nil, errors.New("Invalid value for organization")
|
return nil, errors.New("Invalid value for organization")
|
||||||
@ -125,3 +161,39 @@ func (s *oAuthClients) Create(ctx context.Context, organization string, options
|
|||||||
|
|
||||||
return oc, nil
|
return oc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read an OAuth client by its ID.
|
||||||
|
func (s *oAuthClients) Read(ctx context.Context, oAuthClientID string) (*OAuthClient, error) {
|
||||||
|
if !validStringID(&oAuthClientID) {
|
||||||
|
return nil, errors.New("Invalid value for OAuth client ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf("oauth-clients/%s", url.QueryEscape(oAuthClientID))
|
||||||
|
req, err := s.client.newRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
oc := &OAuthClient{}
|
||||||
|
err = s.client.do(ctx, req, oc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return oc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete an OAuth client by its ID.
|
||||||
|
func (s *oAuthClients) Delete(ctx context.Context, oAuthClientID string) error {
|
||||||
|
if !validStringID(&oAuthClientID) {
|
||||||
|
return errors.New("Invalid value for OAuth client ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf("oauth-clients/%s", url.QueryEscape(oAuthClientID))
|
||||||
|
req, err := s.client.newRequest("DELETE", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.client.do(ctx, req, nil)
|
||||||
|
}
|
||||||
|
79
vendor/github.com/hashicorp/go-tfe/oauth_token.go
generated
vendored
79
vendor/github.com/hashicorp/go-tfe/oauth_token.go
generated
vendored
@ -17,8 +17,16 @@ var _ OAuthTokens = (*oAuthTokens)(nil)
|
|||||||
// TFE API docs:
|
// TFE API docs:
|
||||||
// https://www.terraform.io/docs/enterprise/api/oauth-tokens.html
|
// https://www.terraform.io/docs/enterprise/api/oauth-tokens.html
|
||||||
type OAuthTokens interface {
|
type OAuthTokens interface {
|
||||||
// List all the OAuth Tokens for a given organization.
|
// List all the OAuth tokens for a given organization.
|
||||||
List(ctx context.Context, organization string, options OAuthTokenListOptions) (*OAuthTokenList, error)
|
List(ctx context.Context, organization string, options OAuthTokenListOptions) (*OAuthTokenList, error)
|
||||||
|
// Read a OAuth token by its ID.
|
||||||
|
Read(ctx context.Context, oAuthTokenID string) (*OAuthToken, error)
|
||||||
|
|
||||||
|
// Update an existing OAuth token.
|
||||||
|
Update(ctx context.Context, oAuthTokenID string, options OAuthTokenUpdateOptions) (*OAuthToken, error)
|
||||||
|
|
||||||
|
// Delete a OAuth token by its ID.
|
||||||
|
Delete(ctx context.Context, oAuthTokenID string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// oAuthTokens implements OAuthTokens.
|
// oAuthTokens implements OAuthTokens.
|
||||||
@ -71,3 +79,72 @@ func (s *oAuthTokens) List(ctx context.Context, organization string, options OAu
|
|||||||
|
|
||||||
return otl, nil
|
return otl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read an OAuth token by its ID.
|
||||||
|
func (s *oAuthTokens) Read(ctx context.Context, oAuthTokenID string) (*OAuthToken, error) {
|
||||||
|
if !validStringID(&oAuthTokenID) {
|
||||||
|
return nil, errors.New("Invalid value for OAuth token ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf("oauth-tokens/%s", url.QueryEscape(oAuthTokenID))
|
||||||
|
req, err := s.client.newRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ot := &OAuthToken{}
|
||||||
|
err = s.client.do(ctx, req, ot)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ot, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// OAuthTokenUpdateOptions represents the options for updating an OAuth token.
|
||||||
|
type OAuthTokenUpdateOptions struct {
|
||||||
|
// For internal use only!
|
||||||
|
ID string `jsonapi:"primary,oauth-tokens"`
|
||||||
|
|
||||||
|
// A private SSH key to be used for git clone operations.
|
||||||
|
PrivateSSHKey *string `jsonapi:"attr,ssh-key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update an existing OAuth token.
|
||||||
|
func (s *oAuthTokens) Update(ctx context.Context, oAuthTokenID string, options OAuthTokenUpdateOptions) (*OAuthToken, error) {
|
||||||
|
if !validStringID(&oAuthTokenID) {
|
||||||
|
return nil, errors.New("Invalid value for OAuth token ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we don't send a user provided ID.
|
||||||
|
options.ID = ""
|
||||||
|
|
||||||
|
u := fmt.Sprintf("oauth-tokens/%s", url.QueryEscape(oAuthTokenID))
|
||||||
|
req, err := s.client.newRequest("PATCH", u, &options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ot := &OAuthToken{}
|
||||||
|
err = s.client.do(ctx, req, ot)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ot, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete an OAuth token by its ID.
|
||||||
|
func (s *oAuthTokens) Delete(ctx context.Context, oAuthTokenID string) error {
|
||||||
|
if !validStringID(&oAuthTokenID) {
|
||||||
|
return errors.New("Invalid value for OAuth token ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf("oauth-tokens/%s", url.QueryEscape(oAuthTokenID))
|
||||||
|
req, err := s.client.newRequest("DELETE", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.client.do(ctx, req, nil)
|
||||||
|
}
|
||||||
|
132
vendor/github.com/hashicorp/go-tfe/plan.go
generated
vendored
132
vendor/github.com/hashicorp/go-tfe/plan.go
generated
vendored
@ -5,7 +5,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -47,23 +46,24 @@ const (
|
|||||||
|
|
||||||
// Plan represents a Terraform Enterprise plan.
|
// Plan represents a Terraform Enterprise plan.
|
||||||
type Plan struct {
|
type Plan struct {
|
||||||
ID string `jsonapi:"primary,plans"`
|
ID string `jsonapi:"primary,plans"`
|
||||||
HasChanges bool `jsonapi:"attr,has-changes"`
|
HasChanges bool `jsonapi:"attr,has-changes"`
|
||||||
LogReadURL string `jsonapi:"attr,log-read-url"`
|
LogReadURL string `jsonapi:"attr,log-read-url"`
|
||||||
Status PlanStatus `jsonapi:"attr,status"`
|
ResourceAdditions int `jsonapi:"attr,resource-additions"`
|
||||||
StatusTimestamps *PlanStatusTimestamps `jsonapi:"attr,status-timestamps"`
|
ResourceChanges int `jsonapi:"attr,resource-changes"`
|
||||||
|
ResourceDestructions int `jsonapi:"attr,resource-destructions"`
|
||||||
|
Status PlanStatus `jsonapi:"attr,status"`
|
||||||
|
StatusTimestamps *PlanStatusTimestamps `jsonapi:"attr,status-timestamps"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlanStatusTimestamps holds the timestamps for individual plan statuses.
|
// PlanStatusTimestamps holds the timestamps for individual plan statuses.
|
||||||
type PlanStatusTimestamps struct {
|
type PlanStatusTimestamps struct {
|
||||||
CanceledAt time.Time `json:"canceled-at"`
|
CanceledAt time.Time `json:"canceled-at"`
|
||||||
CreatedAt time.Time `json:"created-at"`
|
ErroredAt time.Time `json:"errored-at"`
|
||||||
ErroredAt time.Time `json:"errored-at"`
|
FinishedAt time.Time `json:"finished-at"`
|
||||||
FinishedAt time.Time `json:"finished-at"`
|
ForceCanceledAt time.Time `json:"force-canceled-at"`
|
||||||
MFAWaitingAt time.Time `json:"mfa_waiting-at"`
|
QueuedAt time.Time `json:"queued-at"`
|
||||||
PendingAt time.Time `json:"pending-at"`
|
StartedAt time.Time `json:"started-at"`
|
||||||
QueuedAt time.Time `json:"queued-at"`
|
|
||||||
RunningAt time.Time `json:"running-at"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a plan by its ID.
|
// Read a plan by its ID.
|
||||||
@ -109,98 +109,24 @@ func (s *plans) Logs(ctx context.Context, planID string) (io.Reader, error) {
|
|||||||
return nil, fmt.Errorf("Invalid log URL: %v", err)
|
return nil, fmt.Errorf("Invalid log URL: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done := func() (bool, error) {
|
||||||
|
p, err := s.Read(ctx, p.ID)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch p.Status {
|
||||||
|
case PlanCanceled, PlanErrored, PlanFinished:
|
||||||
|
return true, nil
|
||||||
|
default:
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &LogReader{
|
return &LogReader{
|
||||||
client: s.client,
|
client: s.client,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
done: done,
|
||||||
logURL: u,
|
logURL: u,
|
||||||
plan: p,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogReader implements io.Reader for streaming plan logs.
|
|
||||||
type LogReader struct {
|
|
||||||
client *Client
|
|
||||||
ctx context.Context
|
|
||||||
logURL *url.URL
|
|
||||||
offset int64
|
|
||||||
plan *Plan
|
|
||||||
reads uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *LogReader) Read(l []byte) (int, error) {
|
|
||||||
if written, err := r.read(l); err != io.ErrNoProgress {
|
|
||||||
return written, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop until we can any data, the context is canceled or the plan
|
|
||||||
// is finsished running. If we would return right away without any
|
|
||||||
// data, we could and up causing a io.ErrNoProgress error.
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-r.ctx.Done():
|
|
||||||
return 0, r.ctx.Err()
|
|
||||||
case <-time.After(500 * time.Millisecond):
|
|
||||||
if written, err := r.read(l); err != io.ErrNoProgress {
|
|
||||||
return written, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *LogReader) read(l []byte) (int, error) {
|
|
||||||
// Update the query string.
|
|
||||||
r.logURL.RawQuery = fmt.Sprintf("limit=%d&offset=%d", len(l), r.offset)
|
|
||||||
|
|
||||||
// Create a new request.
|
|
||||||
req, err := http.NewRequest("GET", r.logURL.String(), nil)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
req = req.WithContext(r.ctx)
|
|
||||||
|
|
||||||
// Retrieve the next chunk.
|
|
||||||
resp, err := r.client.http.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
// Basic response checking.
|
|
||||||
if err := checkResponseCode(resp); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the retrieved chunk.
|
|
||||||
written, err := resp.Body.Read(l)
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
// Ignore io.EOF errors returned when reading from the response
|
|
||||||
// body as this indicates the end of the chunk and not the end
|
|
||||||
// of the logfile.
|
|
||||||
return written, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we need to continue the loop and wait 500 miliseconds
|
|
||||||
// before checking if there is a new chunk available or that the
|
|
||||||
// plan is finished and we are done reading all chunks.
|
|
||||||
if written == 0 {
|
|
||||||
if r.reads%2 == 0 {
|
|
||||||
r.plan, err = r.client.Plans.Read(r.ctx, r.plan.ID)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch r.plan.Status {
|
|
||||||
case PlanCanceled, PlanErrored, PlanFinished:
|
|
||||||
return 0, io.EOF
|
|
||||||
default:
|
|
||||||
r.reads++
|
|
||||||
return 0, io.ErrNoProgress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the offset for the next read.
|
|
||||||
r.offset += int64(written)
|
|
||||||
|
|
||||||
return written, nil
|
|
||||||
}
|
|
||||||
|
72
vendor/github.com/hashicorp/go-tfe/policy_check.go
generated
vendored
72
vendor/github.com/hashicorp/go-tfe/policy_check.go
generated
vendored
@ -1,9 +1,11 @@
|
|||||||
package tfe
|
package tfe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -20,8 +22,14 @@ type PolicyChecks interface {
|
|||||||
// List all policy checks of the given run.
|
// List all policy checks of the given run.
|
||||||
List(ctx context.Context, runID string, options PolicyCheckListOptions) (*PolicyCheckList, error)
|
List(ctx context.Context, runID string, options PolicyCheckListOptions) (*PolicyCheckList, error)
|
||||||
|
|
||||||
|
// Read a policy check by its ID.
|
||||||
|
Read(ctx context.Context, policyCheckID string) (*PolicyCheck, error)
|
||||||
|
|
||||||
// Override a soft-mandatory or warning policy.
|
// Override a soft-mandatory or warning policy.
|
||||||
Override(ctx context.Context, policyCheckID string) (*PolicyCheck, error)
|
Override(ctx context.Context, policyCheckID string) (*PolicyCheck, error)
|
||||||
|
|
||||||
|
// Logs retrieves the logs of a policy check.
|
||||||
|
Logs(ctx context.Context, policyCheckID string) (io.Reader, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// policyChecks implements PolicyChecks.
|
// policyChecks implements PolicyChecks.
|
||||||
@ -64,7 +72,7 @@ type PolicyCheck struct {
|
|||||||
Actions *PolicyActions `jsonapi:"attr,actions"`
|
Actions *PolicyActions `jsonapi:"attr,actions"`
|
||||||
Permissions *PolicyPermissions `jsonapi:"attr,permissions"`
|
Permissions *PolicyPermissions `jsonapi:"attr,permissions"`
|
||||||
Result *PolicyResult `jsonapi:"attr,result"`
|
Result *PolicyResult `jsonapi:"attr,result"`
|
||||||
Scope PolicyScope `jsonapi:"attr,source"`
|
Scope PolicyScope `jsonapi:"attr,scope"`
|
||||||
Status PolicyStatus `jsonapi:"attr,status"`
|
Status PolicyStatus `jsonapi:"attr,status"`
|
||||||
StatusTimestamps *PolicyStatusTimestamps `jsonapi:"attr,status-timestamps"`
|
StatusTimestamps *PolicyStatusTimestamps `jsonapi:"attr,status-timestamps"`
|
||||||
}
|
}
|
||||||
@ -127,6 +135,27 @@ func (s *policyChecks) List(ctx context.Context, runID string, options PolicyChe
|
|||||||
return pcl, nil
|
return pcl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read a policy check by its ID.
|
||||||
|
func (s *policyChecks) Read(ctx context.Context, policyCheckID string) (*PolicyCheck, error) {
|
||||||
|
if !validStringID(&policyCheckID) {
|
||||||
|
return nil, errors.New("Invalid value for policy check ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf("policy-checks/%s", url.QueryEscape(policyCheckID))
|
||||||
|
req, err := s.client.newRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pc := &PolicyCheck{}
|
||||||
|
err = s.client.do(ctx, req, pc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return pc, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Override a soft-mandatory or warning policy.
|
// Override a soft-mandatory or warning policy.
|
||||||
func (s *policyChecks) Override(ctx context.Context, policyCheckID string) (*PolicyCheck, error) {
|
func (s *policyChecks) Override(ctx context.Context, policyCheckID string) (*PolicyCheck, error) {
|
||||||
if !validStringID(&policyCheckID) {
|
if !validStringID(&policyCheckID) {
|
||||||
@ -147,3 +176,44 @@ func (s *policyChecks) Override(ctx context.Context, policyCheckID string) (*Pol
|
|||||||
|
|
||||||
return pc, nil
|
return pc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logs retrieves the logs of a policy check.
|
||||||
|
func (s *policyChecks) Logs(ctx context.Context, policyCheckID string) (io.Reader, error) {
|
||||||
|
if !validStringID(&policyCheckID) {
|
||||||
|
return nil, errors.New("Invalid value for policy check ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop until the context is canceled or the policy check is finished
|
||||||
|
// running. The policy check logs are not streamed and so only available
|
||||||
|
// once the check is finished.
|
||||||
|
for {
|
||||||
|
pc, err := s.Read(ctx, policyCheckID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch pc.Status {
|
||||||
|
case PolicyPending, PolicyQueued:
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case <-time.After(500 * time.Millisecond):
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf("policy-checks/%s/output", url.QueryEscape(policyCheckID))
|
||||||
|
req, err := s.client.newRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logs := bytes.NewBuffer(nil)
|
||||||
|
err = s.client.do(ctx, req, logs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return logs, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4
vendor/github.com/hashicorp/go-tfe/run.go
generated
vendored
4
vendor/github.com/hashicorp/go-tfe/run.go
generated
vendored
@ -89,15 +89,17 @@ type Run struct {
|
|||||||
StatusTimestamps *RunStatusTimestamps `jsonapi:"attr,status-timestamps"`
|
StatusTimestamps *RunStatusTimestamps `jsonapi:"attr,status-timestamps"`
|
||||||
|
|
||||||
// Relations
|
// Relations
|
||||||
|
Apply *Apply `jsonapi:"relation,apply"`
|
||||||
ConfigurationVersion *ConfigurationVersion `jsonapi:"relation,configuration-version"`
|
ConfigurationVersion *ConfigurationVersion `jsonapi:"relation,configuration-version"`
|
||||||
Plan *Plan `jsonapi:"relation,plan"`
|
Plan *Plan `jsonapi:"relation,plan"`
|
||||||
|
PolicyChecks []*PolicyCheck `jsonapi:"relation,policy-checks"`
|
||||||
Workspace *Workspace `jsonapi:"relation,workspace"`
|
Workspace *Workspace `jsonapi:"relation,workspace"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunActions represents the run actions.
|
// RunActions represents the run actions.
|
||||||
type RunActions struct {
|
type RunActions struct {
|
||||||
IsCancelable bool `json:"is-cancelable"`
|
IsCancelable bool `json:"is-cancelable"`
|
||||||
IsComfirmable bool `json:"is-comfirmable"`
|
IsConfirmable bool `json:"is-confirmable"`
|
||||||
IsDiscardable bool `json:"is-discardable"`
|
IsDiscardable bool `json:"is-discardable"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
vendor/github.com/hashicorp/go-tfe/tfe.go
generated
vendored
4
vendor/github.com/hashicorp/go-tfe/tfe.go
generated
vendored
@ -58,7 +58,7 @@ func DefaultConfig() *Config {
|
|||||||
Address: os.Getenv("TFE_ADDRESS"),
|
Address: os.Getenv("TFE_ADDRESS"),
|
||||||
BasePath: DefaultBasePath,
|
BasePath: DefaultBasePath,
|
||||||
Token: os.Getenv("TFE_TOKEN"),
|
Token: os.Getenv("TFE_TOKEN"),
|
||||||
HTTPClient: cleanhttp.DefaultClient(),
|
HTTPClient: cleanhttp.DefaultPooledClient(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the default address if none is given.
|
// Set the default address if none is given.
|
||||||
@ -77,6 +77,7 @@ type Client struct {
|
|||||||
http *http.Client
|
http *http.Client
|
||||||
userAgent string
|
userAgent string
|
||||||
|
|
||||||
|
Applies Applies
|
||||||
ConfigurationVersions ConfigurationVersions
|
ConfigurationVersions ConfigurationVersions
|
||||||
OAuthClients OAuthClients
|
OAuthClients OAuthClients
|
||||||
OAuthTokens OAuthTokens
|
OAuthTokens OAuthTokens
|
||||||
@ -142,6 +143,7 @@ func NewClient(cfg *Config) (*Client, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the services.
|
// Create the services.
|
||||||
|
client.Applies = &applies{client: client}
|
||||||
client.ConfigurationVersions = &configurationVersions{client: client}
|
client.ConfigurationVersions = &configurationVersions{client: client}
|
||||||
client.OAuthClients = &oAuthClients{client: client}
|
client.OAuthClients = &oAuthClients{client: client}
|
||||||
client.OAuthTokens = &oAuthTokens{client: client}
|
client.OAuthTokens = &oAuthTokens{client: client}
|
||||||
|
24
vendor/github.com/hashicorp/go-tfe/variable.go
generated
vendored
24
vendor/github.com/hashicorp/go-tfe/variable.go
generated
vendored
@ -21,6 +21,9 @@ type Variables interface {
|
|||||||
// Create is used to create a new variable.
|
// Create is used to create a new variable.
|
||||||
Create(ctx context.Context, options VariableCreateOptions) (*Variable, error)
|
Create(ctx context.Context, options VariableCreateOptions) (*Variable, error)
|
||||||
|
|
||||||
|
// Read a variable by its ID.
|
||||||
|
Read(ctx context.Context, variableID string) (*Variable, error)
|
||||||
|
|
||||||
// Update values of an existing variable.
|
// Update values of an existing variable.
|
||||||
Update(ctx context.Context, variableID string, options VariableUpdateOptions) (*Variable, error)
|
Update(ctx context.Context, variableID string, options VariableUpdateOptions) (*Variable, error)
|
||||||
|
|
||||||
@ -161,6 +164,27 @@ func (s *variables) Create(ctx context.Context, options VariableCreateOptions) (
|
|||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read a variable by its ID.
|
||||||
|
func (s *variables) Read(ctx context.Context, variableID string) (*Variable, error) {
|
||||||
|
if !validStringID(&variableID) {
|
||||||
|
return nil, errors.New("Invalid value for variable ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := fmt.Sprintf("vars/%s", url.QueryEscape(variableID))
|
||||||
|
req, err := s.client.newRequest("GET", u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v := &Variable{}
|
||||||
|
err = s.client.do(ctx, req, v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
|
||||||
// VariableUpdateOptions represents the options for updating a variable.
|
// VariableUpdateOptions represents the options for updating a variable.
|
||||||
type VariableUpdateOptions struct {
|
type VariableUpdateOptions struct {
|
||||||
// For internal use only!
|
// For internal use only!
|
||||||
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@ -1804,10 +1804,10 @@
|
|||||||
"revisionTime": "2018-07-12T07:51:27Z"
|
"revisionTime": "2018-07-12T07:51:27Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "Xo/jovk4kg+1xHsdyfTtBhcLkXo=",
|
"checksumSHA1": "V2A92CHPEiPIsU4Wepl0ukznka8=",
|
||||||
"path": "github.com/hashicorp/go-tfe",
|
"path": "github.com/hashicorp/go-tfe",
|
||||||
"revision": "6781009f2a64d61df9aff58f17427f0ef43abad0",
|
"revision": "cca0c15746d89219f9732f6c07d267827fef25cd",
|
||||||
"revisionTime": "2018-09-08T08:19:18Z"
|
"revisionTime": "2018-09-20T19:42:22Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "85XUnluYJL7F55ptcwdmN8eSOsk=",
|
"checksumSHA1": "85XUnluYJL7F55ptcwdmN8eSOsk=",
|
||||||
|
Loading…
Reference in New Issue
Block a user