Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new states and endpoint for configuration version archiving #338

Merged
merged 4 commits into from Mar 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 26 additions & 0 deletions configuration_version.go
Expand Up @@ -39,6 +39,10 @@ type ConfigurationVersions interface {
// the upload URL from a configuration version and the full path to the
// configuration files on disk.
Upload(ctx context.Context, url string, path string) error

// Archive a configuration version. This can only be done on configuration versions that
// were created with the API or CLI, are in an uploaded state, and have no runs in progress.
Archive(ctx context.Context, cvID string) error
}

// configurationVersions implements ConfigurationVersions.
Expand All @@ -51,7 +55,9 @@ type ConfigurationStatus string

// List all available configuration version statuses.
const (
ConfigurationArchived ConfigurationStatus = "archived"
ConfigurationErrored ConfigurationStatus = "errored"
ConfigurationFetching ConfigurationStatus = "fetching"
ConfigurationPending ConfigurationStatus = "pending"
ConfigurationUploaded ConfigurationStatus = "uploaded"
)
Expand Down Expand Up @@ -95,6 +101,8 @@ type ConfigurationVersion struct {
// CVStatusTimestamps holds the timestamps for individual configuration version
// statuses.
type CVStatusTimestamps struct {
ArchivedAt time.Time `jsonapi:"attr,archived-at,rfc3339"`
FetchingAt time.Time `jsonapi:"attr,fetching-at,rfc3339"`
FinishedAt time.Time `jsonapi:"attr,finished-at,rfc3339"`
QueuedAt time.Time `jsonapi:"attr,queued-at,rfc3339"`
StartedAt time.Time `jsonapi:"attr,started-at,rfc3339"`
Expand Down Expand Up @@ -274,6 +282,24 @@ func (s *configurationVersions) Upload(ctx context.Context, u, path string) erro
return s.client.do(ctx, req, nil)
}

// Archive a configuration version. This can only be done on configuration versions that
// were created with the API or CLI, are in an uploaded state, and have no runs in progress.
func (s *configurationVersions) Archive(ctx context.Context, cvID string) error {
if !validStringID(&cvID) {
return ErrInvalidConfigVersionID
}

body := bytes.NewBuffer(nil)

u := fmt.Sprintf("configuration-versions/%s/actions/archive", url.QueryEscape(cvID))
req, err := s.client.newRequest("POST", u, body)
if err != nil {
return err
}

return s.client.do(ctx, req, nil)
}

func (o *ConfigurationVersionReadOptions) valid() error {
if o == nil {
return nil // nothing to validate
Expand Down
64 changes: 64 additions & 0 deletions configuration_version_integration_test.go
Expand Up @@ -237,6 +237,70 @@ func TestConfigurationVersionsUpload(t *testing.T) {
})
}

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

cv, cvCleanup := createConfigurationVersion(t, client, nil)
defer cvCleanup()

t.Run("when the configuration version exists and has been uploaded", func(t *testing.T) {
err := client.ConfigurationVersions.Upload(
ctx,
cv.UploadURL,
"test-fixtures/config-version",
)
require.NoError(t, err)

// We do this is a small loop, because it can take a second
// before the upload is finished.
for i := 0; ; i++ {
refreshed, err := client.ConfigurationVersions.Read(ctx, cv.ID)
require.NoError(t, err)

if refreshed.Status == ConfigurationUploaded {
break
}

if i > 10 {
t.Fatal("Timeout waiting for the configuration version to be uploaded")
}

time.Sleep(1 * time.Second)
}

err = client.ConfigurationVersions.Archive(ctx, cv.ID)
require.NoError(t, err)

// We do this is a small loop, because it can take a second
// before the archive is finished.
for i := 0; ; i++ {
refreshed, err := client.ConfigurationVersions.Read(ctx, cv.ID)
require.NoError(t, err)

if refreshed.Status == ConfigurationArchived {
break
}

if i > 10 {
t.Fatal("Timeout waiting for the configuration version to be archived")
}

time.Sleep(1 * time.Second)
}
})

t.Run("when the configuration version does not exist", func(t *testing.T) {
err := client.ConfigurationVersions.Archive(ctx, "nonexisting")
assert.Equal(t, err, ErrResourceNotFound)
})

t.Run("with invalid configuration version id", func(t *testing.T) {
err := client.ConfigurationVersions.Archive(ctx, badIdentifier)
assert.EqualError(t, err, ErrInvalidConfigVersionID.Error())
})
}

func TestConfigurationVersions_Unmarshal(t *testing.T) {
data := map[string]interface{}{
"data": map[string]interface{}{
Expand Down
14 changes: 14 additions & 0 deletions mocks/configuration_version_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions run.go
Expand Up @@ -59,6 +59,7 @@ const (
RunCostEstimating RunStatus = "cost_estimating"
RunDiscarded RunStatus = "discarded"
RunErrored RunStatus = "errored"
RunFetching RunStatus = "fetching"
RunPending RunStatus = "pending"
RunPlanQueued RunStatus = "plan_queued"
RunPlanned RunStatus = "planned"
Expand Down Expand Up @@ -148,6 +149,8 @@ type RunStatusTimestamps struct {
CostEstimatingAt time.Time `jsonapi:"attr,cost-estimating-at,rfc3339"`
DiscardedAt time.Time `jsonapi:"attr,discarded-at,rfc3339"`
ErroredAt time.Time `jsonapi:"attr,errored-at,rfc3339"`
FetchedAt time.Time `jsonapi:"attr,fetched-at,rfc3339"`
FetchingAt time.Time `jsonapi:"attr,fetching-at,rfc3339"`
ForceCanceledAt time.Time `jsonapi:"attr,force-canceled-at,rfc3339"`
PlanQueueableAt time.Time `jsonapi:"attr,plan-queueable-at,rfc3339"`
PlanQueuedAt time.Time `jsonapi:"attr,plan-queued-at,rfc3339"`
Expand Down