@ -9,21 +9,45 @@ import (
"io"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
tfe "github.com/hashicorp/go-tfe"
)
type mockClient struct {
ConfigurationVersions * mockConfigurationVersions
Organizations * mockOrganizations
Plans * mockPlans
Runs * mockRuns
StateVersions * mockStateVersions
Workspaces * mockWorkspaces
}
func newMockClient ( ) * mockClient {
c := & mockClient { }
c . ConfigurationVersions = newMockConfigurationVersions ( c )
c . Organizations = newMockOrganizations ( c )
c . Plans = newMockPlans ( c )
c . Runs = newMockRuns ( c )
c . StateVersions = newMockStateVersions ( c )
c . Workspaces = newMockWorkspaces ( c )
return c
}
type mockConfigurationVersions struct {
client * mockClient
configVersions map [ string ] * tfe . ConfigurationVersion
uploadPaths map [ string ] string
uploadURLs map [ string ] * tfe . ConfigurationVersion
workspaces map [ string ] * tfe . ConfigurationVersion
}
func newMockConfigurationVersions ( ) * mockConfigurationVersions {
func newMockConfigurationVersions ( client * mockClient ) * mockConfigurationVersions {
return & mockConfigurationVersions {
client : client ,
configVersions : make ( map [ string ] * tfe . ConfigurationVersion ) ,
uploadPaths : make ( map [ string ] string ) ,
uploadURLs : make ( map [ string ] * tfe . ConfigurationVersion ) ,
workspaces : make ( map [ string ] * tfe . ConfigurationVersion ) ,
}
}
@ -47,7 +71,6 @@ func (m *mockConfigurationVersions) Create(ctx context.Context, workspaceID stri
m . configVersions [ cv . ID ] = cv
m . uploadURLs [ url ] = cv
m . workspaces [ workspaceID ] = cv
return cv , nil
}
@ -65,16 +88,19 @@ func (m *mockConfigurationVersions) Upload(ctx context.Context, url, path string
if ! ok {
return errors . New ( "404 not found" )
}
m . uploadPaths [ cv . ID ] = path
cv . Status = tfe . ConfigurationUploaded
return nil
}
type mockOrganizations struct {
client * mockClient
organizations map [ string ] * tfe . Organization
}
func newMockOrganizations ( ) * mockOrganizations {
func newMockOrganizations ( client * mockClient ) * mockOrganizations {
return & mockOrganizations {
client : client ,
organizations : make ( map [ string ] * tfe . Organization ) ,
}
}
@ -117,32 +143,53 @@ func (m *mockOrganizations) Delete(ctx context.Context, name string) error {
}
type mockPlans struct {
logs map [ string ] string
plans map [ string ] * tfe . Plan
client * mockClient
logs map [ string ] string
plans map [ string ] * tfe . Plan
}
func newMockPlans ( ) * mockPlans {
func newMockPlans ( client * mockClient ) * mockPlans {
return & mockPlans {
logs : make ( map [ string ] string ) ,
plans : make ( map [ string ] * tfe . Plan ) ,
client : client ,
logs : make ( map [ string ] string ) ,
plans : make ( map [ string ] * tfe . Plan ) ,
}
}
func ( m * mockPlans ) Read ( ctx context . Context , planID string ) ( * tfe . Plan , error ) {
p , ok := m . plans [ planID ]
if ! ok {
url := fmt . Sprintf ( "https://app.terraform.io/_archivist/%s" , planID )
// create is a helper function to create a mock plan that uses the configured
// working directory to find the logfile. This enables us to test if we are
// using the
func ( m * mockPlans ) create ( cvID , workspaceID string ) ( * tfe . Plan , error ) {
id := generateID ( "plan-" )
url := fmt . Sprintf ( "https://app.terraform.io/_archivist/%s" , id )
p = & tfe . Plan {
ID : planID ,
LogReadURL : url ,
Status : tfe . Plan Finished ,
}
p : = & tfe . Plan {
ID : id ,
LogReadURL : url ,
Status : tfe . Plan Pending ,
}
m . logs [ url ] = "plan/output.log"
m . plans [ p . ID ] = p
w , ok := m . client . Workspaces . workspaceIDs [ workspaceID ]
if ! ok {
return nil , tfe . ErrResourceNotFound
}
m . logs [ url ] = filepath . Join (
m . client . ConfigurationVersions . uploadPaths [ cvID ] ,
w . WorkingDirectory ,
"output.log" ,
)
m . plans [ p . ID ] = p
return p , nil
}
func ( m * mockPlans ) Read ( ctx context . Context , planID string ) ( * tfe . Plan , error ) {
p , ok := m . plans [ planID ]
if ! ok {
return nil , tfe . ErrResourceNotFound
}
p . Status = tfe . PlanFinished
return p , nil
}
@ -157,7 +204,11 @@ func (m *mockPlans) Logs(ctx context.Context, planID string) (io.Reader, error)
return nil , tfe . ErrResourceNotFound
}
logs , err := ioutil . ReadFile ( "./test-fixtures/" + logfile )
if _ , err := os . Stat ( logfile ) ; os . IsNotExist ( err ) {
return bytes . NewBufferString ( "logfile does not exist" ) , nil
}
logs , err := ioutil . ReadFile ( logfile )
if err != nil {
return nil , err
}
@ -166,34 +217,39 @@ func (m *mockPlans) Logs(ctx context.Context, planID string) (io.Reader, error)
}
type mockRuns struct {
client * mockClient
runs map [ string ] * tfe . Run
workspaces map [ string ] [ ] * tfe . Run
}
func newMockRuns ( ) * mockRuns {
func newMockRuns ( client * mockClient ) * mockRuns {
return & mockRuns {
client : client ,
runs : make ( map [ string ] * tfe . Run ) ,
workspaces : make ( map [ string ] [ ] * tfe . Run ) ,
}
}
func ( m * mockRuns ) List ( ctx context . Context , workspaceID string , options tfe . RunListOptions ) ( [ ] * tfe . Run , error ) {
w , ok := m . client . Workspaces . workspaceIDs [ workspaceID ]
if ! ok {
return nil , tfe . ErrResourceNotFound
}
var rs [ ] * tfe . Run
for _ , r := range m . workspaces [ workspaceID ] {
for _ , r := range m . workspaces [ w . ID] {
rs = append ( rs , r )
}
return rs , nil
}
func ( m * mockRuns ) Create ( ctx context . Context , options tfe . RunCreateOptions ) ( * tfe . Run , error ) {
id := generateID ( "run-" )
p := & tfe . Plan {
ID : generateID ( "plan-" ) ,
Status : tfe . PlanPending ,
p , err := m . client . Plans . create ( options . ConfigurationVersion . ID , options . Workspace . ID )
if err != nil {
return nil , err
}
r := & tfe . Run {
ID : id ,
ID : generateID ( "run-" ) ,
Plan : p ,
Status : tfe . RunPending ,
}
@ -225,13 +281,15 @@ func (m *mockRuns) Discard(ctx context.Context, runID string, options tfe.RunDis
}
type mockStateVersions struct {
client * mockClient
states map [ string ] [ ] byte
stateVersions map [ string ] * tfe . StateVersion
workspaces map [ string ] [ ] string
}
func newMockStateVersions ( ) * mockStateVersions {
func newMockStateVersions ( client * mockClient ) * mockStateVersions {
return & mockStateVersions {
client : client ,
states : make ( map [ string ] [ ] byte ) ,
stateVersions : make ( map [ string ] * tfe . StateVersion ) ,
workspaces : make ( map [ string ] [ ] string ) ,
@ -277,14 +335,21 @@ func (m *mockStateVersions) Read(ctx context.Context, svID string) (*tfe.StateVe
}
func ( m * mockStateVersions ) Current ( ctx context . Context , workspaceID string ) ( * tfe . StateVersion , error ) {
svs , ok := m . workspaces [ workspaceID ]
w , ok := m . client . Workspaces . workspaceIDs [ workspaceID ]
if ! ok {
return nil , tfe . ErrResourceNotFound
}
svs , ok := m . workspaces [ w . ID ]
if ! ok || len ( svs ) == 0 {
return nil , tfe . ErrResourceNotFound
}
sv , ok := m . stateVersions [ svs [ len ( svs ) - 1 ] ]
if ! ok {
return nil , tfe . ErrResourceNotFound
}
return sv , nil
}
@ -297,12 +362,14 @@ func (m *mockStateVersions) Download(ctx context.Context, url string) ([]byte, e
}
type mockWorkspaces struct {
client * mockClient
workspaceIDs map [ string ] * tfe . Workspace
workspaceNames map [ string ] * tfe . Workspace
}
func newMockWorkspaces ( ) * mockWorkspaces {
func newMockWorkspaces ( client * mockClient ) * mockWorkspaces {
return & mockWorkspaces {
client : client ,
workspaceIDs : make ( map [ string ] * tfe . Workspace ) ,
workspaceNames : make ( map [ string ] * tfe . Workspace ) ,
}
@ -317,9 +384,8 @@ func (m *mockWorkspaces) List(ctx context.Context, organization string, options
}
func ( m * mockWorkspaces ) Create ( ctx context . Context , organization string , options tfe . WorkspaceCreateOptions ) ( * tfe . Workspace , error ) {
id := generateID ( "ws-" )
w := & tfe . Workspace {
ID : id ,
ID : generateID ( "ws-" ) ,
Name : * options . Name ,
}
m . workspaceIDs [ w . ID ] = w
@ -340,8 +406,16 @@ func (m *mockWorkspaces) Update(ctx context.Context, organization, workspace str
if ! ok {
return nil , tfe . ErrResourceNotFound
}
w . Name = * options . Name
w . TerraformVersion = * options . TerraformVersion
if options . Name != nil {
w . Name = * options . Name
}
if options . TerraformVersion != nil {
w . TerraformVersion = * options . TerraformVersion
}
if options . WorkingDirectory != nil {
w . WorkingDirectory = * options . WorkingDirectory
}
delete ( m . workspaceNames , workspace )
m . workspaceNames [ w . Name ] = w