Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ variables:
# and check the job creating the image to make sure you have the right SHA prefix
TEST_INFRA_DEFINITIONS_BUILDIMAGES_SUFFIX: ""
# Make sure to update test-infra-definitions version in go.mod as well
TEST_INFRA_DEFINITIONS_BUILDIMAGES: a1d921006e35
TEST_INFRA_DEFINITIONS_BUILDIMAGES: eb67dd1667e4
DATADOG_AGENT_BUILDERS: v22276738-b36b132

DATADOG_AGENT_EMBEDDED_PATH: /opt/datadog-agent/embedded
Expand Down
2 changes: 1 addition & 1 deletion test/new-e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ require (
// `TEST_INFRA_DEFINITIONS_BUILDIMAGES` matches the commit sha in the module version
// Example: github.com/DataDog/test-infra-definitions v0.0.0-YYYYMMDDHHmmSS-0123456789AB
// => TEST_INFRA_DEFINITIONS_BUILDIMAGES: 0123456789AB
github.com/DataDog/test-infra-definitions v0.0.0-20240308103459-6dbc5dad4e60
github.com/DataDog/test-infra-definitions v0.0.0-20240312182905-eb67dd1667e4
github.com/aws/aws-sdk-go-v2 v1.25.2
github.com/aws/aws-sdk-go-v2/config v1.27.6
github.com/aws/aws-sdk-go-v2/service/ec2 v1.138.1
Expand Down
4 changes: 2 additions & 2 deletions test/new-e2e/go.sum

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

17 changes: 9 additions & 8 deletions test/new-e2e/tests/remote-config/rc_ssl_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ package remoteconfig

import (
_ "embed"
"github.com/stretchr/testify/assert"
"testing"
"time"

"github.com/stretchr/testify/assert"

"github.com/DataDog/datadog-agent/test/new-e2e/pkg/e2e"
"github.com/DataDog/datadog-agent/test/new-e2e/pkg/environments"
awshost "github.com/DataDog/datadog-agent/test/new-e2e/pkg/environments/aws/host"
Expand Down Expand Up @@ -38,13 +39,13 @@ func TestSslConfigSuite(t *testing.T) {

// TestRemoteConfigSSLConfigMismatch tests the startup condition where the agent's SSL config is disabled but RC's TLS validation is not explicitly disabled
func (s *sslConfigSuite) TestRemoteConfigSSLConfigMismatch() {
// Ensure the remote config service starts
assertLogsEventually(s.T(), s.Env().RemoteHost, "agent", "remote config service started", 2*time.Minute, 5*time.Second)
Comment thread
pducolin marked this conversation as resolved.

// Ensure the agent logs a warning about the SSL config mismatch
assertLogsEventually(s.T(), s.Env().RemoteHost, "agent", "remote Configuration does not allow skipping TLS validation by default", 2*time.Minute, 5*time.Second)
// Ensure the remote config service stops, and the client stops because the service is no longer responding
assertLogsEventually(s.T(), s.Env().RemoteHost, "agent", "remote configuration isn't enabled, disabling client", 2*time.Minute, 5*time.Second)
expectedLogs := []string{
// Ensure the agent logs a warning about the SSL config mismatch
"remote Configuration does not allow skipping TLS validation by default",
// Ensure the remote config service stops, and the client stops because the service is no longer responding
"remote configuration isn't enabled, disabling client",
}
assertAgentLogsEventually(s.T(), s.Env().RemoteHost, "agent", expectedLogs, 2*time.Minute, 5*time.Second)

// Ensure the agent remains running despite the remote config service initialization failure
// EventuallyWithT will wait for the duration of the `tick` argument before executing the assertion function,
Expand Down
20 changes: 12 additions & 8 deletions test/new-e2e/tests/remote-config/tracer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,20 @@ func TestRcTracerSuite(t *testing.T) {

// TestRemoteConfigTracerUpdate tests the remote-config service by attempting to retrieve RC payloads as if a tracer were calling it
func (s *tracerSuite) TestRemoteConfigTracerUpdate() {
// Ensure the remote config service starts
assertLogsEventually(s.T(), s.Env().RemoteHost, "agent", "remote config service started", 2*time.Minute, 5*time.Second)

// Wait until we've started querying for configs
assertLogsEventually(s.T(), s.Env().RemoteHost, "agent", "/api/v0.1/configurations", 2*time.Minute, 5*time.Second)
expectedAgentLogs := []string{
// Ensure the remote config service starts
"remote config service started",
// Wait until we've started querying for configs
"/api/v0.1/configurations",
}
assertAgentLogsEventually(s.T(), s.Env().RemoteHost, "agent", expectedAgentLogs, 2*time.Minute, 5*time.Second)

// Get configs as though we are a tracer
getConfigsOutput := mustCurlAgentRcServiceEventually(s.T(), s.Env().RemoteHost, tracerPayloadJSON, 2*time.Minute, 5*time.Second)
require.Contains(s.T(), getConfigsOutput, "roots", "expected a roots key in the tracer config output")
require.Contains(s.T(), getConfigsOutput, "targets", "expected a targets key in the tracer config output")
expectedKeys := []string{
"roots",
"targets",
}
assertCurlAgentRcServiceContainsEventually(s.T(), s.Env().RemoteHost, tracerPayloadJSON, expectedKeys, 2*time.Minute, 5*time.Second)

// Check remote-config command output for our e2e test client that we fetched configs for
remoteConfigOutput := s.Env().Agent.Client.RemoteConfig()
Expand Down
74 changes: 64 additions & 10 deletions test/new-e2e/tests/remote-config/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,91 @@ package remoteconfig
import (
_ "embed"
"fmt"
"github.com/DataDog/datadog-agent/test/new-e2e/pkg/components"
"github.com/stretchr/testify/assert"
"os"
"path"
"strings"
"testing"
"time"

"github.com/DataDog/datadog-agent/test/new-e2e/pkg/components"
"github.com/stretchr/testify/assert"
)

// assertLogsEventually will verify that a given `agentName` component's logs contain a pattern.
// It will continually retry until the `expectedLogPattern` is found or the `maxRetries` is reached,
// waiting `retryInterval` between each attempt.
// If the `expectedLogPattern` is not found or an error occurs, the calling test will fail.
func assertLogsEventually(t *testing.T, rh *components.RemoteHost, agentName string, expectedLogPattern string, waitFor time.Duration, tick time.Duration) {
func assertAgentLogsEventually(t *testing.T, rh *components.RemoteHost, agentName string, expectedLogs []string, waitFor time.Duration, tick time.Duration) {
t.Helper()
foundLogs := make(map[string]bool, len(expectedLogs))
missingLogs := make([]string, len(expectedLogs))
// initially all logs are missing
copy(missingLogs, expectedLogs)
remoteLogsPath := fmt.Sprintf("/var/log/datadog/%s.log", agentName)
t.Logf("looking for logs in %s", remoteLogsPath)
assert.EventuallyWithTf(t, func(c *assert.CollectT) {
output, err := rh.Execute(fmt.Sprintf("cat /var/log/datadog/%s.log", agentName))
if assert.NoError(c, err) {
assert.Contains(c, output, expectedLogPattern)
// read agent logs
agentLogs, err := readRemoteFile(rh, remoteLogsPath)
if !assert.NoError(c, err) {
return
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess assert.NoError will raise a message so no need to create one here, correct?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would not: assert does not interrupt the go routine execution. I should use require that calls FailNow, but currently it panics and interrupts the Eventually. This will change as soon as testify merges this PR

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a consequence we might have put a log message to understand the error. But it's unlikely to happen so I guess it's fine

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we log the error out of the Eventually. All failed assertions messages are saved in the assert.CollectT and logged on Fail

https://github.com/marshall-lee/testify/blob/master/assert/assertions.go#L312-L336

}
for _, log := range missingLogs {
if strings.Contains(agentLogs, log) {
t.Logf("found log: %s", log)
foundLogs[log] = true
}
}
}, waitFor, tick, "failed to find log with pattern `%s`", expectedLogPattern)
// reset missing logs
missingLogs = make([]string, 0, len(expectedLogs))
Comment thread
chouetz marked this conversation as resolved.
for _, log := range expectedLogs {
if _, ok := foundLogs[log]; ok {
continue
}
missingLogs = append(missingLogs, log)
}
assert.Empty(c, missingLogs, "still missing logs")
t.Logf("missing logs:\n[%s]", strings.Join(missingLogs, ","))
}, waitFor, tick, "failed finding logs in agent")
}

// mustCurlAgentRcServiceEventually will curl the remote config service's endpoint to get tracer
// configurations every `tick` until either it is successful (in which case it will return the
// output of the curl command), or the `waitFor` duration is reached (in which case it will
// fail the calling test).
func mustCurlAgentRcServiceEventually(t *testing.T, rh *components.RemoteHost, payload string, waitFor time.Duration, tick time.Duration) string {
func assertCurlAgentRcServiceContainsEventually(t *testing.T, rh *components.RemoteHost, payload string, expectedKeys []string, waitFor time.Duration, tick time.Duration) string {
Comment thread
chouetz marked this conversation as resolved.
t.Helper()
var output string
missingContents := make([]string, len(expectedKeys))
copy(missingContents, expectedKeys)
foundContents := make(map[string]bool, len(expectedKeys))
assert.EventuallyWithTf(t, func(c *assert.CollectT) {
curl, err := rh.Execute(fmt.Sprintf("curl -sS localhost:8126/v0.7/config -d @- <<EOF\n%sEOF", payload))
curlOutput, err := rh.Execute(fmt.Sprintf("curl -sSL localhost:8126/v0.7/config -d @- <<EOF\n%sEOF", payload))
assert.NoError(c, err)
output = curl
for _, content := range missingContents {
if strings.Contains(curlOutput, content) {
t.Logf("found content: %s", content)
foundContents[content] = true
}
}
// reset missing contents
missingContents = make([]string, 0, len(expectedKeys))
for _, content := range expectedKeys {
if _, ok := foundContents[content]; ok {
continue
}
missingContents = append(missingContents, content)
}
assert.Empty(c, missingContents, "still missing contents")
}, waitFor, tick, "could not curl remote config service")
return output
}

func readRemoteFile(rh *components.RemoteHost, remotePath string) (string, error) {
Comment thread
chouetz marked this conversation as resolved.
localPath := path.Join(os.TempDir(), path.Base(remotePath))
err := rh.GetFile(remotePath, localPath)
if err != nil {
return "", err
}
b, err := os.ReadFile(localPath)
return string(b), err
}