diff --git a/CHANGELOG.md b/CHANGELOG.md index e66ef36..f780620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,13 @@ NOTES: * Deprecated attributes `remote_agents` and `emails` of `runscope_environment`. Use `remote_agent` and `email` instead. +* Deprecated attribute `variables`, `assertions` and `headers` of `runscope_step`. + Use `variable` instead. ENHANCEMENTS: * Added attributes `remote_agent` and `email` of `runscope_environment`. +* Added attribute `variable`, `assertion` and `header` of `runscope_step`. ## 0.7.0 (March 27, 2021) diff --git a/runscope/resource_runscope_step.go b/runscope/resource_runscope_step.go index c65ccc6..3d31c5c 100644 --- a/runscope/resource_runscope_step.go +++ b/runscope/resource_runscope_step.go @@ -117,7 +117,30 @@ func resourceRunscopeStep() *schema.Resource { }, }, }, - Optional: true, + Optional: true, + ConflictsWith: []string{"variable"}, + Deprecated: "use variable instead", + }, + "variable": { + Type: schema.TypeSet, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "property": { + Type: schema.TypeString, + Optional: true, + }, + "source": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + Optional: true, + ConflictsWith: []string{"variables"}, }, // TODO: rename to "assertion" for better UX "assertions": { @@ -142,7 +165,34 @@ func resourceRunscopeStep() *schema.Resource { }, }, }, - Optional: true, + Optional: true, + ConflictsWith: []string{"assertion"}, + Deprecated: "use assertion instead", + }, + "assertion": { + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "source": { + Type: schema.TypeString, + Required: true, + }, + "property": { + Type: schema.TypeString, + Optional: true, + }, + "comparison": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + Optional: true, + ConflictsWith: []string{"assertions"}, }, // TODO: rename to "header" for better UX "headers": { @@ -160,6 +210,25 @@ func resourceRunscopeStep() *schema.Resource { }, }, }, + ConflictsWith: []string{"header"}, + Deprecated: "use header instead", + }, + "header": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + ConflictsWith: []string{"headers"}, }, "auth": { Type: schema.TypeSet, @@ -248,9 +317,21 @@ func resourceStepRead(d *schema.ResourceData, meta interface{}) error { d.Set("method", step.Method) d.Set("url", step.URL) d.Set("body", step.Body) - d.Set("variables", readVariables(step.Variables)) - d.Set("assertions", readAssertions(step.Assertions)) - d.Set("headers", readHeaders(step.Headers)) + if _, ok := d.GetOk("variables"); ok { + d.Set("variables", readVariables(step.Variables)) + } else { + d.Set("variable", readVariables(step.Variables)) + } + if _, ok := d.GetOk("assertions"); ok { + d.Set("assertions", readAssertions(step.Assertions)) + } else { + d.Set("assertion", readAssertions(step.Assertions)) + } + if _, ok := d.GetOk("headers"); ok { + d.Set("headers", readHeaders(step.Headers)) + } else { + d.Set("header", readHeaders(step.Headers)) + } d.Set("scripts", step.Scripts) d.Set("before_scripts", step.BeforeScripts) d.Set("note", step.Note) @@ -276,7 +357,10 @@ func resourceStepUpdate(d *schema.ResourceData, meta interface{}) error { if d.HasChange("url") || d.HasChange("variables") || + d.HasChange("variable") || + d.HasChange("assertion") || d.HasChange("assertions") || + d.HasChange("header") || d.HasChange("headers") || d.HasChange("body") || d.HasChange("note") { @@ -323,7 +407,16 @@ func createStepFromResourceData(d *schema.ResourceData) (*runscope.TestStep, str step.URL = attr.(string) } - if attr, ok := d.GetOk("variables"); ok { + func() { + var attr interface{} + var ok bool + + if attr, ok = d.GetOk("variables"); !ok { + if attr, ok = d.GetOk("variable"); !ok { + return + } + } + variables := []*runscope.Variable{} items := attr.(*schema.Set) for _, x := range items.List() { @@ -337,7 +430,7 @@ func createStepFromResourceData(d *schema.ResourceData) (*runscope.TestStep, str variables = append(variables, &variable) } step.Variables = variables - } + }() if v, _ := d.GetOk("auth"); v != nil { authSet := v.(*schema.Set).List() @@ -351,7 +444,16 @@ func createStepFromResourceData(d *schema.ResourceData) (*runscope.TestStep, str } } - if attr, ok := d.GetOk("assertions"); ok { + func() { + var attr interface{} + var ok bool + + if attr, ok = d.GetOk("assertions"); !ok { + if attr, ok = d.GetOk("assertion"); !ok { + return + } + } + assertions := []*runscope.Assertion{} items := attr.([]interface{}) for _, x := range items { @@ -367,9 +469,18 @@ func createStepFromResourceData(d *schema.ResourceData) (*runscope.TestStep, str } step.Assertions = assertions - } + }() + + func() { + var attr interface{} + var ok bool + + if attr, ok = d.GetOk("headers"); !ok { + if attr, ok = d.GetOk("header"); !ok { + return + } + } - if attr, ok := d.GetOk("headers"); ok { step.Headers = make(map[string][]string) items := attr.(*schema.Set) for _, x := range items.List() { @@ -377,7 +488,7 @@ func createStepFromResourceData(d *schema.ResourceData) (*runscope.TestStep, str header := item["header"].(string) step.Headers[header] = append(step.Headers[header], item["value"].(string)) } - } + }() if attr, ok := d.GetOk("scripts"); ok { step.Scripts = expandStringList(attr.([]interface{})) diff --git a/runscope/resource_runscope_step_test.go b/runscope/resource_runscope_step_test.go index 135ecc9..cd37223 100644 --- a/runscope/resource_runscope_step_test.go +++ b/runscope/resource_runscope_step_test.go @@ -23,6 +23,20 @@ func TestAccStep_basic(t *testing.T) { testAccCheckStepMainPageExists("runscope_step.main_page"), resource.TestCheckResourceAttr( "runscope_step.main_page", "url", "http://example.com"), + resource.TestCheckResourceAttr("runscope_step.main_page", "variables.#", "2"), + resource.TestCheckResourceAttr("runscope_step.main_page", "assertions.#", "2"), + resource.TestCheckResourceAttr("runscope_step.main_page", "headers.#", "3"), + ), + }, + { + Config: fmt.Sprintf(testRunscopeStepConfigAWithSingulars, teamID), + Check: resource.ComposeTestCheckFunc( + testAccCheckStepMainPageExists("runscope_step.main_page"), + resource.TestCheckResourceAttr( + "runscope_step.main_page", "url", "http://example.com"), + resource.TestCheckResourceAttr("runscope_step.main_page", "variable.#", "2"), + resource.TestCheckResourceAttr("runscope_step.main_page", "assertion.#", "2"), + resource.TestCheckResourceAttr("runscope_step.main_page", "header.#", "3"), ), }, }, @@ -312,6 +326,77 @@ resource "runscope_bucket" "bucket" { } ` +const testRunscopeStepConfigAWithSingulars = ` +resource "runscope_step" "main_page" { + bucket_id = "${runscope_bucket.bucket.id}" + test_id = "${runscope_test.test.id}" + step_type = "request" + note = "Testing step, single step test" + url = "http://example.com" + method = "GET" + variable { + name = "httpStatus" + source = "response_status" + } + variable { + name = "httpContentEncoding" + source = "response_header" + property = "Content-Encoding" + } + + assertion { + source = "response_status" + comparison = "equal_number" + value = "200" + } + assertion { + source = "response_json" + comparison = "equal" + value = "c5baeb4a-2379-478a-9cda-1b671de77cf9" + property = "data.id" + } + + header { + header = "Accept-Encoding" + value = "application/json" + } + header { + header = "Accept-Encoding" + value = "application/xml" + } + header { + header = "Authorization" + value = "Bearer bb74fe7b-b9f2-48bd-9445-bdc60e1edc6a" + } + + + auth { + username = "user" + auth_type = "basic" + password = "password1" + } + + scripts = [ + "log(\"script 1\");", + "log(\"script 2\");", + ] + before_scripts = [ + "log(\"before script\");", + ] +} + +resource "runscope_test" "test" { + bucket_id = "${runscope_bucket.bucket.id}" + name = "runscope test" + description = "This is a test test..." +} + +resource "runscope_bucket" "bucket" { + name = "terraform-provider-test" + team_uuid = "%s" +} +` + const testRunscopeStepConfigMultipleSteps = ` resource "runscope_step" "step_a" { bucket_id = "${runscope_bucket.bucket.id}" diff --git a/website/docs/r/step.html.markdown b/website/docs/r/step.html.markdown index cb322a6..01ae878 100644 --- a/website/docs/r/step.html.markdown +++ b/website/docs/r/step.html.markdown @@ -22,22 +22,22 @@ resource "runscope_step" "main_page" { url = "http://example.com" note = "A comment for the test step" method = "GET" - variables { + variable { name = "httpStatus" source = "response_status" } - variables { + variable { name = "httpContentEncoding" source = "response_header" property = "Content-Encoding" } - assertions { + assertion { source = "response_status" comparison = "equal_number" value = "200" } - assertions { + assertion { source = "response_json" comparison = "equal" value = "c5baeb4a-2379-478a-9cda-1b671de77cf9" @@ -61,15 +61,15 @@ resource "runscope_step" "main_page" { alert('this is a multi-line after script') EOF ] - headers { + header { header = "Accept-Encoding" value = "application/json" } - headers { + header { header = "Accept-Encoding" value = "application/xml" } - headers { + header { header = "Authorization" value = "Bearer bb74fe7b-b9f2-48bd-9445-bdc60e1edc6a" } @@ -106,33 +106,37 @@ The following arguments are supported: When creating a `request` type of step the additional arguments also apply: * `method` - (Required) The HTTP method for this request step. -* `variables` - (Optional) A list of variables to extract out of the HTTP response from this request. Variables documented below. -* `assertions` - (Optional) A list of assertions to apply to the HTTP response from this request. Assertions documented below. -* `headers` - (Optional) A list of headers to apply to the request. Headers documented below. +* `variable` - (Optional) Block describing variable to extract out of the HTTP response from this request. May be declared multiple times. Variable documented below. +* `assertion` - (Optional) Block describing assertion to apply to the HTTP response from this request. May be declared multiple times. Assertion documented below. +* `header` - (Optional) Block describing header to apply to the request. May be declared multiple times. Header documented below. * `body` - (Optional) A string to use as the body of the request. * `auth` - (Optional) The credentials used to authenticate the request * `before_script` - (Optional) Runs a script before the request is made * `script` - (Optional) Runs a script after the request is made -Variables (`variables`) supports the following: +* `variables` - (Optional) **Deprecated**. Use `variable` block instead. A list of variables to extract out of the HTTP response from this request. +* `assertions` - (Optional) **Deprecated**. Use `assertion` block instead. A list of assertions to apply to the HTTP response from this request. +* `headers` - (Optional) **Deprecated**. Use `header` block instead. A list of headers to apply to the request. + +Variable (`variable`) supports the following: * `name` - (Required) Name of the variable to define. * `property` - (Required) The name of the source property. i.e. header name or json path * `source` - (Required) The variable source, for list of allowed values see: https://www.runscope.com/docs/api/steps#assertions -Assertions (`assertions`) supports the following: +Assertion (`assertion`) supports the following: * `source` - (Required) The assertion source, for list of allowed values see: https://www.runscope.com/docs/api/steps#assertions * `property` - (Optional) The name of the source property. i.e. header name or json path * `comparison` - (Required) The assertion comparison to make i.e. `equals`, for list of allowed values see: https://www.runscope.com/docs/api/steps#assertions * `value` - (Optional) The value the `comparison` will use -**Example Assertions** +**Example Assertion** Status Code == 200 -```json -"assertions": [ +``` +"assertion": [ { "source": "response_status", "comparison": "equal_number", @@ -144,8 +148,8 @@ Status Code == 200 JSON element 'address' contains the text "avenue" -```json -"assertions": [ +``` +"assertion": [ { "source": "response_json", "property": "address", @@ -158,8 +162,8 @@ JSON element 'address' contains the text "avenue" Response Time is faster than 1 second. -```json -"assertions": [ +``` +"assertion": [ { "source": "response_time", "comparison": "is_less_than",