diff --git a/variable.go b/variable.go index e249fcb..df6549b 100644 --- a/variable.go +++ b/variable.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/url" + "time" "github.com/google/go-querystring/query" ) @@ -53,19 +54,22 @@ type VariableList struct { // Variable represents a Scalr variable. type Variable struct { - ID string `jsonapi:"primary,vars"` - Key string `jsonapi:"attr,key"` - Value string `jsonapi:"attr,value"` - Category CategoryType `jsonapi:"attr,category"` - Description string `jsonapi:"attr,description"` - HCL bool `jsonapi:"attr,hcl"` - Sensitive bool `jsonapi:"attr,sensitive"` - Final bool `jsonapi:"attr,final"` + ID string `jsonapi:"primary,vars"` + Key string `jsonapi:"attr,key"` + Value string `jsonapi:"attr,value"` + Category CategoryType `jsonapi:"attr,category"` + Description string `jsonapi:"attr,description"` + HCL bool `jsonapi:"attr,hcl"` + Sensitive bool `jsonapi:"attr,sensitive"` + Final bool `jsonapi:"attr,final"` + UpdatedByEmail string `jsonapi:"attr,updated-by-email"` + UpdatedAt time.Time `jsonapi:"attr,updated-at,iso8601"` // Relations Workspace *Workspace `jsonapi:"relation,workspace"` Environment *Environment `jsonapi:"relation,environment"` Account *Account `jsonapi:"relation,account"` + UpdatedBy *User `jsonapi:"relation,updated-by"` } // VariableListOptions represents the options for listing variables. @@ -116,6 +120,9 @@ func (s *variables) List(ctx context.Context, options VariableListOptions) (*Var type VariableWriteQueryOptions struct { Force *bool `url:"force,omitempty"` + + // The comma-separated list of relationship paths. + Include *string `url:"include,omitempty"` } // VariableCreateOptions represents the options for creating a new variable. @@ -205,7 +212,14 @@ func (s *variables) Read(ctx context.Context, variableID string) (*Variable, err } u := fmt.Sprintf("vars/%s", url.QueryEscape(variableID)) - req, err := s.client.newRequest("GET", u, nil) + + options := struct { + Include string `url:"include"` + }{ + Include: "updated-by", + } + + req, err := s.client.newRequest("GET", u, &options) if err != nil { return nil, err } diff --git a/variable_test.go b/variable_test.go index 1c20ad3..38d7d25 100644 --- a/variable_test.go +++ b/variable_test.go @@ -36,6 +36,38 @@ func TestVariablesCreate(t *testing.T) { assert.Equal(t, *options.Value, v.Value) assert.Equal(t, *options.Category, v.Category) assert.Equal(t, *options.Description, v.Description) + assert.NotEmpty(t, v.UpdatedByEmail) + assert.NotEmpty(t, v.UpdatedAt) + assert.NotEmpty(t, v.UpdatedBy) + assert.NotEmpty(t, v.UpdatedBy.ID) + assert.Empty(t, v.UpdatedBy.Email) + }) + + t.Run("with included updated-by", func(t *testing.T) { + options := VariableCreateOptions{ + Key: String(randomVariableKey(t)), + Value: String(""), + Category: Category(CategoryShell), + Description: String("random variable test"), + Workspace: wsTest, + QueryOptions: &VariableWriteQueryOptions{ + Include: String("updated-by"), + }, + } + + v, err := client.Variables.Create(ctx, options) + require.NoError(t, err) + + assert.NotEmpty(t, v.ID) + assert.Equal(t, *options.Key, v.Key) + assert.Equal(t, *options.Value, v.Value) + assert.Equal(t, *options.Category, v.Category) + assert.Equal(t, *options.Description, v.Description) + assert.NotEmpty(t, v.UpdatedByEmail) + assert.NotEmpty(t, v.UpdatedAt) + assert.NotEmpty(t, v.UpdatedBy) + assert.NotEmpty(t, v.UpdatedBy.ID) + assert.Equal(t, v.UpdatedBy.Email, v.UpdatedByEmail) }) t.Run("when options is missing value", func(t *testing.T) { @@ -164,6 +196,11 @@ func TestVariablesRead(t *testing.T) { assert.Equal(t, vTest.Key, v.Key) assert.Equal(t, vTest.Sensitive, v.Sensitive) assert.Equal(t, vTest.Value, v.Value) + assert.NotEmpty(t, v.UpdatedAt) + assert.NotEmpty(t, v.UpdatedByEmail) + assert.NotEmpty(t, v.UpdatedBy) + assert.NotEmpty(t, v.UpdatedBy.Email) + assert.Equal(t, v.UpdatedByEmail, v.UpdatedBy.Email) }) t.Run("when the variable does not exist", func(t *testing.T) { @@ -205,9 +242,39 @@ func TestVariablesUpdate(t *testing.T) { require.NoError(t, err) assert.Equal(t, *options.Key, v.Key) - assert.Equal(t, *options.HCL, v.HCL) + assert.Equal(t, false, v.HCL) assert.Equal(t, *options.Value, v.Value) assert.Equal(t, *options.Description, v.Description) + assert.NotEmpty(t, v.UpdatedByEmail) + assert.NotEmpty(t, v.UpdatedAt) + assert.NotEmpty(t, v.UpdatedBy) + assert.NotEmpty(t, v.UpdatedBy.ID) + assert.Empty(t, v.UpdatedBy.Email) + }) + + t.Run("with valid options and included updated-by", func(t *testing.T) { + options := VariableUpdateOptions{ + Key: String("newname"), + Value: String("newvalue"), + Description: String("newdescription"), + HCL: Bool(true), + QueryOptions: &VariableWriteQueryOptions{ + Include: String("updated-by"), + }, + } + + v, err := client.Variables.Update(ctx, vTest.ID, options) + require.NoError(t, err) + + assert.Equal(t, *options.Key, v.Key) + assert.Equal(t, false, v.HCL) + assert.Equal(t, *options.Value, v.Value) + assert.Equal(t, *options.Description, v.Description) + assert.NotEmpty(t, v.UpdatedByEmail) + assert.NotEmpty(t, v.UpdatedAt) + assert.NotEmpty(t, v.UpdatedBy) + assert.NotEmpty(t, v.UpdatedBy.ID) + assert.Equal(t, v.UpdatedBy.Email, v.UpdatedByEmail) }) t.Run("when updating a subset of values", func(t *testing.T) { @@ -242,6 +309,7 @@ func TestVariablesUpdate(t *testing.T) { updated, err := client.Variables.Update(ctx, created.ID, VariableUpdateOptions{}) require.NoError(t, err) + updated.UpdatedAt = created.UpdatedAt assert.Equal(t, created, updated) }) @@ -344,6 +412,38 @@ func TestVariablesList(t *testing.T) { assert.ElementsMatch(t, expectedIds, responseIds) }) + t.Run("with included updated-by", func(t *testing.T) { + variables, err := client.Variables.List(ctx, VariableListOptions{}) + if err != nil { + log.Fatalf("Cant remove default variables before test: %v", err) + return + } + for _, variable := range variables.Items { + err = client.Variables.Delete(ctx, variable.ID) + if err != nil { + log.Fatalf("Cant remove default variables before test: %v", err) + return + } + } + + _, deleteVar := createVariable(t, client, nil, nil, &Account{ID: defaultAccountID}) + defer deleteVar() + + responseVariables, err := client.Variables.List( + ctx, VariableListOptions{ + Include: String("updated-by"), + }) + require.NoError(t, err) + + for _, variable := range responseVariables.Items { + assert.NotEmpty(t, variable.UpdatedByEmail) + assert.NotEmpty(t, variable.UpdatedAt) + assert.NotEmpty(t, variable.UpdatedBy) + assert.NotEmpty(t, variable.UpdatedBy.ID) + assert.Equal(t, variable.UpdatedBy.Email, variable.UpdatedByEmail) + } + }) + t.Run("category", func(t *testing.T) { workspace, deleteWorkspace := createWorkspace(t, client, nil) defer deleteWorkspace()