Skip to content

Commit

Permalink
Add new workspace fields (#192)
Browse files Browse the repository at this point in the history
* Add new workspace fields

* nil check

* check for nil readme

* additional test cases

* expect an error here
  • Loading branch information
mwhooker authored Mar 23, 2021
1 parent 1de9e44 commit 074a0e4
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
56 changes: 56 additions & 0 deletions workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"context"
"errors"
"fmt"
"io"
"net/url"
"strings"
"time"
)

Expand All @@ -25,6 +27,9 @@ type Workspaces interface {
// Read a workspace by its name.
Read(ctx context.Context, organization string, workspace string) (*Workspace, error)

// Readme gets the readme of a workspace by its ID.
Readme(ctx context.Context, workspaceID string) (io.Reader, error)

// ReadByID reads a workspace by its ID.
ReadByID(ctx context.Context, workspaceID string) (*Workspace, error)

Expand Down Expand Up @@ -97,6 +102,13 @@ type Workspace struct {
TriggerPrefixes []string `jsonapi:"attr,trigger-prefixes"`
VCSRepo *VCSRepo `jsonapi:"attr,vcs-repo"`
WorkingDirectory string `jsonapi:"attr,working-directory"`
UpdatedAt time.Time `jsonapi:"attr,updated-at,iso8601"`
ResourceCount int `jsonapi:"attr,resource-count"`
ApplyDurationAverage time.Duration `jsonapi:"attr,apply-duration-average"`
PlanDurationAverage time.Duration `jsonapi:"attr,plan-duration-average"`
PolicyCheckFailures int `jsonapi:"attr,policy-check-failures"`
RunFailures int `jsonapi:"attr,run-failures"`
RunsCount int `jsonapi:"attr,workspace-kpis-runs-count"`

// Relations
AgentPool *AgentPool `jsonapi:"relation,agent-pool"`
Expand All @@ -105,6 +117,18 @@ type Workspace struct {
SSHKey *SSHKey `jsonapi:"relation,ssh-key"`
}

// workspaceWithReadme is the same as a workspace but it has a readme.
type workspaceWithReadme struct {
ID string `jsonapi:"primary,workspaces"`
Readme *workspaceReadme `jsonapi:"relation,readme"`
}

// workspaceReadme contains the readme of the workspace.
type workspaceReadme struct {
ID string `jsonapi:"primary,workspace-readme"`
RawMarkdown string `jsonapi:"attr,raw-markdown"`
}

// VCSRepo contains the configuration of a VCS integration.
type VCSRepo struct {
Branch string `json:"branch"`
Expand Down Expand Up @@ -322,6 +346,10 @@ func (s *workspaces) Read(ctx context.Context, organization, workspace string) (
return nil, err
}

// durations come over in ms
w.ApplyDurationAverage *= time.Millisecond
w.PlanDurationAverage *= time.Millisecond

return w, nil
}

Expand All @@ -343,9 +371,37 @@ func (s *workspaces) ReadByID(ctx context.Context, workspaceID string) (*Workspa
return nil, err
}

// durations come over in ms
w.ApplyDurationAverage *= time.Millisecond
w.PlanDurationAverage *= time.Millisecond

return w, nil
}

// Readme gets the readme of a workspace by its ID.
func (s *workspaces) Readme(ctx context.Context, workspaceID string) (io.Reader, error) {
if !validStringID(&workspaceID) {
return nil, ErrInvalidWorkspaceID
}

u := fmt.Sprintf("workspaces/%s?include=readme", url.QueryEscape(workspaceID))
req, err := s.client.newRequest("GET", u, nil)
if err != nil {
return nil, err
}

r := &workspaceWithReadme{}
err = s.client.do(ctx, req, r)
if err != nil {
return nil, err
}
if r.Readme == nil {
return nil, nil
}

return strings.NewReader(r.Readme.RawMarkdown), nil
}

// WorkspaceUpdateOptions represents the options for updating a workspace.
type WorkspaceUpdateOptions struct {
// Type is a public field utilized by JSON:API to
Expand Down
61 changes: 61 additions & 0 deletions workspace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package tfe

import (
"context"
"io/ioutil"
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -256,6 +258,65 @@ func TestWorkspacesRead(t *testing.T) {
})
}

func TestWorkspacesReadWithHistory(t *testing.T) {
client := testClient(t)

orgTest, orgTestCleanup := createOrganization(t, client)
defer orgTestCleanup()

wTest, wTestCleanup := createWorkspace(t, client, orgTest)
defer wTestCleanup()

_, rCleanup := createAppliedRun(t, client, wTest)
defer rCleanup()

w, err := client.Workspaces.Read(context.Background(), orgTest.Name, wTest.Name)
require.NoError(t, err)

assert.Equal(t, 1, w.RunsCount)
assert.Equal(t, 1, w.ResourceCount)
}

func TestWorkspacesReadReadme(t *testing.T) {
client := testClient(t)
ctx := context.Background()

orgTest, orgTestCleanup := createOrganization(t, client)
defer orgTestCleanup()

wTest, wTestCleanup := createWorkspaceWithVCS(t, client, orgTest)
defer wTestCleanup()

_, rCleanup := createAppliedRun(t, client, wTest)
defer rCleanup()

t.Run("when the readme exists", func(t *testing.T) {
w, err := client.Workspaces.Readme(ctx, wTest.ID)
require.NoError(t, err)
require.NotNil(t, w)

readme, err := ioutil.ReadAll(w)
require.NoError(t, err)
require.True(
t,
strings.HasPrefix(string(readme), `This is a simple test`),
"got: %s", readme,
)
})

t.Run("when the readme does not exist", func(t *testing.T) {
w, err := client.Workspaces.Readme(ctx, "nonexisting")
assert.Nil(t, w)
assert.Error(t, err)
})

t.Run("without a valid workspace ID", func(t *testing.T) {
w, err := client.Workspaces.Readme(ctx, badIdentifier)
assert.Nil(t, w)
assert.EqualError(t, err, ErrInvalidWorkspaceID.Error())
})
}

func TestWorkspacesReadByID(t *testing.T) {
client := testClient(t)
ctx := context.Background()
Expand Down

0 comments on commit 074a0e4

Please sign in to comment.