github.com/leg100/ots@v0.0.7-0.20210919080622-034055ced4bd/state_version.go (about)

     1  package ots
     2  
     3  import (
     4  	"encoding/base64"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/leg100/go-tfe"
     9  	"gorm.io/gorm"
    10  )
    11  
    12  var (
    13  	ErrInvalidStateVersionGetOptions = errors.New("invalid state version get options")
    14  )
    15  
    16  // StateVersion represents a Terraform Enterprise state version.
    17  type StateVersion struct {
    18  	ID string
    19  
    20  	gorm.Model
    21  
    22  	Serial       int64
    23  	VCSCommitSHA string
    24  	VCSCommitURL string
    25  
    26  	// BlobID is ID of the binary object containing the state
    27  	BlobID string
    28  
    29  	// State version belongs to a workspace
    30  	Workspace *Workspace
    31  
    32  	// Run that created this state version. Optional.
    33  	// Run     *Run
    34  
    35  	Outputs []*StateVersionOutput
    36  
    37  	// State version has many outputs
    38  	StateVersionOutputs []StateVersionOutput
    39  }
    40  
    41  // StateVersionList represents a list of state versions.
    42  type StateVersionList struct {
    43  	*tfe.Pagination
    44  	Items []*StateVersion
    45  }
    46  
    47  type StateVersionService interface {
    48  	Create(workspaceID string, opts tfe.StateVersionCreateOptions) (*StateVersion, error)
    49  	Current(workspaceID string) (*StateVersion, error)
    50  	Get(id string) (*StateVersion, error)
    51  	Download(id string) ([]byte, error)
    52  	List(opts tfe.StateVersionListOptions) (*StateVersionList, error)
    53  }
    54  
    55  type StateVersionStore interface {
    56  	Create(sv *StateVersion) (*StateVersion, error)
    57  	Get(opts StateVersionGetOptions) (*StateVersion, error)
    58  	List(opts tfe.StateVersionListOptions) (*StateVersionList, error)
    59  }
    60  
    61  // StateVersionGetOptions are options for retrieving a single StateVersion.
    62  // Either ID *or* WorkspaceID must be specfiied.
    63  type StateVersionGetOptions struct {
    64  	// ID of state version to retrieve
    65  	ID *string
    66  
    67  	// Get current state version belonging to workspace with this ID
    68  	WorkspaceID *string
    69  }
    70  
    71  type StateVersionFactory struct {
    72  	WorkspaceService WorkspaceService
    73  	BlobStore        BlobStore
    74  }
    75  
    76  func (f *StateVersionFactory) NewStateVersion(workspaceID string, opts tfe.StateVersionCreateOptions) (*StateVersion, error) {
    77  	sv := StateVersion{
    78  		Serial: *opts.Serial,
    79  		ID:     GenerateID("sv"),
    80  	}
    81  
    82  	ws, err := f.WorkspaceService.Get(WorkspaceSpecifier{ID: &workspaceID})
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  	sv.Workspace = ws
    87  
    88  	decoded, err := base64.StdEncoding.DecodeString(*opts.State)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	sv.BlobID = NewBlobID()
    94  	if err := f.BlobStore.Put(sv.BlobID, decoded); err != nil {
    95  		return nil, err
    96  	}
    97  
    98  	state, err := Parse(decoded)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	for k, v := range state.Outputs {
   104  		sv.Outputs = append(sv.Outputs, &StateVersionOutput{
   105  			ID:    GenerateID("wsout"),
   106  			Name:  k,
   107  			Type:  v.Type,
   108  			Value: v.Value,
   109  		})
   110  	}
   111  
   112  	return &sv, nil
   113  }
   114  
   115  func (r *StateVersion) DownloadURL() string {
   116  	return fmt.Sprintf("/state-versions/%s/download", r.ID)
   117  }