diff --git a/go.mod b/go.mod index f1ff2f787..d01cd7148 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.5.2 github.com/hashicorp/go-slug v0.4.1 github.com/hashicorp/go-uuid v1.0.1 - github.com/hashicorp/jsonapi v0.0.0-20210326175023-166ae20eb0d1 + github.com/hashicorp/jsonapi v0.0.0-20210420151930-edf82c9774bf github.com/stretchr/testify v1.3.0 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 ) diff --git a/go.sum b/go.sum index e81662ebe..7e65118e4 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/hashicorp/go-slug v0.4.1 h1:/jAo8dNuLgSImoLXaX7Od7QB4TfYCVPam+OpAt5bZ github.com/hashicorp/go-slug v0.4.1/go.mod h1:I5tq5Lv0E2xcNXNkmx7BSfzi1PsJ2cNjs3cC3LwyhK8= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/jsonapi v0.0.0-20210326175023-166ae20eb0d1 h1:V95qyPxj4IE39U+fyXdQXUWFCwqXUfTbIl/Gb+lb3zc= -github.com/hashicorp/jsonapi v0.0.0-20210326175023-166ae20eb0d1/go.mod h1:Yog5+CPEM3c99L1CL2CFCYoSzgWm5vTU58idbRUaLik= +github.com/hashicorp/jsonapi v0.0.0-20210420151930-edf82c9774bf h1:EsVVE/vPelkJ83dk/Y3CeMbH/yPR2S8bLzMtxUoMFGI= +github.com/hashicorp/jsonapi v0.0.0-20210420151930-edf82c9774bf/go.mod h1:Yog5+CPEM3c99L1CL2CFCYoSzgWm5vTU58idbRUaLik= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/notification_configuration.go b/notification_configuration.go index 09f6e0810..dfc59cc87 100644 --- a/notification_configuration.go +++ b/notification_configuration.go @@ -73,7 +73,7 @@ type NotificationConfigurationList struct { type NotificationConfiguration struct { ID string `jsonapi:"primary,notification-configurations"` CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"` - DeliveryResponses []DeliveryResponse `jsonapi:"attr,delivery-responses"` + DeliveryResponses []*DeliveryResponse `jsonapi:"attr,delivery-responses"` DestinationType NotificationDestinationType `jsonapi:"attr,destination-type"` Enabled bool `jsonapi:"attr,enabled"` Name string `jsonapi:"attr,name"` diff --git a/notification_configuration_test.go b/notification_configuration_test.go index c5dc810ea..9e55423b0 100644 --- a/notification_configuration_test.go +++ b/notification_configuration_test.go @@ -1,11 +1,8 @@ package tfe import ( - "bytes" "context" - "encoding/json" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -319,59 +316,3 @@ func TestNotificationConfigurationVerify(t *testing.T) { assert.EqualError(t, err, "invalid value for notification configuration ID") }) } - -func TestNotificationConfiguration_Unmarshal(t *testing.T) { - headers := map[string][]string{ - "cache-control": {"private"}, - "content-length": {"129"}, - } - data := map[string]interface{}{ - "data": map[string]interface{}{ - "type": "notification-configurations", - "id": "nc-ntv3HbhJqvFzamy7", - "attributes": map[string]interface{}{ - "created-at": "2018-03-02T23:42:06.651Z", - "delivery-responses": []interface{}{ - map[string]interface{}{ - "body": "html", - "code": "200", - "headers": headers, - "sent-at": "2021-03-23T17:13:52+00:00", - "successful": "true", - "url": "hashicorp.com", - }, - }, - "destination-type": NotificationDestinationTypeEmail, - "enabled": true, - "name": "general", - "token": "secret", - "triggers": []string{"run:applying", "run:completed"}, - "url": "hashicorp.com", - "email-addresses": []string{"test@hashicorp.com"}, - }, - }, - } - byteData, err := json.Marshal(data) - require.NoError(t, err) - - responseBody := bytes.NewReader(byteData) - nc := &NotificationConfiguration{} - err = unmarshalResponse(responseBody, nc) - require.NoError(t, err) - - iso8601TimeFormat := "2006-01-02T15:04:05Z" - parsedTime, err := time.Parse(iso8601TimeFormat, "2018-03-02T23:42:06.651Z") - require.NoError(t, err) - sentAtTime, err := time.Parse(time.RFC3339, "2021-03-23T17:13:52+00:00") - require.NoError(t, err) - - assert.Equal(t, nc.ID, "nc-ntv3HbhJqvFzamy7") - assert.Equal(t, nc.CreatedAt, parsedTime) - assert.Equal(t, len(nc.DeliveryResponses), 1) - assert.Equal(t, "html", nc.DeliveryResponses[0].Body) - assert.Equal(t, "200", nc.DeliveryResponses[0].Code) - assert.Equal(t, "true", nc.DeliveryResponses[0].Successful) - assert.Equal(t, sentAtTime, nc.DeliveryResponses[0].SentAt) - assert.Equal(t, []string{"129"}, nc.DeliveryResponses[0].Headers["content-length"]) - assert.Equal(t, []string{"private"}, nc.DeliveryResponses[0].Headers["cache-control"]) -} diff --git a/policy.go b/policy.go index bf4c2ea8f..c038ef38f 100644 --- a/policy.go +++ b/policy.go @@ -62,12 +62,12 @@ type PolicyList struct { // Policy represents a Terraform Enterprise policy. type Policy struct { - ID string `jsonapi:"primary,policies"` - Name string `jsonapi:"attr,name"` - Description string `jsonapi:"attr,description"` - Enforce []Enforcement `jsonapi:"attr,enforce"` - PolicySetCount int `jsonapi:"attr,policy-set-count"` - UpdatedAt time.Time `jsonapi:"attr,updated-at,iso8601"` + ID string `jsonapi:"primary,policies"` + Name string `jsonapi:"attr,name"` + Description string `jsonapi:"attr,description"` + Enforce []*Enforcement `jsonapi:"attr,enforce"` + PolicySetCount int `jsonapi:"attr,policy-set-count"` + UpdatedAt time.Time `jsonapi:"attr,updated-at,iso8601"` // Relations Organization *Organization `jsonapi:"relation,organization"` @@ -128,8 +128,8 @@ type PolicyCreateOptions struct { // EnforcementOptions represents the enforcement options of a policy. type EnforcementOptions struct { - Path *string `jsonapi:"attr,path,omitempty"` - Mode *EnforcementLevel `jsonapi:"attr,mode"` + Path *string `json:"path,omitempty"` + Mode *EnforcementLevel `json:"mode"` } func (o PolicyCreateOptions) valid() error { diff --git a/policy_test.go b/policy_test.go index 66341ccfd..53b74f17e 100644 --- a/policy_test.go +++ b/policy_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + retryablehttp "github.com/hashicorp/go-retryablehttp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -218,6 +219,8 @@ func TestPoliciesRead(t *testing.T) { assert.Equal(t, pTest.Description, p.Description) assert.Equal(t, pTest.PolicySetCount, p.PolicySetCount) assert.NotEmpty(t, p.Enforce) + assert.NotEmpty(t, p.Enforce[0].Path) + assert.NotEmpty(t, p.Enforce[0].Mode) assert.Equal(t, pTest.Organization.Name, p.Organization.Name) }) @@ -275,6 +278,8 @@ func TestPoliciesUpdate(t *testing.T) { defer pBeforeCleanup() require.Equal(t, 1, len(pBefore.Enforce)) + pathBefore := pBefore.Enforce[0].Path + modeBefore := pBefore.Enforce[0].Mode pAfter, err := client.Policies.Update(ctx, pBefore.ID, PolicyUpdateOptions{ Enforce: []*EnforcementOptions{ @@ -286,7 +291,10 @@ func TestPoliciesUpdate(t *testing.T) { }) require.NoError(t, err) + require.Equal(t, 1, len(pAfter.Enforce)) assert.Equal(t, pBefore, pAfter) + assert.Equal(t, pathBefore, pAfter.Enforce[0].Path) + assert.Equal(t, modeBefore, pAfter.Enforce[0].Mode) }) t.Run("with a new description", func(t *testing.T) { @@ -438,3 +446,58 @@ func TestPolicy_Unmarshal(t *testing.T) { assert.Equal(t, policy.Enforce[0].Mode, EnforcementAdvisory) assert.Equal(t, policy.UpdatedAt, parsedTime) } + +func TestPolicyCreateOptions_Marshal(t *testing.T) { + opts := PolicyCreateOptions{ + Name: String("my-policy"), + Description: String("details"), + Enforce: []*EnforcementOptions{ + { + Path: String("/foo"), + Mode: EnforcementMode(EnforcementSoft), + }, + { + Path: String("/bar"), + Mode: EnforcementMode(EnforcementSoft), + }, + }, + } + + reqBody, err := serializeRequestBody(&opts) + require.NoError(t, err) + req, err := retryablehttp.NewRequest("POST", "url", reqBody) + require.NoError(t, err) + bodyBytes, err := req.BodyBytes() + require.NoError(t, err) + + expectedBody := `{"data":{"type":"policies","attributes":{"description":"details","enforce":[{"path":"/foo","mode":"soft-mandatory"},{"path":"/bar","mode":"soft-mandatory"}],"name":"my-policy"}}} +` + assert.Equal(t, expectedBody, string(bodyBytes)) +} + +func TestPolicyUpdateOptions_Marshal(t *testing.T) { + opts := PolicyUpdateOptions{ + Description: String("details"), + Enforce: []*EnforcementOptions{ + { + Path: String("/foo"), + Mode: EnforcementMode(EnforcementSoft), + }, + { + Path: String("/bar"), + Mode: EnforcementMode(EnforcementSoft), + }, + }, + } + + reqBody, err := serializeRequestBody(&opts) + require.NoError(t, err) + req, err := retryablehttp.NewRequest("POST", "url", reqBody) + require.NoError(t, err) + bodyBytes, err := req.BodyBytes() + require.NoError(t, err) + + expectedBody := `{"data":{"type":"policies","attributes":{"description":"details","enforce":[{"path":"/foo","mode":"soft-mandatory"},{"path":"/bar","mode":"soft-mandatory"}]}}} +` + assert.Equal(t, expectedBody, string(bodyBytes)) +}