Skip to content

Commit

Permalink
[datadog_synthetics_test] Add handling of a wait step for multistep a…
Browse files Browse the repository at this point in the history
…pi tests (DataDog#2472)

* add handling of a wait step for multistep api tests

* add some fixes and update cassettes

* update docs
  • Loading branch information
teodor2312 authored and bharling committed Jul 8, 2024
1 parent bc175aa commit f60fee4
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 146 deletions.
230 changes: 126 additions & 104 deletions datadog/resource_datadog_synthetics_test_.go
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@ func syntheticsTestAPIStep() *schema.Schema {
requestElemSchema.Schema["follow_redirects"] = syntheticsFollowRedirectsOption()

return &schema.Schema{
Description: "Steps for multistep api tests",
Description: "Steps for multi-step api tests",
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Expand All @@ -815,11 +815,11 @@ func syntheticsTestAPIStep() *schema.Schema {
Required: true,
},
"subtype": {
Description: "The subtype of the Synthetic multistep API test step.",
Description: "The subtype of the Synthetic multi-step API test step.",
Type: schema.TypeString,
Optional: true,
Default: "http",
ValidateDiagFunc: validators.ValidateEnumValue(datadogV1.NewSyntheticsAPIStepSubtypeFromValue),
ValidateDiagFunc: validators.ValidateEnumValue(datadogV1.NewSyntheticsAPITestStepSubtypeFromValue, datadogV1.NewSyntheticsAPIWaitStepSubtypeFromValue),
},
"extracted_value": {
Description: "Values to parse and save as variables from the response.",
Expand Down Expand Up @@ -895,6 +895,11 @@ func syntheticsTestAPIStep() *schema.Schema {
Optional: true,
},
"retry": syntheticsTestOptionsRetry(),
"value": {
Description: "The time to wait in seconds. Minimum value: 0. Maximum value: 180.",
Type: schema.TypeInt,
Optional: true,
},
},
},
}
Expand Down Expand Up @@ -1678,54 +1683,64 @@ func buildSyntheticsAPITestStruct(d *schema.ResourceData) *datadogV1.SyntheticsA
step := datadogV1.SyntheticsAPIStep{}
stepMap := s.(map[string]interface{})

step.SetName(stepMap["name"].(string))
step.SetSubtype(datadogV1.SyntheticsAPIStepSubtype(stepMap["subtype"].(string)))

extractedValues := buildExtractedValues(stepMap["extracted_value"].([]interface{}))
step.SetExtractedValues(extractedValues)

assertions := stepMap["assertion"].([]interface{})
step.SetAssertions(buildAssertions(assertions))

request := datadogV1.SyntheticsTestRequest{}
requests := stepMap["request_definition"].([]interface{})
if len(requests) > 0 && requests[0] != nil {
requestMap := requests[0].(map[string]interface{})
request.SetMethod(requestMap["method"].(string))
request.SetUrl(requestMap["url"].(string))
request.SetBody(requestMap["body"].(string))
if v, ok := requestMap["body_type"].(string); ok && v != "" {
request.SetBodyType(datadogV1.SyntheticsTestRequestBodyType(v))
}
request.SetTimeout(float64(requestMap["timeout"].(int)))
request.SetAllowInsecure(requestMap["allow_insecure"].(bool))
request.SetFollowRedirects(requestMap["follow_redirects"].(bool))
request.SetPersistCookies(requestMap["persist_cookies"].(bool))
request.SetNoSavingResponseBody(requestMap["no_saving_response_body"].(bool))
if v, ok := requestMap["http_version"].(string); ok && v != "" {
request.SetHttpVersion(datadogV1.SyntheticsTestOptionsHTTPVersion(v))
stepSubtype := stepMap["subtype"].(string)

if stepSubtype == "" || stepSubtype == "http" || stepSubtype == "grpc" {
step.SyntheticsAPITestStep = datadogV1.NewSyntheticsAPITestStepWithDefaults()
step.SyntheticsAPITestStep.SetName(stepMap["name"].(string))
step.SyntheticsAPITestStep.SetSubtype(datadogV1.SyntheticsAPITestStepSubtype(stepMap["subtype"].(string)))

extractedValues := buildExtractedValues(stepMap["extracted_value"].([]interface{}))
step.SyntheticsAPITestStep.SetExtractedValues(extractedValues)

assertions := stepMap["assertion"].([]interface{})
step.SyntheticsAPITestStep.SetAssertions(buildAssertions(assertions))

request := datadogV1.SyntheticsTestRequest{}
requests := stepMap["request_definition"].([]interface{})
if len(requests) > 0 && requests[0] != nil {
requestMap := requests[0].(map[string]interface{})
request.SetMethod(requestMap["method"].(string))
request.SetUrl(requestMap["url"].(string))
request.SetBody(requestMap["body"].(string))
if v, ok := requestMap["body_type"].(string); ok && v != "" {
request.SetBodyType(datadogV1.SyntheticsTestRequestBodyType(v))
}
request.SetTimeout(float64(requestMap["timeout"].(int)))
request.SetAllowInsecure(requestMap["allow_insecure"].(bool))
request.SetFollowRedirects(requestMap["follow_redirects"].(bool))
request.SetPersistCookies(requestMap["persist_cookies"].(bool))
request.SetNoSavingResponseBody(requestMap["no_saving_response_body"].(bool))
if v, ok := requestMap["http_version"].(string); ok && v != "" {
request.SetHttpVersion(datadogV1.SyntheticsTestOptionsHTTPVersion(v))
}
}
}

request = *completeSyntheticsTestRequest(request, stepMap["request_headers"].(map[string]interface{}), stepMap["request_query"].(map[string]interface{}), stepMap["request_basicauth"].([]interface{}), stepMap["request_client_certificate"].([]interface{}), stepMap["request_proxy"].([]interface{}), map[string]interface{}{})
request = *completeSyntheticsTestRequest(request, stepMap["request_headers"].(map[string]interface{}), stepMap["request_query"].(map[string]interface{}), stepMap["request_basicauth"].([]interface{}), stepMap["request_client_certificate"].([]interface{}), stepMap["request_proxy"].([]interface{}), map[string]interface{}{})

step.SetRequest(request)
step.SyntheticsAPITestStep.SetRequest(request)

step.SetAllowFailure(stepMap["allow_failure"].(bool))
step.SetIsCritical(stepMap["is_critical"].(bool))
step.SyntheticsAPITestStep.SetAllowFailure(stepMap["allow_failure"].(bool))
step.SyntheticsAPITestStep.SetIsCritical(stepMap["is_critical"].(bool))

optionsRetry := datadogV1.SyntheticsTestOptionsRetry{}
retries := stepMap["retry"].([]interface{})
if len(retries) > 0 && retries[0] != nil {
retry := retries[0]
optionsRetry := datadogV1.SyntheticsTestOptionsRetry{}
retries := stepMap["retry"].([]interface{})
if len(retries) > 0 && retries[0] != nil {
retry := retries[0]

if count, ok := retry.(map[string]interface{})["count"]; ok {
optionsRetry.SetCount(int64(count.(int)))
}
if interval, ok := retry.(map[string]interface{})["interval"]; ok {
optionsRetry.SetInterval(float64(interval.(int)))
if count, ok := retry.(map[string]interface{})["count"]; ok {
optionsRetry.SetCount(int64(count.(int)))
}
if interval, ok := retry.(map[string]interface{})["interval"]; ok {
optionsRetry.SetInterval(float64(interval.(int)))
}
step.SyntheticsAPITestStep.SetRetry(optionsRetry)
}
step.SetRetry(optionsRetry)
} else if stepSubtype == "wait" {
step.SyntheticsAPIWaitStep = datadogV1.NewSyntheticsAPIWaitStepWithDefaults()
step.SyntheticsAPIWaitStep.SetName(stepMap["name"].(string))
step.SyntheticsAPIWaitStep.SetSubtype(datadogV1.SyntheticsAPIWaitStepSubtype(stepMap["subtype"].(string)))
step.SyntheticsAPIWaitStep.SetValue(int32(stepMap["value"].(int)))
}

steps = append(steps, step)
Expand Down Expand Up @@ -3351,78 +3366,85 @@ func updateSyntheticsAPITestLocalState(d *schema.ResourceData, syntheticsTest *d

for i, step := range *steps {
localStep := make(map[string]interface{})
localStep["name"] = step.GetName()
localStep["subtype"] = step.GetSubtype()

localAssertions, err := buildLocalAssertions(step.GetAssertions())
if err != nil {
return diag.FromErr(err)
}
localStep["assertion"] = localAssertions
localStep["extracted_value"] = buildLocalExtractedValues(step.GetExtractedValues())

stepRequest := step.GetRequest()
localRequest := buildLocalRequest(stepRequest)
localRequest["allow_insecure"] = stepRequest.GetAllowInsecure()
localRequest["follow_redirects"] = stepRequest.GetFollowRedirects()
localStep["request_definition"] = []map[string]interface{}{localRequest}
localStep["request_headers"] = stepRequest.GetHeaders()
localStep["request_query"] = stepRequest.GetQuery()

if basicAuth, ok := stepRequest.GetBasicAuthOk(); ok {
localAuth := buildLocalBasicAuth(basicAuth)
localStep["request_basicauth"] = []map[string]string{localAuth}
}

if clientCertificate, ok := stepRequest.GetCertificateOk(); ok {
localCertificate := make(map[string][]map[string]string)
localCertificate["cert"] = make([]map[string]string, 1)
localCertificate["cert"][0] = make(map[string]string)
localCertificate["key"] = make([]map[string]string, 1)
localCertificate["key"][0] = make(map[string]string)
if step.SyntheticsAPITestStep != nil {
localStep["name"] = step.SyntheticsAPITestStep.GetName()
localStep["subtype"] = step.SyntheticsAPITestStep.GetSubtype()

cert := clientCertificate.GetCert()
localCertificate["cert"][0]["filename"] = cert.GetFilename()
localAssertions, err := buildLocalAssertions(step.SyntheticsAPITestStep.GetAssertions())
if err != nil {
return diag.FromErr(err)
}
localStep["assertion"] = localAssertions
localStep["extracted_value"] = buildLocalExtractedValues(step.SyntheticsAPITestStep.GetExtractedValues())

stepRequest := step.SyntheticsAPITestStep.GetRequest()
localRequest := buildLocalRequest(stepRequest)
localRequest["allow_insecure"] = stepRequest.GetAllowInsecure()
localRequest["follow_redirects"] = stepRequest.GetFollowRedirects()
localStep["request_definition"] = []map[string]interface{}{localRequest}
localStep["request_headers"] = stepRequest.GetHeaders()
localStep["request_query"] = stepRequest.GetQuery()

if basicAuth, ok := stepRequest.GetBasicAuthOk(); ok {
localAuth := buildLocalBasicAuth(basicAuth)
localStep["request_basicauth"] = []map[string]string{localAuth}
}

key := clientCertificate.GetKey()
localCertificate["key"][0]["filename"] = key.GetFilename()
if clientCertificate, ok := stepRequest.GetCertificateOk(); ok {
localCertificate := make(map[string][]map[string]string)
localCertificate["cert"] = make([]map[string]string, 1)
localCertificate["cert"][0] = make(map[string]string)
localCertificate["key"] = make([]map[string]string, 1)
localCertificate["key"][0] = make(map[string]string)

certContentKey := fmt.Sprintf("api_step.%d.request_client_certificate.0.cert.0.content", i)
keyContentKey := fmt.Sprintf("api_step.%d.request_client_certificate.0.key.0.content", i)
cert := clientCertificate.GetCert()
localCertificate["cert"][0]["filename"] = cert.GetFilename()

// the content of client certificate is write-only so it will not be returned by the API.
// To avoid useless diff but also prevent storing the value in clear in the state
// we store a hash of the value.
if configCertificateContent, ok := d.GetOk(certContentKey); ok {
localCertificate["cert"][0]["content"] = getCertificateStateValue(configCertificateContent.(string))
}
if configKeyContent, ok := d.GetOk(keyContentKey); ok {
localCertificate["key"][0]["content"] = getCertificateStateValue(configKeyContent.(string))
}
key := clientCertificate.GetKey()
localCertificate["key"][0]["filename"] = key.GetFilename()

localStep["request_client_certificate"] = []map[string][]map[string]string{localCertificate}
}
certContentKey := fmt.Sprintf("api_step.%d.request_client_certificate.0.cert.0.content", i)
keyContentKey := fmt.Sprintf("api_step.%d.request_client_certificate.0.key.0.content", i)

if proxy, ok := stepRequest.GetProxyOk(); ok {
localProxy := make(map[string]interface{})
localProxy["url"] = proxy.GetUrl()
localProxy["headers"] = proxy.GetHeaders()
// the content of client certificate is write-only so it will not be returned by the API.
// To avoid useless diff but also prevent storing the value in clear in the state
// we store a hash of the value.
if configCertificateContent, ok := d.GetOk(certContentKey); ok {
localCertificate["cert"][0]["content"] = getCertificateStateValue(configCertificateContent.(string))
}
if configKeyContent, ok := d.GetOk(keyContentKey); ok {
localCertificate["key"][0]["content"] = getCertificateStateValue(configKeyContent.(string))
}

localStep["request_proxy"] = []map[string]interface{}{localProxy}
}
localStep["request_client_certificate"] = []map[string][]map[string]string{localCertificate}
}

localStep["allow_failure"] = step.GetAllowFailure()
localStep["is_critical"] = step.GetIsCritical()
if proxy, ok := stepRequest.GetProxyOk(); ok {
localProxy := make(map[string]interface{})
localProxy["url"] = proxy.GetUrl()
localProxy["headers"] = proxy.GetHeaders()

if retry, ok := step.GetRetryOk(); ok {
localRetry := make(map[string]interface{})
if count, ok := retry.GetCountOk(); ok {
localRetry["count"] = *count
localStep["request_proxy"] = []map[string]interface{}{localProxy}
}
if interval, ok := retry.GetIntervalOk(); ok {
localRetry["interval"] = *interval

localStep["allow_failure"] = step.SyntheticsAPITestStep.GetAllowFailure()
localStep["is_critical"] = step.SyntheticsAPITestStep.GetIsCritical()

if retry, ok := step.SyntheticsAPITestStep.GetRetryOk(); ok {
localRetry := make(map[string]interface{})
if count, ok := retry.GetCountOk(); ok {
localRetry["count"] = *count
}
if interval, ok := retry.GetIntervalOk(); ok {
localRetry["interval"] = *interval
}
localStep["retry"] = []map[string]interface{}{localRetry}
}
localStep["retry"] = []map[string]interface{}{localRetry}
} else if step.SyntheticsAPIWaitStep != nil {
localStep["name"] = step.SyntheticsAPIWaitStep.GetName()
localStep["subtype"] = step.SyntheticsAPIWaitStep.GetSubtype()
localStep["value"] = step.SyntheticsAPIWaitStep.GetValue()
}

localSteps[i] = localStep
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2024-06-13T11:39:35.035141+02:00
2024-07-02T17:53:32.710488+02:00
Loading

0 comments on commit f60fee4

Please sign in to comment.