terraform/vendor/github.com/hashicorp/go-tfe/state_version.go

221 lines
5.7 KiB
Go

package tfe
import (
"bytes"
"context"
"errors"
"fmt"
"net/url"
"time"
)
// Compile-time proof of interface implementation.
var _ StateVersions = (*stateVersions)(nil)
// StateVersions describes all the state version related methods that
// the Terraform Enterprise API supports.
//
// TFE API docs:
// https://www.terraform.io/docs/enterprise/api/state-versions.html
type StateVersions interface {
// List all the state versions for a given workspace.
List(ctx context.Context, options StateVersionListOptions) (*StateVersionList, error)
// Create a new state version for the given workspace.
Create(ctx context.Context, workspaceID string, options StateVersionCreateOptions) (*StateVersion, error)
// Read a state version by its ID.
Read(ctx context.Context, svID string) (*StateVersion, error)
// Current reads the latest available state from the given workspace.
Current(ctx context.Context, workspaceID string) (*StateVersion, error)
// Download retrieves the actual stored state of a state version
Download(ctx context.Context, url string) ([]byte, error)
}
// stateVersions implements StateVersions.
type stateVersions struct {
client *Client
}
// StateVersionList represents a list of state versions.
type StateVersionList struct {
*Pagination
Items []*StateVersion
}
// StateVersion represents a Terraform Enterprise state version.
type StateVersion struct {
ID string `jsonapi:"primary,state-versions"`
CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"`
DownloadURL string `jsonapi:"attr,hosted-state-download-url"`
Serial int64 `jsonapi:"attr,serial"`
VCSCommitSHA string `jsonapi:"attr,vcs-commit-sha"`
VCSCommitURL string `jsonapi:"attr,vcs-commit-url"`
// Relations
Run *Run `jsonapi:"relation,run"`
}
// StateVersionListOptions represents the options for listing state versions.
type StateVersionListOptions struct {
ListOptions
Organization *string `url:"filter[organization][name]"`
Workspace *string `url:"filter[workspace][name]"`
}
func (o StateVersionListOptions) valid() error {
if !validString(o.Organization) {
return errors.New("organization is required")
}
if !validString(o.Workspace) {
return errors.New("workspace is required")
}
return nil
}
// List all the state versions for a given workspace.
func (s *stateVersions) List(ctx context.Context, options StateVersionListOptions) (*StateVersionList, error) {
if err := options.valid(); err != nil {
return nil, err
}
req, err := s.client.newRequest("GET", "state-versions", &options)
if err != nil {
return nil, err
}
svl := &StateVersionList{}
err = s.client.do(ctx, req, svl)
if err != nil {
return nil, err
}
return svl, nil
}
// StateVersionCreateOptions represents the options for creating a state version.
type StateVersionCreateOptions struct {
// For internal use only!
ID string `jsonapi:"primary,state-versions"`
// The lineage of the state.
Lineage *string `jsonapi:"attr,lineage,omitempty"`
// The MD5 hash of the state version.
MD5 *string `jsonapi:"attr,md5"`
// The serial of the state.
Serial *int64 `jsonapi:"attr,serial"`
// The base64 encoded state.
State *string `jsonapi:"attr,state"`
// Force can be set to skip certain validations. Wrong use
// of this flag can cause data loss, so USE WITH CAUTION!
Force *bool `jsonapi:"attr,force"`
// Specifies the run to associate the state with.
Run *Run `jsonapi:"relation,run,omitempty"`
}
func (o StateVersionCreateOptions) valid() error {
if !validString(o.MD5) {
return errors.New("MD5 is required")
}
if o.Serial == nil {
return errors.New("serial is required")
}
if !validString(o.State) {
return errors.New("state is required")
}
return nil
}
// Create a new state version for the given workspace.
func (s *stateVersions) Create(ctx context.Context, workspaceID string, options StateVersionCreateOptions) (*StateVersion, error) {
if !validStringID(&workspaceID) {
return nil, errors.New("invalid value for workspace ID")
}
if err := options.valid(); err != nil {
return nil, err
}
// Make sure we don't send a user provided ID.
options.ID = ""
u := fmt.Sprintf("workspaces/%s/state-versions", url.QueryEscape(workspaceID))
req, err := s.client.newRequest("POST", u, &options)
if err != nil {
return nil, err
}
sv := &StateVersion{}
err = s.client.do(ctx, req, sv)
if err != nil {
return nil, err
}
return sv, nil
}
// Read a state version by its ID.
func (s *stateVersions) Read(ctx context.Context, svID string) (*StateVersion, error) {
if !validStringID(&svID) {
return nil, errors.New("invalid value for state version ID")
}
u := fmt.Sprintf("state-versions/%s", url.QueryEscape(svID))
req, err := s.client.newRequest("GET", u, nil)
if err != nil {
return nil, err
}
sv := &StateVersion{}
err = s.client.do(ctx, req, sv)
if err != nil {
return nil, err
}
return sv, nil
}
// Current reads the latest available state from the given workspace.
func (s *stateVersions) Current(ctx context.Context, workspaceID string) (*StateVersion, error) {
if !validStringID(&workspaceID) {
return nil, errors.New("invalid value for workspace ID")
}
u := fmt.Sprintf("workspaces/%s/current-state-version", url.QueryEscape(workspaceID))
req, err := s.client.newRequest("GET", u, nil)
if err != nil {
return nil, err
}
sv := &StateVersion{}
err = s.client.do(ctx, req, sv)
if err != nil {
return nil, err
}
return sv, nil
}
// Download retrieves the actual stored state of a state version
func (s *stateVersions) Download(ctx context.Context, url string) ([]byte, error) {
req, err := s.client.newRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/json")
var buf bytes.Buffer
err = s.client.do(ctx, req, &buf)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}