Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jv integration tests for runtime config #1899

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

JoukoVirtanen
Copy link
Contributor

Description

Integration tests for runtime configuration. The tests create various versions of the runtime configuration file and check that the configuration introspection endpoint returns the correct expected configuration.

Checklist

  • Investigated and inspected CI test results
  • Updated documentation accordingly

Automated testing

  • Added unit tests
  • Added integration tests
  • Added regression tests

If any of these don't apply, please comment below.

Testing Performed

TODO(replace-me)
Use this space to explain how you tested your PR, or, if you didn't test it, why you did not do so. (Valid reasons include "CI is sufficient" or "No testable changes")
In addition to reviewing your code, reviewers must also review your testing instructions, and make sure they are sufficient.

For more details, ref the Confluence page about this section.

} catch (const YAML::Exception& e) {
CLOG(ERROR) << "Failed to parse the configuration file: " << config_file << ". Error: " << e.what();
} catch (const std::exception& e) {
CLOG(ERROR) << "An unknown error occured while loading the configuration file: " << config_file << ". Error: " << e.what();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Remove

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

Copy link
Collaborator

@Molter73 Molter73 left a comment

Choose a reason for hiding this comment

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

I'm less than half way through, I'll finish the review tomorrow.

collector/lib/ConfigLoader.cpp Outdated Show resolved Hide resolved
@@ -67,12 +67,20 @@ TEST(CollectorConfigTest, TestYamlConfigToConfigInvalid) {
}

TEST(CollectorConfigTest, TestYamlConfigToConfigEmpty) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please update this test name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -41,6 +41,7 @@ func NewDockerCollectorManager(e executor.Executor, name string) *DockerCollecto
"/host/etc:ro": "/etc",
"/host/usr/lib:ro": "/usr/lib",
"/host/sys/kernel/debug:ro": "/sys/kernel/debug",
"/etc/stackrox:ro": "/tmp",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Consider creating a separate directory for this like /tmp/collector-test and use that instead of the full /tmp directory.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment on lines 42 to 79
func AssertExternalIps(t *testing.T, enable bool, collectorIP string) {
AssertRepeated(t, func() bool {
body := QueryConfig(t, collectorIP)
var response types.RuntimeConfig
err := json.Unmarshal(body, &response)
assert.NoError(t, err)

return response.Networking.ExternalIps.Enable == enable
})
}

func AssertNoRuntimeConfig(t *testing.T, collectorIP string) {
AssertRepeated(t, func() bool {
body := QueryConfig(t, collectorIP)
return strings.TrimSpace(string(body)) == "{}"
})
}

// TODO: This should be in its own package
func AssertRepeated(t *testing.T, condition func() bool) {
tick := time.NewTicker(1 * time.Second)
timer := time.After(3 * time.Minute)

for {
select {
case <-tick.C:
if condition() {
// Condition has been met
return
}

case <-timer:
// TODO: This message should be passed in rather than hard coded here
t.Log("Timeout reached: Runtime configuration was not updated")
t.FailNow()
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

We probably want to move all assertions to a separate pkg/assert or similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment on lines 34 to 40
func QueryConfig(t *testing.T, collectorIP string) []byte {
log.Info("Querying: /state/config")
body, err := IntrospectionQuery(collectorIP, "/state/config")
assert.NoError(t, err)
log.Info("Response: %q", body)
return body
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not 100% sold this is something we need, from a test we could just do:

body, err := IntrospectionQuery(s.Collector().IP(), "/state/config")
s.Require().NoError(err)

This is simple enough and you can add the logging if you deem it necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@JoukoVirtanen JoukoVirtanen force-pushed the jv-integration-tests-for-runtime-config branch from b446ed0 to 347114d Compare November 6, 2024 19:21
@JoukoVirtanen JoukoVirtanen changed the base branch from master to jv-ROX-26726-collector-integration-tests-should-record-all-connections November 7, 2024 02:18
@JoukoVirtanen JoukoVirtanen changed the base branch from jv-ROX-26726-collector-integration-tests-should-record-all-connections to master November 7, 2024 02:23
@@ -33,7 +33,7 @@ loop:
case <-timer:
// we know they don't match at this point, but by using
// ElementsMatch we get much better logging about the differences
return assert.ElementsMatch(t, expected, s.Connections(containerID), "timed out waiting for networks")
return assert.ElementsMatch(t, expected, s.Connections(containerID), "timed out waiting for network connections")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The changes in this file were made here https://github.com/stackrox/collector/pull/1902/files

@@ -32,7 +32,6 @@ const (
// us to use any comparable type as the key)
type ProcessMap map[types.ProcessInfo]interface{}
type LineageMap map[types.ProcessLineage]interface{}
type ConnMap map[types.NetworkInfo]interface{}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The changes in this file were made here https://github.com/stackrox/collector/pull/1902/files

Comment on lines 15 to 22
func AssertExternalIps(t *testing.T, enable bool, collectorIP string) {
AssertRepeated(t, func() bool {
body, err := collector.IntrospectionQuery(collectorIP, "/state/config")
Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't need to do this here, but the IntrospectionQuery method needs to be part of a collector manager object, it would change this to be a lot simpler/clearer:

func AssertExternalIps(t *testing.T, enable bool, collector *CollectorManager) {
	AssertRepeated(t, func() bool {
		body, err := collector.IntrospectionQuery("/state/config")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it can be done in another PR. Maybe we should have an Introspection struct that could be a member of a Collector interface. The introspection object would get the IP address from the collector object.

integration-tests/pkg/types/runtime_config.go Outdated Show resolved Hide resolved
integration-tests/suites/runtime_config_file.go Outdated Show resolved Hide resolved
integration-tests/suites/runtime_config_file.go Outdated Show resolved Hide resolved
integration-tests/suites/runtime_config_file.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@Molter73 Molter73 left a comment

Choose a reason for hiding this comment

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

Thanks for splitting the tests up, as silly as it may sound, it's a lot easier to understand what is going on now.

The comments I left now are mostly on moving some comments around to leave the code blocks on their own. This should help reduce clutter a bit more, since the description of what will be done is provided up front and the code is left as clean as possible.

integration-tests/suites/runtime_config_file.go Outdated Show resolved Hide resolved
integration-tests/suites/runtime_config_file.go Outdated Show resolved Hide resolved
Comment on lines 124 to 127
// The runtime config file was deleted before starting collector so there should not be any config
assert.AssertNoRuntimeConfig(s.T(), collectorIP)
// Since there is no config the default is used, which means external IPs is disabled and we should
// expect a normalized connection
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// The runtime config file was deleted before starting collector so there should not be any config
assert.AssertNoRuntimeConfig(s.T(), collectorIP)
// Since there is no config the default is used, which means external IPs is disabled and we should
// expect a normalized connection
// The runtime config file was deleted before starting collector.
// Default configuration is external IPs disabled.
// We expect normalized connections.
assert.AssertNoRuntimeConfig(s.T(), collectorIP)

Copy link
Collaborator

Choose a reason for hiding this comment

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

This same change can be applied to the other 2 tests.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This was not applied to all tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It has now been applied to all tests.

integration-tests/suites/runtime_config_file.go Outdated Show resolved Hide resolved
integration-tests/suites/runtime_config_file.go Outdated Show resolved Hide resolved
integration-tests/suites/runtime_config_file.go Outdated Show resolved Hide resolved
@JoukoVirtanen
Copy link
Contributor Author

JoukoVirtanen commented Nov 12, 2024

CI results

Run 1
Many Konflux integration tests failed. rhcos failed with

=== RUN   TestProcfsScraperDisableFeatureFlag/TestProcfsScraper
    expect_conn.go:181: 
        	Error Trace:	/tests/pkg/mock_sensor/expect_conn.go:181
        	            				/tests/suites/procfs_scraper.go:72
        	Error:      	elements differ
        	            	
        	            	extra elements in list A:
        	            	([]interface ***) (len=1) ***
        	            	 (types.EndpointInfo) ***
        	            	  Protocol: (string) (len=15) "L4_PROTOCOL_TCP",
        	            	  Address: (types.ListenAddress) ***
        	            	   AddressData: (string) (len=4) "\x00\x00\x00\x00",
        	            	   Port: (int) 80,
        	            	   IpNetwork: (string) (len=5) "\x00\x00\x00\x00 "
        	            	  ***,
        	            	  CloseTimestamp: (string) (len=5) "<nil>",
        	            	  Originator: (types.ProcessOriginator) ***
        	            	   ProcessName: (string) "",
        	            	   ProcessExecFilePath: (string) "",
        	            	   ProcessArgs: (string) ""
        	            	  ***
        	            	 ***
        	            	***
        	            	
        	            	
        	            	listA:
        	            	([]types.EndpointInfo) (len=1) ***
        	            	 (types.EndpointInfo) ***
        	            	  Protocol: (string) (len=15) "L4_PROTOCOL_TCP",
        	            	  Address: (types.ListenAddress) ***
        	            	   AddressData: (string) (len=4) "\x00\x00\x00\x00",
        	            	   Port: (int) 80,
        	            	   IpNetwork: (string) (len=5) "\x00\x00\x00\x00 "
        	            	  ***,
        	            	  CloseTimestamp: (string) (len=5) "<nil>",
        	            	  Originator: (types.ProcessOriginator) ***
        	            	   ProcessName: (string) "",
        	            	   ProcessExecFilePath: (string) "",
        	            	   ProcessArgs: (string) ""
        	            	  ***
        	            	 ***
        	            	***
        	            	
        	            	
        	            	listB:
        	            	([]types.EndpointInfo) ***
        	            	***
        	Test:       	TestProcfsScraperDisableFeatureFlag/TestProcfsScraper
        	Messages:   	timed out waiting for endpoints

The other konflux integration tests failed with either problems pulling the image. Both konflux and non-konflux cos integration tests failed with verifier errors.

Run 2:
Similar errors as above. No procfs test error. Collector also fails for fedora coreos.

Run 3:
rhcos had the following error

=== RUN   TestUdpNetworkFlow/TestUdpNetorkflow/sendto_recvmmsg
    udp_networkflow.go:274: 
        	Error Trace:	/tests/suites/udp_networkflow.go:274
        	            				/tests/suites/udp_networkflow.go:244
        	            				/tests/suites/udp_networkflow.go:105
        	            				/tests/suites/udp_networkflow.go:96
        	            				/go/pkg/mod/github.com/stretchr/[email protected]/suite/suite.go:115
        	Error:      	Received unexpected error:
        	            	Error response from daemon: container create: creating container storage: the container name "udp-server" is already in use by 0b88d4d870e77d5fed05bd5bad8a1dd1e5391d4e229d7ffb3d92a5bd57d0febf. You have to remove that container to be able to reuse that name: that name is already in use
        	            	create udp-server

I did not see a previous failure that caused this error. There were other failures unrelated to the changes in the PR.

@JoukoVirtanen JoukoVirtanen marked this pull request as ready for review November 12, 2024 23:16
@JoukoVirtanen JoukoVirtanen requested a review from a team as a code owner November 12, 2024 23:16
Copy link
Collaborator

@Molter73 Molter73 left a comment

Choose a reason for hiding this comment

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

Changes look ok, but #1902 still has comments on it that haven't been addressed, if your intent is to merge the changes from that PR with this one, please close it so I can move my comments to this PR.

Comment on lines 36 to 37
tick := time.NewTicker(1 * time.Second)
timer := time.After(3 * time.Minute)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can these timeouts be configurable via some parameters?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@JoukoVirtanen JoukoVirtanen force-pushed the jv-integration-tests-for-runtime-config branch from 8420864 to 9b4f72e Compare November 14, 2024 01:54
@JoukoVirtanen
Copy link
Contributor Author

Changes look ok, but #1902 still has comments on it that haven't been addressed, if your intent is to merge the changes from that PR with this one, please close it so I can move my comments to this PR.

I have addressed the PR review comments in the other PR.

integration-tests/pkg/assert/assert.go Outdated Show resolved Hide resolved
integration-tests/pkg/mock_sensor/server.go Outdated Show resolved Hide resolved
@JoukoVirtanen JoukoVirtanen force-pushed the jv-integration-tests-for-runtime-config branch from 4a03f7b to 9241f09 Compare November 21, 2024 05:20
Copy link
Collaborator

@Molter73 Molter73 left a comment

Choose a reason for hiding this comment

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

LGTM, but holding approval until #1902 is merged, so this can be rebased on top of that.

e8bb38d Starting work
23ee1b0 Working with config introspection endpoint. No checks for connections yet
1b919ee Moved code for introspection endpoint from mock sensor to own directory
91ee35e Testing with an invalid config
ae8bf37 Creates a container with an external connection and adds tests for it. Also made changes so that external connections can be checked for
34247e2 Mock server no longer maintains just a map of connections seen, but all connections
edf7ca3 Should be able to handle cidr blocks and non-cidr blocks
4b227bd Able to handle the case when there is only port data
dbed0a1 Brought in changes to server.go to handle external ips
fd24fe8 Apply suggestions from code review
3eb5e48 Cleanup
13f8539 Able to control if connections should be ordered or not. Also added comments
f9ea3fc Listening for new connection events instead of using a ticker
6d06416 Using ExpectSameElementsConnections instead of ExpectExactConnections
9c3f013 More error handling for reading the configuration. Using a volume mount
a4fe63b Fixed lint error
8dce19c The runtime config file is only modified on the host machine
1c05a55 There is now only one source code file for runtime config introspection
7b77e23 Minor fixes for k8s
e53509f Added comments and sleeps when config does not change so we get a scrape interval
2da34ae Increased the afterglow period
ca6dd2c Update collector/lib/ConfigLoader.cpp
6aa60e0 Renamed unit test. Integration tests use a dedicated directory
a6b0c57 Created a new assert package
949534d Apply suggestions from code review
09b13aa Split test into smaller tests
9346776 Apply suggestions from code review
3586964 Removed unneeded sort
5e95832 Using slices.ContainsFunc in HasConnection
76e244d Made timings in AssertRepeated configurable
5e94d5c Always sort the connections when comparing
12c04f3 Not using assertMismatch
129308e Updated comments
0b34466 Apply suggestions from code review
e2fd23c Sorting connections inside Connections instead of SortedConnections
a544a68 Created ElementsMatchFunc in assert pkg
6d1a737 Using spew for logging
2ae0101 Apply suggestions from code review
416b7f2 Importing logging package
9241f09 Simplified by removing checkIfConnectionsMatchExpected
ba6babc Changed assert.True to assert.Fail
@JoukoVirtanen JoukoVirtanen force-pushed the jv-integration-tests-for-runtime-config branch from ba6babc to 72fb150 Compare November 28, 2024 03:14
Copy link
Collaborator

@Molter73 Molter73 left a comment

Choose a reason for hiding this comment

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

LGTM!

Just a small comment on a TODO that I think we could solve quickly before merging, but we can also address it on the next PR that needs to use the helper function.

Comment on lines 55 to 56
// TODO: This message should be passed in rather than hard coded here
log.Error("Timeout reached: Runtime configuration was not updated")
Copy link
Collaborator

Choose a reason for hiding this comment

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

This TODO should be relatively simple to solve, add a format and args parameter to the function like this:

func AssertRepeated(t *testing.T, tickTime time.Duration, timeout time.Duration, condition func() bool, msg string, args ...interface{}) {

Then here you can just call log.Error like this:

log.Error("Timeout reached: " + msg, args...)

If this ends up being too verbose on the call sites with the function being defined inline, you can always define the function and assign it to a variable, then pass that in.

@Molter73
Copy link
Collaborator

Also, there are some tests on the multiarch for konflux, but those are due to the integration test image not being rebuilt for those archs, this is not a blocker for this PR and I'm trying to address it here: #1974

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants