diff --git a/.circleci/README.md b/.circleci/README.md index c717b017b6690..e097248219003 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -11,12 +11,12 @@ This image is now built alongside other images in [agent-buildimages](https://gi Once you have created a new image by building a new version of agent-buildimages, you can test your modification with the associated invoke task: ```bash -invoke -e buildimages.update --image-tag v12345678-c0mm1t5 +invoke -e buildimages.update --tag v12345678-c0mm1t5 ``` -This will update the configuration of circleci and gitlab to use the __test version__ of these images. -Once your test is successful, you can either move the `_test_version` from files or invoke +This will update the configuration of circleci and gitlab to use the __test__ version of these images. +Once your test is successful, you can either move the `_test_only` from files or invoke ```bash -invoke -e buildimages.update --image-tag v12345678-c0mm1t5 --no-test-version +invoke -e buildimages.update --tag v12345678-c0mm1t5 --no-test ``` If everything is green, get a review and merge the PR. diff --git a/.copyright-overrides.yml b/.copyright-overrides.yml index 8051687b44906..7689d21d0ca46 100644 --- a/.copyright-overrides.yml +++ b/.copyright-overrides.yml @@ -365,6 +365,7 @@ github.com/signalfx/sapm-proto/*: Copyright 2019 Splunk, Inc. go.mongodb.org/atlas/mongodbatlas: Copyright 2022 MongoDB Inc github.com/go-jose/go-jose/v4: Copyright 2014 Square Inc. github.com/gocolly/colly: Copyright 2018 Adam Tauber +github.com/puzpuzpuz/xsync/v3: Copyright (c) 2021 Andrey Pechkurov github.com/vibrantbyte/go-antpath/antpath: vibrantbyte |suchao github.com/vibrantbyte/go-antpath/extend: vibrantbyte |suchao diff --git a/.ddqa/config.toml b/.ddqa/config.toml index 0b2d11709b4b1..0e1297377768d 100644 --- a/.ddqa/config.toml +++ b/.ddqa/config.toml @@ -57,12 +57,20 @@ jira_statuses = ["To Do", "In Progress", "Done"] github_team = "universal-service-monitoring" github_labels = ["team/usm"] -[teams."Network Device Monitoring"] +[teams."Network Device Monitoring - Core"] jira_project = "NDMII" jira_issue_type = "Task" jira_statuses = ["To Do", "In Progress", "Done"] -github_team = "network-device-monitoring" -github_labels = ["team/network-device-monitoring"] +github_team = "ndm-core" +github_labels = ["team/ndm-core", "team/network-device-monitoring"] +exclude_members = ["leeavital", "heyronhay"] + +[teams."Network Device Monitoring - Integrations"] +jira_project = "NDINT" +jira_issue_type = "Task" +jira_statuses = ["To Do", "In Progress", "Done"] +github_team = "ndm-integrations" +github_labels = ["team/ndm-integrations"] exclude_members = ["leeavital", "heyronhay"] [teams."Network Performance Monitoring"] @@ -203,9 +211,9 @@ jira_statuses = ["💼 To Do", "💡 In Progress", "✅ Done"] github_team = "container-app" github_labels = ["team/container-app"] -[teams."APM Onboarding"] -jira_project = "APMON" -jira_issue_type = "Story" +[teams."APM Injection Platform"] +jira_project = "INPLAT" +jira_issue_type = "Task" jira_statuses = ["Selected For Development", "In Progress", "Done"] github_team = "apm-onboarding" github_labels = ["team/apm-onboarding"] @@ -222,4 +230,4 @@ jira_project = "DEBUG" jira_issue_type = "Task" jira_statuses = ["To Do", "In Progress", "Done"] github_team = "debugger-go" -github_labels = ["team/dynamic-instrumentation"] \ No newline at end of file +github_labels = ["team/dynamic-instrumentation"] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 17088e208475c..1e60e1e230c97 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -190,7 +190,7 @@ /cmd/agent/subcommands/dogstatsd* @DataDog/agent-metrics-logs /cmd/agent/subcommands/integrations @DataDog/agent-integrations @DataDog/agent-shared-components /cmd/agent/subcommands/remoteconfig @Datadog/remote-config -/cmd/agent/subcommands/snmp @DataDog/network-device-monitoring +/cmd/agent/subcommands/snmp @DataDog/ndm-core /cmd/agent/subcommands/streamlogs @DataDog/agent-metrics-logs /cmd/agent/subcommands/streamep @DataDog/container-integrations /cmd/agent/subcommands/taggerlist @DataDog/container-platform @@ -207,7 +207,7 @@ /cmd/agent/dist/conf.d/oracle-dbm.d/ @DataDog/database-monitoring /cmd/agent/dist/conf.d/network_path.d/ @DataDog/Networks @DataDog/network-device-monitoring /cmd/agent/dist/conf.d/sbom.d/ @DataDog/container-integrations -/cmd/agent/dist/conf.d/snmp.d/ @DataDog/network-device-monitoring +/cmd/agent/dist/conf.d/snmp.d/ @DataDog/ndm-core /cmd/agent/dist/conf.d/win32_event_log.d/ @DataDog/windows-agent /cmd/agent/install*.sh @DataDog/container-ecosystems @DataDog/agent-delivery /cmd/cluster-agent/ @DataDog/container-platform @@ -230,7 +230,7 @@ /cmd/system-probe/modules/eventmonitor* @DataDog/agent-security /cmd/system-probe/modules/tcp_queue_tracer* @DataDog/container-integrations /cmd/system-probe/modules/traceroute* @DataDog/network-device-monitoring @Datadog/Networks -/cmd/system-probe/modules/ping* @DataDog/network-device-monitoring +/cmd/system-probe/modules/ping* @DataDog/ndm-core /cmd/system-probe/modules/language_detection* @DataDog/processes @DataDog/universal-service-monitoring /cmd/system-probe/modules/dynamic_instrumentation* @DataDog/debugger /cmd/system-probe/windows_resources/ @DataDog/windows-kernel-integrations @@ -274,7 +274,7 @@ /omnibus/config/software/datadog-security-agent*.rb @Datadog/agent-security @DataDog/agent-delivery /omnibus/config/software/openscap.rb @DataDog/agent-cspm /omnibus/config/software/sds.rb @DataDog/agent-processing-and-routing -/omnibus/config/software/snmp-traps.rb @DataDog/network-device-monitoring +/omnibus/config/software/snmp-traps.rb @DataDog/ndm-core /omnibus/resources/*/msi/ @DataDog/windows-agent # The following is managed by `inv lint-components` -- DO NOT EDIT @@ -290,13 +290,13 @@ /comp/forwarder @DataDog/agent-processing-and-routing /comp/logs @DataDog/agent-metrics-logs /comp/metadata @DataDog/agent-shared-components -/comp/ndmtmp @DataDog/network-device-monitoring -/comp/netflow @DataDog/network-device-monitoring +/comp/ndmtmp @DataDog/ndm-core +/comp/netflow @DataDog/ndm-integrations /comp/networkpath @DataDog/Networks @DataDog/network-device-monitoring /comp/otelcol @DataDog/opentelemetry /comp/process @DataDog/processes /comp/remote-config @DataDog/remote-config -/comp/snmptraps @DataDog/network-device-monitoring +/comp/snmptraps @DataDog/ndm-core /comp/systray @DataDog/windows-agent /comp/trace @DataDog/agent-apm /comp/updater @DataDog/fleet @DataDog/windows-agent @@ -316,9 +316,9 @@ /comp/autoscaling/datadogclient @DataDog/container-integrations /comp/etw @DataDog/windows-agent /comp/languagedetection/client @DataDog/container-platform -/comp/rdnsquerier @DataDog/network-device-monitoring +/comp/rdnsquerier @DataDog/ndm-integrations /comp/serializer/compression @DataDog/agent-metrics-logs -/comp/snmpscan @DataDog/network-device-monitoring +/comp/snmpscan @DataDog/ndm-core # END COMPONENTS # pkg @@ -354,7 +354,7 @@ /pkg/trace/transform/ @DataDog/opentelemetry /comp/core/autodiscovery/listeners/ @DataDog/container-platform /comp/core/autodiscovery/listeners/cloudfoundry*.go @DataDog/platform-integrations -/comp/core/autodiscovery/listeners/snmp*.go @DataDog/network-device-monitoring +/comp/core/autodiscovery/listeners/snmp*.go @DataDog/ndm-core /comp/core/autodiscovery/providers/ @DataDog/container-platform /comp/core/autodiscovery/providers/file*.go @DataDog/agent-metrics-logs /comp/core/autodiscovery/providers/config_reader*.go @DataDog/container-platform @DataDog/agent-metrics-logs @@ -381,13 +381,13 @@ /pkg/collector/corechecks/embed/apm/ @DataDog/agent-apm /pkg/collector/corechecks/embed/process/ @DataDog/processes /pkg/collector/corechecks/gpu/ @DataDog/ebpf-platform -/pkg/collector/corechecks/network-devices/ @DataDog/network-device-monitoring +/pkg/collector/corechecks/network-devices/ @DataDog/ndm-integrations /pkg/collector/corechecks/orchestrator/ @DataDog/container-app /pkg/collector/corechecks/net/ @DataDog/platform-integrations /pkg/collector/corechecks/oracle @DataDog/database-monitoring /pkg/collector/corechecks/sbom/ @DataDog/container-integrations /pkg/collector/corechecks/servicediscovery/ @DataDog/universal-service-monitoring -/pkg/collector/corechecks/snmp/ @DataDog/network-device-monitoring +/pkg/collector/corechecks/snmp/ @DataDog/ndm-core /pkg/collector/corechecks/system/ @DataDog/platform-integrations /pkg/collector/corechecks/system/**/*_windows*.go @DataDog/platform-integrations @DataDog/windows-agent /pkg/collector/corechecks/system/wincrashdetect/ @DataDog/windows-kernel-integrations @@ -419,7 +419,7 @@ /pkg/flare/*_win.go @Datadog/windows-agent /pkg/flare/*_windows.go @Datadog/windows-agent /pkg/flare/*_windows_test.go @Datadog/windows-agent -/pkg/flare/sysprobe @DataDog/Networks @Datadog/windows-agent @DataDog/processes @DataDog/agent-security @DataDog/universal-service-monitoring @DataDog/ebpf-platform +/pkg/flare/sysprobe @DataDog/Networks @Datadog/windows-agent @DataDog/agent-security @DataDog/universal-service-monitoring @DataDog/ebpf-platform /pkg/fleet/ @DataDog/fleet @DataDog/windows-agent /pkg/pidfile/ @DataDog/agent-shared-components /pkg/persistentcache/ @DataDog/agent-metrics-logs @@ -475,7 +475,7 @@ /pkg/process/metadata/parser/ @DataDog/universal-service-monitoring @DataDog/processes @DataDog/Networks /pkg/process/metadata/parser/*windows* @DataDog/universal-service-monitoring @DataDog/processes @DataDog/Networks @DataDog/windows-kernel-integrations /pkg/process/monitor/ @DataDog/universal-service-monitoring -/pkg/process/net/ @DataDog/universal-service-monitoring @DataDog/processes @DataDog/Networks +/pkg/process/net/ @DataDog/universal-service-monitoring @DataDog/Networks /pkg/process/net/common_windows.go @DataDog/windows-agent /pkg/process/net/windows_pipe.go @DataDog/windows-kernel-integrations /pkg/process/net/windows_pipe_testutil.go @DataDog/windows-kernel-integrations @@ -520,8 +520,8 @@ /pkg/databasemonitoring @DataDog/database-monitoring /pkg/kubestatemetrics @DataDog/container-integrations /pkg/security/ @DataDog/agent-security -/pkg/networkdevice/ @DataDog/network-device-monitoring -/pkg/snmp/ @DataDog/network-device-monitoring +/pkg/networkdevice/ @DataDog/ndm-core +/pkg/snmp/ @DataDog/ndm-core /pkg/tagger/ @DataDog/container-platform /pkg/windowsdriver/ @DataDog/windows-kernel-integrations /comp/core/workloadmeta/collectors/internal/cloudfoundry @DataDog/platform-integrations @@ -576,9 +576,6 @@ /test/kitchen/ @DataDog/agent-devx-loops /test/kitchen/test-definitions/ @DataDog/container-ecosystems @DataDog/agent-delivery /test/kitchen/test/integration/ @DataDog/container-ecosystems @DataDog/agent-delivery -/test/kitchen/site-cookbooks/dd-security-agent-check/ @DataDog/agent-security -/test/kitchen/test/integration/security-agent-stress/ @DataDog/agent-security -/test/kitchen/test/integration/security-agent-test/ @DataDog/agent-security /test/kitchen/site-cookbooks/dd-system-probe-check/ @DataDog/windows-kernel-integrations /test/kitchen/test/integration/win-all-subservices/ @DataDog/windows-agent /test/kitchen/test/integration/win-alt-dir/ @DataDog/windows-agent @@ -589,8 +586,8 @@ /test/kitchen/test/integration/win-repair/ @DataDog/windows-agent /test/kitchen/test/integration/win-user/ @DataDog/windows-agent /test/fakeintake/ @DataDog/agent-e2e-testing @DataDog/agent-devx-loops -/test/fakeintake/aggregator/ndmflowAggregator.go @DataDog/network-device-monitoring -/test/fakeintake/aggregator/ndmflowAggregator_test.go @DataDog/network-device-monitoring +/test/fakeintake/aggregator/ndmflowAggregator.go @DataDog/ndm-integrations +/test/fakeintake/aggregator/ndmflowAggregator_test.go @DataDog/ndm-integrations /test/fakeintake/aggregator/servicediscovery* @DataDog/universal-service-monitoring /test/new-e2e/ @DataDog/agent-e2e-testing @DataDog/agent-devx-loops /test/new-e2e/pkg/components/datadog-installer @DataDog/windows-agent @@ -603,7 +600,8 @@ /test/new-e2e/tests/containers @DataDog/container-integrations @DataDog/container-platform /test/new-e2e/tests/discovery @DataDog/universal-service-monitoring /test/new-e2e/tests/language-detection @DataDog/processes -/test/new-e2e/tests/ndm @DataDog/network-device-monitoring +/test/new-e2e/tests/ndm @DataDog/ndm-core +/test/new-e2e/tests/ndm/netflow @DataDog/ndm-integrations /test/new-e2e/tests/npm @DataDog/Networks /test/new-e2e/tests/npm/ec2_1host_wkit_test.go @DataDog/Networks @DataDog/windows-kernel-integrations /test/new-e2e/tests/orchestrator @DataDog/container-app diff --git a/.github/workflows/buildimages-update.yml b/.github/workflows/buildimages-update.yml index 88c45417e33a3..01e46eaac3d34 100644 --- a/.github/workflows/buildimages-update.yml +++ b/.github/workflows/buildimages-update.yml @@ -83,11 +83,11 @@ jobs: - name: Update buildimages IDs and Go version id: update_build_images env: - TEST_VERSION_FLAG: ${{ inputs.test_version && '--test-version' || '--no-test-version' }} + TEST_VERSION_FLAG: ${{ inputs.test_version && '--test' || '--no-test' }} INCLUDE_OTEL_MODULES: ${{ inputs.include_otel_modules && '--include-otel-modules' || '' }} run: | if [ "${{ steps.current_go_version.outputs.GO_VERSION }}" = "${{ inputs.go_version }}" ]; then - inv -e buildimages.update --image-tag ${{ inputs.images_id }} $TEST_VERSION_FLAG + inv -e buildimages.update --tag ${{ inputs.images_id }} $TEST_VERSION_FLAG echo 'MESSAGE=Update buildimages ID to ${{ inputs.images_id }}' >> $GITHUB_OUTPUT else inv -e update-go --image-tag ${{ inputs.images_id }} $TEST_VERSION_FLAG $INCLUDE_OTEL_MODULES -v "${{ inputs.go_version }}" @@ -140,7 +140,7 @@ jobs: ${{ inputs.images_id }} \ ${{ steps.current_go_version.outputs.GO_VERSION }} \ ${{ inputs.go_version }} \ - ${{ inputs.test_version && '--test-version' || '' }} > $TMP_PR_BODY_PATH + ${{ inputs.test_version && '--test' || '' }} > $TMP_PR_BODY_PATH # Create the PR gh pr create \ diff --git a/.github/workflows/chase_release_managers.yml b/.github/workflows/chase_release_managers.yml index c1a4cff2baad0..66bacdd751fc8 100644 --- a/.github/workflows/chase_release_managers.yml +++ b/.github/workflows/chase_release_managers.yml @@ -32,5 +32,6 @@ jobs: ATLASSIAN_USERNAME : ${{ secrets.ATLASSIAN_USERNAME }} ATLASSIAN_PASSWORD : ${{ secrets.ATLASSIAN_PASSWORD }} SLACK_API_TOKEN : ${{ secrets.SLACK_DATADOG_AGENT_BOT_TOKEN }} + VERSION: ${{ github.event.inputs.version }} run: | - inv -e release.chase-release-managers --version ${{ github.event.inputs.version }} + inv -e release.chase-release-managers --version "$VERSION" diff --git a/.github/workflows/code_review_complexity.yml b/.github/workflows/code_review_complexity.yml new file mode 100644 index 0000000000000..9ba527ec1fd9f --- /dev/null +++ b/.github/workflows/code_review_complexity.yml @@ -0,0 +1,36 @@ +--- +name: "PR complexity label" + +on: + pull_request: + types: [opened, synchronize, reopened] + branches: + - main + - "[0-9]+.[0-9]+.x" + pull_request_review_comment: + types: [created, deleted] + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +permissions: {} +jobs: + codereview-complexity: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - name: Setup python + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + with: + python-version: 3.12 + cache: 'pip' + cache-dependency-path: '**/requirements*.txt' + - name: Install dependencies + run: pip install -r requirements.txt -r tasks/requirements.txt + - name: Check code review complexity + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + run: inv -e github.assign-codereview-label --pr-id="$PR_NUMBER" diff --git a/.github/workflows/create_rc_pr.yml b/.github/workflows/create_rc_pr.yml index bd40afbf6e315..f0576c65084c9 100644 --- a/.github/workflows/create_rc_pr.yml +++ b/.github/workflows/create_rc_pr.yml @@ -82,8 +82,10 @@ jobs: ATLASSIAN_USERNAME: ${{ secrets.ATLASSIAN_USERNAME }} ATLASSIAN_PASSWORD: ${{ secrets.ATLASSIAN_PASSWORD }} SLACK_API_TOKEN : ${{ secrets.SLACK_DATADOG_AGENT_BOT_TOKEN }} + MATRIX: ${{ matrix.value }} + WARNING: ${{ needs.find_release_branches.outputs.warning }} run: | - echo "CHANGES=$(inv -e release.check-for-changes -r ${{ matrix.value }} ${{ needs.find_release_branches.outputs.warning }})" >> $GITHUB_OUTPUT + echo "CHANGES=$(inv -e release.check-for-changes -r "$MATRIX" "$WARNING")" >> $GITHUB_OUTPUT - name: Create RC PR if: ${{ steps.check_for_changes.outputs.CHANGES == 'true'}} diff --git a/.github/workflows/create_release_schedule.yml b/.github/workflows/create_release_schedule.yml index 4f674987ecf05..3be6f95c9658c 100644 --- a/.github/workflows/create_release_schedule.yml +++ b/.github/workflows/create_release_schedule.yml @@ -36,5 +36,7 @@ jobs: env: ATLASSIAN_USERNAME : ${{ secrets.ATLASSIAN_USERNAME }} ATLASSIAN_PASSWORD : ${{ secrets.ATLASSIAN_PASSWORD }} + INPUT_VERSION: ${{ github.event.inputs.version }} + FREEZE_DATE: ${{ github.event.inputs.freeze_date }} run: | - inv -e release.create-schedule --version ${{ github.event.inputs.version }} --freeze-date ${{ github.event.inputs.freeze_date }} + inv -e release.create-schedule --version "$INPUT_VERSION" --freeze-date "$FREEZE_DATE" diff --git a/.github/workflows/cws-btfhub-sync.yml b/.github/workflows/cws-btfhub-sync.yml index e5fe407c6307b..efbb9c24bb782 100644 --- a/.github/workflows/cws-btfhub-sync.yml +++ b/.github/workflows/cws-btfhub-sync.yml @@ -81,8 +81,11 @@ jobs: echo "ARTIFACT_NAME=constants-${{ matrix.cone }}" | tr '/' '-' >> $GITHUB_OUTPUT - name: Sync constants + env: + ARTIFACT_NAME: ${{ steps.artifact-name.outputs.ARTIFACT_NAME }} + FORCE_REFRESH: ${{ inputs.force_refresh && '--force-refresh' || '' }} run: | - inv -e security-agent.generate-btfhub-constants --archive-path=./dev/dist/archive --output-path=./${{ steps.artifact-name.outputs.ARTIFACT_NAME }}.json ${{ inputs.force_refresh && '--force-refresh' || '' }} + inv -e security-agent.generate-btfhub-constants --archive-path=./dev/dist/archive --output-path=./"$ARTIFACT_NAME".json "$FORCE_REFRESH" - name: Upload artifact uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 @@ -140,6 +143,9 @@ jobs: skip_checkout: true - name: Create Pull Request + env: + BRANCH_NAME: ${{ steps.branch-name.outputs.BRANCH_NAME }} + BASE_BRANCH: ${{ inputs.base_branch || 'main' }} uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 if: steps.commit-creator.outputs.changes_detected == 'true' with: @@ -149,8 +155,8 @@ jobs: title: 'CWS: sync BTFHub constants', owner, repo, - head: '${{ steps.branch-name.outputs.BRANCH_NAME }}', - base: '${{ inputs.base_branch || 'main' }}', + head: "$BRANCH_NAME", + base: "$BASE_BRANCH", body: [ '### What does this PR do?', 'This PR syncs the BTFHub constants used by CWS', diff --git a/.github/workflows/go_mod_tidy.yml b/.github/workflows/go_mod_tidy.yml index a01b9d29ad803..95ad7719e2da3 100644 --- a/.github/workflows/go_mod_tidy.yml +++ b/.github/workflows/go_mod_tidy.yml @@ -22,9 +22,10 @@ jobs: - name: Checkout PR # run only if triggered manually, otherwise we are already on the right branch and we won't have `pr_number` if: ${{ github.event_name == 'workflow_dispatch' }} - run: gh pr checkout ${{ github.event.inputs.pr_number }} + run: gh pr checkout "$PR_NUMBER" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.inputs.pr_number }} - name: Install go uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 with: @@ -51,5 +52,7 @@ jobs: with: commit_message: Auto-generate go.sum and LICENSE-3rdparty.csv changes - name: changes + env: + CHANGES: ${{ steps.autocommit.outputs.changes_detected }} run: | - echo "Changes detected: ${{ steps.autocommit.outputs.changes_detected }}" + echo "Changes detected: $CHANGES" diff --git a/.github/workflows/label-analysis.yml b/.github/workflows/label-analysis.yml index 29f35d223e758..f6801b956028b 100644 --- a/.github/workflows/label-analysis.yml +++ b/.github/workflows/label-analysis.yml @@ -33,7 +33,9 @@ jobs: - name: Install dependencies run: pip install -r requirements.txt -r tasks/requirements.txt - name: Auto assign team label - run: inv -e github.assign-team-label --pr-id='${{ github.event.pull_request.number }}' + env: + PR_ID: ${{ github.event.pull_request.number }} + run: inv -e github.assign-team-label --pr-id="$PR_ID" release-note-check: if: github.triggering_actor != 'dd-devflow[bot]' runs-on: ubuntu-latest @@ -63,10 +65,13 @@ jobs: LABELS: ${{ steps.pr-labels.outputs.LABELS }} steps: - name: Get PR labels + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + EVENT_NUMBER: ${{ github.event.number }} id: pr-labels run: | - labels="$(gh pr view '${{ github.event.pull_request.number }}' --json labels --jq '[.labels[].name] | (join(" "))')" - echo "Fetched labels for PR ${{github.event.number}}: $labels" + labels="$(gh pr view "$PR_NUMBER" --json labels --jq '[.labels[].name] | (join(" "))')" + echo "Fetched labels for PR $EVENT_NUMBER: $labels" echo "LABELS=$labels" >> "$GITHUB_OUTPUT" team-label-check: needs: fetch-labels diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8d0e021acbd81..164e21e121bde 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -181,6 +181,41 @@ variables: DATADOG_AGENT_SYSPROBE_BUILDIMAGES: v47046711-76471b8e DATADOG_AGENT_BTF_GEN_BUILDIMAGES_SUFFIX: "" DATADOG_AGENT_BTF_GEN_BUILDIMAGES: v47046711-76471b8e + # New images to enable different version per image - not used yet + CI_IMAGE_BTF_GEN: v47046711-76471b8e + CI_IMAGE_BTF_GEN_SUFFIX: "" + CI_IMAGE_DEB_X64: v47046711-76471b8e + CI_IMAGE_DEB_X64_SUFFIX: "" + CI_IMAGE_DEB_ARM64: v47046711-76471b8e + CI_IMAGE_DEB_ARM64_SUFFIX: "" + CI_IMAGE_DEB_ARMHF: v47046711-76471b8e + CI_IMAGE_DEB_ARMHF_SUFFIX: "" + CI_IMAGE_DD_AGENT_TESTING: v47046711-76471b8e + CI_IMAGE_DD_AGENT_TESTING_SUFFIX: "" + CI_IMAGE_DOCKER_X64: v47046711-76471b8e + CI_IMAGE_DOCKER_X64_SUFFIX: "" + CI_IMAGE_DOCKER_ARM64: v47046711-76471b8e + CI_IMAGE_DOCKER_ARM64_SUFFIX: "" + CI_IMAGE_GITLAB_AGENT_DEPLOY: v47046711-76471b8e + CI_IMAGE_GITLAB_AGENT_DEPLOY_SUFFIX: "" + CI_IMAGE_LINUX_GLIBC_2_17_X64: v47046711-76471b8e + CI_IMAGE_LINUX_GLIBC_2_17_X64_SUFFIX: "" + CI_IMAGE_LINUX_GLIBC_2_23_ARM64: v47046711-76471b8e + CI_IMAGE_LINUX_GLIBC_2_23_ARM64_SUFFIX: "" + CI_IMAGE_SYSTEM_PROBE_X64: v47046711-76471b8e + CI_IMAGE_SYSTEM_PROBE_X64_SUFFIX: "" + CI_IMAGE_SYSTEM_PROBE_ARM64: v47046711-76471b8e + CI_IMAGE_SYSTEM_PROBE_ARM64_SUFFIX: "" + CI_IMAGE_RPM_X64: v47046711-76471b8e + CI_IMAGE_RPM_X64_SUFFIX: "" + CI_IMAGE_RPM_ARM64: v47046711-76471b8e + CI_IMAGE_RPM_ARM64_SUFFIX: "" + CI_IMAGE_RPM_ARMHF: v47046711-76471b8e + CI_IMAGE_RPM_ARMHF_SUFFIX: "" + CI_IMAGE_WIN_1809_X64: v47046711-76471b8e + CI_IMAGE_WIN_1809_X64_SUFFIX: "" + CI_IMAGE_WIN_LTSC2022_X64: v47046711-76471b8e + CI_IMAGE_WIN_LTSC2022_X64_SUFFIX: "" DATADOG_AGENT_EMBEDDED_PATH: /opt/datadog-agent/embedded DEB_GPG_KEY_ID: c0962c7d @@ -706,9 +741,6 @@ workflow: - pkg/ebpf/**/* - pkg/security/**/* - pkg/eventmonitor/**/* - - test/kitchen/site-cookbooks/dd-security-agent-check/**/* - - test/kitchen/test/integration/security-agent-test/**/* - - test/kitchen/test/integration/security-agent-stress/**/* - .gitlab/kernel_matrix_testing/security_agent.yml - .gitlab/kernel_matrix_testing/common.yml - .gitlab/source_test/ebpf.yml diff --git a/.gitlab/choco_build/choco_build.yml b/.gitlab/choco_build/choco_build.yml index 61be7eb6e75bd..d8f125fc7d8e4 100644 --- a/.gitlab/choco_build/choco_build.yml +++ b/.gitlab/choco_build/choco_build.yml @@ -23,24 +23,32 @@ windows_choco_offline_7_x64: paths: - omnibus/pkg -# The online version of the choco job fetches the msi package from S3 so -# it is run only once the msi package is pushed +# The online version of the choco job gets the msi package through the gitlab artifacts windows_choco_online_7_x64: rules: - !reference [.on_deploy_stable_or_beta_repo_branch_manual] + !reference [.on_deploy_stable_or_beta_repo_branch] stage: choco_and_install_script_build tags: ["runner:windows-docker", "windowsversion:1809"] - needs: ["deploy_staging_windows_tags-7"] + needs: ["deploy_packages_windows-x64-7"] variables: ARCH: "x64" script: - '$_instance_id = (iwr -UseBasicParsing http://169.254.169.254/latest/meta-data/instance-id).content ; Write-Host "Running on instance $($_instance_id)"' - $ErrorActionPreference = "Stop" - - if (Test-Path .omnibus) { remove-item -recurse -force .omnibus } + - mkdir temp\ + - copy omnibus\pkg\*.msi temp\ + - if (Test-Path omnibus) { remove-item -recurse -force omnibus } - if (Test-Path build-out) { remove-item -recurse -force build-out } - mkdir omnibus\pkg - - docker run --rm -v "$(Get-Location):c:\mnt" 486234852809.dkr.ecr.us-east-1.amazonaws.com/ci/datadog-agent-buildimages/windows_1809_${ARCH}${Env:DATADOG_AGENT_WINBUILDIMAGES_SUFFIX}:${Env:DATADOG_AGENT_WINBUILDIMAGES} c:\mnt\tasks\winbuildscripts\chocopack.bat online + - > + docker run --rm + -v "$(Get-Location):c:\mnt" + -e CI_PIPELINE_ID=${CI_PIPELINE_ID} + -e BUCKET_BRANCH="$BUCKET_BRANCH" + 486234852809.dkr.ecr.us-east-1.amazonaws.com/ci/datadog-agent-buildimages/windows_1809_${ARCH}${Env:DATADOG_AGENT_WINBUILDIMAGES_SUFFIX}:${Env:DATADOG_AGENT_WINBUILDIMAGES} + c:\mnt\tasks\winbuildscripts\chocopack.bat online c:\mnt\temp - If ($lastExitCode -ne "0") { throw "Previous command returned $lastExitCode" } + - Remove-Item -Path "temp\" -Recurse -Force - copy build-out\*.nupkg omnibus\pkg - $CopyNupkgToS3 = "$S3_CP_CMD --recursive --exclude '*' --include '*.nupkg' build-out $S3_RELEASE_ARTIFACTS_URI/choco/nupkg" - Invoke-Expression $CopyNupkgToS3 diff --git a/.gitlab/deploy_packages/windows.yml b/.gitlab/deploy_packages/windows.yml index a5b10e40d712d..42280d4e22027 100644 --- a/.gitlab/deploy_packages/windows.yml +++ b/.gitlab/deploy_packages/windows.yml @@ -18,6 +18,9 @@ deploy_packages_windows-x64-7: --include "datadog-agent-7*.msi" --include "datadog-agent-7*.debug.zip" $OMNIBUS_PACKAGE_DIR $S3_RELEASE_ARTIFACTS_URI/msi/x86_64/ + artifacts: + paths: + - $OMNIBUS_PACKAGE_DIR deploy_staging_windows_tags-7: rules: diff --git a/.gitlab/functional_test/regression_detector.yml b/.gitlab/functional_test/regression_detector.yml index ec44f3d9fc9ed..d4be7a0957cad 100644 --- a/.gitlab/functional_test/regression_detector.yml +++ b/.gitlab/functional_test/regression_detector.yml @@ -5,7 +5,7 @@ single-machine-performance-regression_detector: - !reference [.except_main_or_release_branch] - when: on_success image: 486234852809.dkr.ecr.us-east-1.amazonaws.com/ci/datadog-agent-buildimages/docker_x64$DATADOG_AGENT_BUILDIMAGES_SUFFIX:$DATADOG_AGENT_BUILDIMAGES - tags: ["runner:docker"] + tags: ["arch:amd64"] needs: - job: single_machine_performance-amd64-a7 artifacts: false @@ -76,7 +76,7 @@ single-machine-performance-regression_detector: - echo "Commit ${BASELINE_SHA} is recent enough" - echo "Checking if image exists for commit ${BASELINE_SHA}..." - | - while [[ ! $(aws ecr describe-images --profile single-machine-performance --registry-id "${SMP_ACCOUNT_ID}" --repository-name "${SMP_AGENT_TEAM_ID}-agent" --image-ids imageTag="${BASELINE_SHA}-7-amd64") ]] + while [[ ! $(aws ecr describe-images --region us-west-2 --profile single-machine-performance --registry-id "${SMP_ACCOUNT_ID}" --repository-name "${SMP_AGENT_TEAM_ID}-agent" --image-ids imageTag="${BASELINE_SHA}-7-amd64") ]] do echo "No image exists for ${BASELINE_SHA} - checking predecessor of ${BASELINE_SHA} next" BASELINE_SHA=$(git rev-parse ${BASELINE_SHA}^) diff --git a/.gitlab/functional_test/serverless.yml b/.gitlab/functional_test/serverless.yml index 039a7eb029884..62bc0ae0555d7 100644 --- a/.gitlab/functional_test/serverless.yml +++ b/.gitlab/functional_test/serverless.yml @@ -4,7 +4,7 @@ serverless_cold_start_performance-deb_x64: - !reference [.except_mergequeue] - when: on_success image: 486234852809.dkr.ecr.us-east-1.amazonaws.com/ci/datadog-agent-buildimages/docker_x64$DATADOG_AGENT_BUILDIMAGES_SUFFIX:$DATADOG_AGENT_BUILDIMAGES - tags: ["runner:docker"] + tags: ["runner:docker"] # Still required as compute.sh is doing a container run needs: ["go_deps", "build_serverless-deb_x64"] before_script: - !reference [.retrieve_linux_go_deps] @@ -14,4 +14,4 @@ serverless_cold_start_performance-deb_x64: - cp test/integration/serverless_perf/* /tmp/serverless-ci - cd /tmp/serverless-ci # Docker does not like syslinks, that's why it's easier to build the image in /tmp - docker build -t datadogci/lambda-extension . - - ./compute.sh \ No newline at end of file + - ./compute.sh diff --git a/.gitlab/integration_test/linux.yml b/.gitlab/integration_test/linux.yml index 73a4f52e32112..a260fd6d30372 100644 --- a/.gitlab/integration_test/linux.yml +++ b/.gitlab/integration_test/linux.yml @@ -3,6 +3,7 @@ needs: ["go_deps", "go_tools_deps"] rules: - !reference [.except_mergequeue] + - when: on_success image: 486234852809.dkr.ecr.us-east-1.amazonaws.com/ci/datadog-agent-buildimages/deb_x64$DATADOG_AGENT_BUILDIMAGES_SUFFIX:$DATADOG_AGENT_BUILDIMAGES tags: ["docker-in-docker:amd64"] before_script: diff --git a/.gitlab/integration_test/otel.yml b/.gitlab/integration_test/otel.yml index 9b372bc8f6766..21ef2098a789f 100644 --- a/.gitlab/integration_test/otel.yml +++ b/.gitlab/integration_test/otel.yml @@ -27,7 +27,7 @@ docker_image_build_otel: stage: integration_test image: 486234852809.dkr.ecr.us-east-1.amazonaws.com/ci/datadog-agent-buildimages/docker_x64$DATADOG_AGENT_BUILDIMAGES_SUFFIX:$DATADOG_AGENT_BUILDIMAGES needs: ["go_deps","integration_tests_otel"] - tags: ["runner:docker"] + tags: ["runner:docker"] # Still required because the otel_agent_build_tests.py is doing a container run before_script: - !reference [.retrieve_linux_go_deps] - mkdir -p /tmp/otel-ci diff --git a/.gitlab/internal_image_deploy/internal_image_deploy.yml b/.gitlab/internal_image_deploy/internal_image_deploy.yml index 58bfebfa2bd87..de908856c4dda 100644 --- a/.gitlab/internal_image_deploy/internal_image_deploy.yml +++ b/.gitlab/internal_image_deploy/internal_image_deploy.yml @@ -94,7 +94,7 @@ docker_trigger_internal-ot: docker_trigger_cluster_agent_internal: stage: internal_image_deploy - rules: !reference [.on_deploy] + rules: !reference [.on_deploy_internal_or_manual] needs: - job: docker_build_cluster_agent_amd64 artifacts: false diff --git a/.gitlab/internal_kubernetes_deploy/internal_kubernetes_deploy.yml b/.gitlab/internal_kubernetes_deploy/internal_kubernetes_deploy.yml index 792b7e727b537..dda2aa13eb56c 100644 --- a/.gitlab/internal_kubernetes_deploy/internal_kubernetes_deploy.yml +++ b/.gitlab/internal_kubernetes_deploy/internal_kubernetes_deploy.yml @@ -24,6 +24,8 @@ internal_kubernetes_deploy_experimental: artifacts: false - job: docker_trigger_cluster_agent_internal artifacts: false + - job: deploy_packages_windows-x64-7 + artifacts: false - job: k8s-e2e-main # Currently only require container Argo workflow artifacts: false optional: true diff --git a/.gitlab/internal_kubernetes_deploy/rc_kubernetes_deploy.yml b/.gitlab/internal_kubernetes_deploy/rc_kubernetes_deploy.yml index 3f880e8cb0ac6..79212136a42ee 100644 --- a/.gitlab/internal_kubernetes_deploy/rc_kubernetes_deploy.yml +++ b/.gitlab/internal_kubernetes_deploy/rc_kubernetes_deploy.yml @@ -6,6 +6,9 @@ rc_kubernetes_deploy: stage: internal_kubernetes_deploy rules: - if: $RC_K8S_DEPLOYMENTS == "true" + when: on_success + - if: $RC_BUILD == "true" + when: manual needs: - job: docker_trigger_internal artifacts: false diff --git a/.gitlab/kernel_matrix_testing/common.yml b/.gitlab/kernel_matrix_testing/common.yml index 9768897240102..9f39da153596b 100644 --- a/.gitlab/kernel_matrix_testing/common.yml +++ b/.gitlab/kernel_matrix_testing/common.yml @@ -154,7 +154,7 @@ - pulumi login $(cat $STACK_DIR | tr -d '\n') # Each VM gets 12GB of memory. We have set 8GB as base for the system, and upto 4GB can be used # by a ram backed filesystem holding the system-probe test packages - - inv -e kmt.gen-config --ci --arch=$ARCH --output-file=$VMCONFIG_FILE --sets=$TEST_SETS --vmconfig-template=$TEST_COMPONENT --memory=12288 + - inv -e kmt.gen-config --ci --arch=$ARCH --output-file=$VMCONFIG_FILE --vmconfig-template=$TEST_COMPONENT --memory=12288 - inv -e system-probe.start-microvms --provision-instance --provision-microvms --vmconfig=$VMCONFIG_FILE $INSTANCE_TYPE_ARG $AMI_ID_ARG --ssh-key-name=$AWS_EC2_SSH_KEY_NAME --ssh-key-path=$AWS_EC2_SSH_KEY_FILE --infra-env=$INFRA_ENV --stack-name=kernel-matrix-testing-${TEST_COMPONENT}-${ARCH}-${CI_PIPELINE_ID} --run-agent - jq "." $CI_PROJECT_DIR/stack.output - pulumi logout diff --git a/.gitlab/kernel_matrix_testing/security_agent.yml b/.gitlab/kernel_matrix_testing/security_agent.yml index 63760809cdeab..308eba0978aff 100644 --- a/.gitlab/kernel_matrix_testing/security_agent.yml +++ b/.gitlab/kernel_matrix_testing/security_agent.yml @@ -32,7 +32,6 @@ kmt_setup_env_secagent_arm64: AMI_ID_ARG: "--arm-ami-id=$KERNEL_MATRIX_TESTING_ARM_AMI_ID" LibvirtSSHKey: $CI_PROJECT_DIR/libvirt_rsa-arm TEST_COMPONENT: security-agent - TEST_SETS: cws_host,cws_docker,cws_ad,cws_el,cws_el_ns,cws_fentry kmt_setup_env_secagent_x64: extends: @@ -45,7 +44,6 @@ kmt_setup_env_secagent_x64: AMI_ID_ARG: "--x86-ami-id=$KERNEL_MATRIX_TESTING_X86_AMI_ID" LibvirtSSHKey: $CI_PROJECT_DIR/libvirt_rsa-x86 TEST_COMPONENT: security-agent - TEST_SETS: cws_host,cws_docker,cws_ad,cws_el,cws_el_ns,cws_fentry .upload_secagent_tests: stage: kernel_matrix_testing_prepare @@ -131,6 +129,7 @@ kmt_run_secagent_tests_x64: - "ubuntu_22.04" - "ubuntu_23.10" - "ubuntu_24.04" + - "ubuntu_24.10" - "amazon_4.14" - "amazon_5.4" - "amazon_5.10" @@ -232,6 +231,7 @@ kmt_run_secagent_tests_x64_docker: - "ubuntu_22.04" - "ubuntu_23.10" - "ubuntu_24.04" + - "ubuntu_24.10" - "amazon_4.14" - "amazon_5.4" - "amazon_5.10" @@ -268,6 +268,7 @@ kmt_run_secagent_tests_arm64: - "ubuntu_22.04" - "ubuntu_23.10" - "ubuntu_24.04" + - "ubuntu_24.10" - "amazon_5.4" - "amazon_5.10" - "amazon_2023" @@ -362,6 +363,7 @@ kmt_run_secagent_tests_arm64_docker: - "ubuntu_22.04" - "ubuntu_23.10" - "ubuntu_24.04" + - "ubuntu_24.10" - "amazon_5.4" - "amazon_5.10" - "amazon_2023" diff --git a/.gitlab/kernel_matrix_testing/system_probe.yml b/.gitlab/kernel_matrix_testing/system_probe.yml index 7b16017409d4b..af39dcb606af5 100644 --- a/.gitlab/kernel_matrix_testing/system_probe.yml +++ b/.gitlab/kernel_matrix_testing/system_probe.yml @@ -122,7 +122,6 @@ kmt_setup_env_sysprobe_arm64: AMI_ID_ARG: "--arm-ami-id=$KERNEL_MATRIX_TESTING_ARM_AMI_ID" LibvirtSSHKey: $CI_PROJECT_DIR/libvirt_rsa-arm TEST_COMPONENT: system-probe - TEST_SETS: "only_usm,no_usm" kmt_setup_env_sysprobe_x64: extends: @@ -135,7 +134,6 @@ kmt_setup_env_sysprobe_x64: AMI_ID_ARG: "--x86-ami-id=$KERNEL_MATRIX_TESTING_X86_AMI_ID" LibvirtSSHKey: $CI_PROJECT_DIR/libvirt_rsa-x86 TEST_COMPONENT: system-probe - TEST_SETS: "only_usm,no_usm" .upload_sysprobe_tests: stage: kernel_matrix_testing_prepare diff --git a/.gitlab/source_test/ebpf.yml b/.gitlab/source_test/ebpf.yml index 012406f1b85aa..53ea5c6506f2f 100644 --- a/.gitlab/source_test/ebpf.yml +++ b/.gitlab/source_test/ebpf.yml @@ -94,7 +94,6 @@ prepare_sysprobe_ebpf_functional_tests_x64: - mkdir -p /opt/datadog-agent/embedded/bin - cp /tmp/clang-bpf /opt/datadog-agent/embedded/bin/clang-bpf - cp /tmp/llc-bpf /opt/datadog-agent/embedded/bin/llc-bpf - - invoke -e security-agent.kitchen-prepare --skip-linters prepare_secagent_ebpf_functional_tests_arm64: extends: .prepare_secagent_ebpf_functional_tests diff --git a/.gitlab/source_test/windows.yml b/.gitlab/source_test/windows.yml index 300b9698dfce4..c8b2bb87fc334 100644 --- a/.gitlab/source_test/windows.yml +++ b/.gitlab/source_test/windows.yml @@ -110,7 +110,7 @@ tests_windows-x64: artifacts: when: always paths: - - $DD_AGENT_TESTING_DIR/site-cookbooks/dd-security-agent-check/files + - $CI_PROJECT_DIR/test/new-e2e/tests/security-agent-functional/artifacts tests_windows_sysprobe_x64: extends: .tests_windows_sysprobe diff --git a/.mockery.yaml b/.mockery.yaml index e7ab03ecdb3cc..6c27a8317f752 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -46,7 +46,7 @@ packages: - github.com/DataDog/datadog-agent/pkg/serializer/types.stubMessageBody=github.com/DataDog/datadog-agent/pkg/serializer/types.ProcessMessageBody # gpu - github.com/DataDog/datadog-agent/pkg/collector/corechecks/gpu/nvmlmetrics: + github.com/DataDog/datadog-agent/pkg/collector/corechecks/gpu/nvidia: interfaces: Collector: config: @@ -56,5 +56,5 @@ packages: inpackage: true dir: "{{.InterfaceDir}}" filename: "mocks.go" - outpkg: nvmlmetrics + outpkg: nvidia mockname: mockCollector diff --git a/Dockerfiles/agent/windows/README.md b/Dockerfiles/agent/windows/README.md index 33330e1574a0b..e33eeda9bd4e0 100644 --- a/Dockerfiles/agent/windows/README.md +++ b/Dockerfiles/agent/windows/README.md @@ -9,10 +9,6 @@ From the root of the repository, run the following command: docker run --rm -it -v "${pwd}:c:\mnt" -e OMNIBUS_TARGET=main -e MAJOR_VERSION=7 -e RELEASE_VERSION=nightly -e PY_RUNTIMES=3 datadog/agent-buildimages-windows_x64:1809 c:\mnt\tasks\winbuildscripts\buildwin.bat ``` -The above will build the Agent 7 nightly. To build the Agent 6, use the following variables: -- MAJOR_VERSION=6 -- PY_RUNTIMES=2,3 - The build artifacts will be in `omnibus\pkg`. 2. Build the entrypoint diff --git a/Dockerfiles/dogstatsd/alpine/Dockerfile b/Dockerfiles/dogstatsd/alpine/Dockerfile index 8d14ac6203e05..8151dce3b0110 100644 --- a/Dockerfiles/dogstatsd/alpine/Dockerfile +++ b/Dockerfiles/dogstatsd/alpine/Dockerfile @@ -1,5 +1,5 @@ ARG BASE_IMAGE_ALPINE_VERSION=3.18 -FROM alpine:$BASE_IMAGE_ALPINE_VERSION +FROM public.ecr.aws/docker/library/alpine:$BASE_IMAGE_ALPINE_VERSION ARG TARGETARCH ARG BASE_IMAGE_ALPINE_VERSION ARG DD_GIT_REPOSITORY_URL diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index 3598029cfb93b..4f2769d0a0eec 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -1160,6 +1160,7 @@ core,github.com/google/gofuzz/bytesource,Apache-2.0,Copyright 2014 Google Inc. A core,github.com/google/gopacket,BSD-3-Clause,"Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. | Copyright (c) 2012 Google, Inc. All rights reserved." core,github.com/google/gopacket/afpacket,BSD-3-Clause,"Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. | Copyright (c) 2012 Google, Inc. All rights reserved." core,github.com/google/gopacket/layers,BSD-3-Clause,"Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. | Copyright (c) 2012 Google, Inc. All rights reserved." +core,github.com/google/gopacket/pcap,BSD-3-Clause,"Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. | Copyright (c) 2012 Google, Inc. All rights reserved." core,github.com/google/gopacket/pcapgo,BSD-3-Clause,"Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. | Copyright (c) 2012 Google, Inc. All rights reserved." core,github.com/google/licenseclassifier/v2,Apache-2.0,Copyright 2017 Google LLC All Rights Reserved. | Copyright 2020 Google LLC All Rights Reserved. core,github.com/google/licenseclassifier/v2/assets,Apache-2.0,Copyright 2017 Google LLC All Rights Reserved. | Copyright 2020 Google LLC All Rights Reserved. @@ -1939,6 +1940,7 @@ core,github.com/prometheus/prometheus/util/osutil,Apache-2.0,Copyright 2012-2015 core,github.com/prometheus/prometheus/util/pool,Apache-2.0,Copyright 2012-2015 The Prometheus Authors core,github.com/prometheus/prometheus/util/strutil,Apache-2.0,Copyright 2012-2015 The Prometheus Authors core,github.com/prometheus/prometheus/util/treecache,Apache-2.0,Copyright 2012-2015 The Prometheus Authors +core,github.com/puzpuzpuz/xsync/v3,Apache-2.0,Copyright (c) 2021 Andrey Pechkurov core,github.com/rcrowley/go-metrics,BSD-2-Clause-Views,Copyright 2012 Richard Crowley. All rights reserved core,github.com/redis/go-redis/v9,BSD-2-Clause,Copyright (c) 2013 The github.com/redis/go-redis Authors core,github.com/redis/go-redis/v9/internal,BSD-2-Clause,Copyright (c) 2013 The github.com/redis/go-redis Authors diff --git a/README.md b/README.md index 7f40e410c1b4f..ab137bbe48339 100644 --- a/README.md +++ b/README.md @@ -51,17 +51,10 @@ To start working on the Agent, you can build the `main` branch: 4. Create a development `datadog.yaml` configuration file in `dev/dist/datadog.yaml`, containing a valid API key: `api_key: `. You can either start with an empty one or use the full one generated by the Agent build from Step 5 (located in `cmd/agent/dist/datadog.yaml` after the build finishes). 5. Build the agent with `invoke agent.build --build-exclude=systemd`. - By default, the Agent will be built to use Python 3 but you can select which Python version you want to use: - - - `invoke agent.build --python-runtimes 2` for Python2 only - - `invoke agent.build --python-runtimes 3` for Python3 only - - `invoke agent.build --python-runtimes 2,3` for both Python2 and Python3 - You can specify a custom Python location for the agent (useful when using virtualenvs): invoke agent.build \ - --python-runtimes 2,3 \ --python-home-2=$GOPATH/src/github.com/DataDog/datadog-agent/venv2 \ --python-home-3=$GOPATH/src/github.com/DataDog/datadog-agent/venv3 diff --git a/cmd/agent/subcommands/diagnose/command.go b/cmd/agent/subcommands/diagnose/command.go index 46f9ccea0e730..5b8e50a432a9f 100644 --- a/cmd/agent/subcommands/diagnose/command.go +++ b/cmd/agent/subcommands/diagnose/command.go @@ -98,7 +98,6 @@ func Commands(globalParams *command.GlobalParams) []*cobra.Command { workloadmetafx.Module(workloadmeta.Params{ AgentType: workloadmeta.NodeAgent, InitHelper: common.GetWorkloadmetaInit(), - NoInstance: !cliParams.runLocal, }), fx.Supply(optional.NewNoneOption[collector.Component]()), taggerimpl.Module(), @@ -287,6 +286,7 @@ func cmdDiagnose(cliParams *cliParams, ac autodiscovery.Component, secretResolver secrets.Component, _ log.Component, + tagger tagger.Component, ) error { diagCfg := diagnosis.Config{ Verbose: cliParams.verbose, @@ -303,7 +303,7 @@ func cmdDiagnose(cliParams *cliParams, return nil } - diagnoseDeps := diagnose.NewSuitesDepsInCLIProcess(senderManager, secretResolver, wmeta, ac) + diagnoseDeps := diagnose.NewSuitesDepsInCLIProcess(senderManager, secretResolver, wmeta, ac, tagger) // Run command // Get the diagnose result diff --git a/cmd/agent/subcommands/flare/command.go b/cmd/agent/subcommands/flare/command.go index 79311e31c29c4..97ee057642e52 100644 --- a/cmd/agent/subcommands/flare/command.go +++ b/cmd/agent/subcommands/flare/command.go @@ -124,10 +124,10 @@ func Commands(globalParams *command.GlobalParams) []*cobra.Command { workloadmetafx.Module(workloadmeta.Params{ AgentType: workloadmeta.NodeAgent, InitHelper: common.GetWorkloadmetaInit(), - NoInstance: !cliParams.forceLocal, //if forceLocal is true, we want to run workloadmeta }), - taggerimpl.OptionalModule(), - autodiscoveryimpl.OptionalModule(), // if forceLocal is true, we will start autodiscovery (loadComponents) later + fx.Provide(tagger.NewTaggerParams), + taggerimpl.Module(), + autodiscoveryimpl.Module(), fx.Supply(optional.NewNoneOption[collector.Component]()), compressionimpl.Module(), diagnosesendermanagerimpl.Module(), @@ -282,7 +282,7 @@ func makeFlare(flareComp flare.Component, _ sysprobeconfig.Component, cliParams *cliParams, _ optional.Option[workloadmeta.Component], - _ optional.Option[tagger.Component]) error { + _ tagger.Component) error { var ( profile flare.ProfileData err error diff --git a/cmd/agent/subcommands/jmx/command.go b/cmd/agent/subcommands/jmx/command.go index b56915eb1b406..851be12dfe138 100644 --- a/cmd/agent/subcommands/jmx/command.go +++ b/cmd/agent/subcommands/jmx/command.go @@ -58,6 +58,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/cli/standalone" pkgcollector "github.com/DataDog/datadog-agent/pkg/collector" "github.com/DataDog/datadog-agent/pkg/config/model" + proccontainers "github.com/DataDog/datadog-agent/pkg/process/util/containers" "github.com/DataDog/datadog-agent/pkg/util/defaultpaths" "github.com/DataDog/datadog-agent/pkg/util/fxutil" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -159,6 +160,13 @@ func Commands(globalParams *command.GlobalParams) []*cobra.Command { taggerimpl.Module(), autodiscoveryimpl.Module(), agent.Bundle(jmxloggerimpl.NewCliParams(cliParams.logFile)), + // InitSharedContainerProvider must be called before the application starts so the workloadmeta collector can be initiailized correctly. + // Since the tagger depends on the workloadmeta collector, we can not make the tagger a dependency of workloadmeta as it would create a circular dependency. + // TODO: (component) - once we remove the dependency of workloadmeta component from the tagger component + // we can include the tagger as part of the workloadmeta component. + fx.Invoke(func(wmeta workloadmeta.Component, tagger tagger.Component) { + proccontainers.InitSharedContainerProvider(wmeta, tagger) + }), ) } @@ -296,7 +304,8 @@ func runJmxCommandConsole(config config.Component, agentAPI internalAPI.Component, collector optional.Option[collector.Component], jmxLogger jmxlogger.Component, - logReceiver optional.Option[integrations.Component]) error { + logReceiver optional.Option[integrations.Component], + tagger tagger.Component) error { // This prevents log-spam from "comp/core/workloadmeta/collectors/internal/remote/process_collector/process_collector.go" // It appears that this collector creates some contention in AD. // Disabling it is both more efficient and gets rid of this log spam @@ -313,7 +322,7 @@ func runJmxCommandConsole(config config.Component, // Create the CheckScheduler, but do not attach it to // AutoDiscovery. - pkgcollector.InitCheckScheduler(collector, senderManager, logReceiver) + pkgcollector.InitCheckScheduler(collector, senderManager, logReceiver, tagger) // if cliSelectedChecks is empty, then we want to fetch all check configs; // otherwise, we fetch only the matching cehck configs. diff --git a/cmd/agent/subcommands/jmx/command_test.go b/cmd/agent/subcommands/jmx/command_test.go index bd162de9cc1bd..f5a07499f7d8c 100644 --- a/cmd/agent/subcommands/jmx/command_test.go +++ b/cmd/agent/subcommands/jmx/command_test.go @@ -8,6 +8,8 @@ package jmx import ( + "os" + "path" "strings" "testing" @@ -16,6 +18,7 @@ import ( "github.com/DataDog/datadog-agent/cmd/agent/command" "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/secrets" + "github.com/DataDog/datadog-agent/pkg/util/defaultpaths" "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) @@ -23,9 +26,12 @@ import ( func TestCollectCommand(t *testing.T) { // this tests several permutations of options that have a complex // relationship with the resulting params + + globalParams := newGlobalParamsTest(t) + t.Run("with no args", func(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(globalParams), []string{"jmx", "collect"}, runJmxCommandConsole, func(cliParams *cliParams, coreParams core.BundleParams, secretParams secrets.Params) { @@ -41,7 +47,7 @@ func TestCollectCommand(t *testing.T) { t.Run("with --log-level", func(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(globalParams), []string{"jmx", "collect", "--log-level", "info"}, runJmxCommandConsole, func(cliParams *cliParams, coreParams core.BundleParams, secretParams secrets.Params) { @@ -57,7 +63,7 @@ func TestCollectCommand(t *testing.T) { t.Run("with --flare", func(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(globalParams), []string{"jmx", "collect", "--flare", "--log-level", "info"}, runJmxCommandConsole, func(cliParams *cliParams, coreParams core.BundleParams, secretParams secrets.Params) { @@ -74,7 +80,7 @@ func TestCollectCommand(t *testing.T) { func TestListEverythingCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"jmx", "list", "everything"}, runJmxCommandConsole, func(cliParams *cliParams, _ core.BundleParams) { @@ -84,7 +90,7 @@ func TestListEverythingCommand(t *testing.T) { func TestListMatchingCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"jmx", "list", "matching"}, runJmxCommandConsole, func(cliParams *cliParams, _ core.BundleParams) { @@ -94,7 +100,7 @@ func TestListMatchingCommand(t *testing.T) { func TestListWithRateMetricsCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"jmx", "list", "with-rate-metrics"}, runJmxCommandConsole, func(cliParams *cliParams, _ core.BundleParams) { @@ -104,7 +110,7 @@ func TestListWithRateMetricsCommand(t *testing.T) { func TestListLimitedCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"jmx", "list", "limited"}, runJmxCommandConsole, func(cliParams *cliParams, _ core.BundleParams) { @@ -114,7 +120,7 @@ func TestListLimitedCommand(t *testing.T) { func TestListCollectedCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"jmx", "list", "collected"}, runJmxCommandConsole, func(cliParams *cliParams, _ core.BundleParams) { @@ -124,10 +130,21 @@ func TestListCollectedCommand(t *testing.T) { func TestListNotMatchingCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"jmx", "list", "not-matching"}, runJmxCommandConsole, func(cliParams *cliParams, _ core.BundleParams) { require.Equal(t, "list_not_matching_attributes", cliParams.command) }) } + +func newGlobalParamsTest(t *testing.T) *command.GlobalParams { + // Because run uses fx.Invoke, we need to provide a valid config file + config := path.Join(t.TempDir(), "datadog.yaml") + err := os.WriteFile(config, []byte("hostname: test"), 0644) + require.NoError(t, err) + + return &command.GlobalParams{ + ConfFilePath: config, + } +} diff --git a/cmd/agent/subcommands/processchecks/command_test.go b/cmd/agent/subcommands/processchecks/command_test.go index b253f0f3d8e04..73b5dc9eede6e 100644 --- a/cmd/agent/subcommands/processchecks/command_test.go +++ b/cmd/agent/subcommands/processchecks/command_test.go @@ -6,8 +6,12 @@ package processchecks import ( + "os" + "path" "testing" + "github.com/stretchr/testify/require" + "github.com/DataDog/datadog-agent/cmd/agent/command" "github.com/DataDog/datadog-agent/cmd/process-agent/subcommands/check" "github.com/DataDog/datadog-agent/pkg/util/fxutil" @@ -15,9 +19,20 @@ import ( func TestCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"processchecks", "process"}, check.RunCheckCmd, func(_ *check.CliParams) {}, ) } + +func newGlobalParamsTest(t *testing.T) *command.GlobalParams { + // Because we uses fx.Invoke some components are built + config := path.Join(t.TempDir(), "datadog.yaml") + err := os.WriteFile(config, []byte("hostname: test"), 0644) + require.NoError(t, err) + + return &command.GlobalParams{ + ConfFilePath: config, + } +} diff --git a/cmd/agent/subcommands/run/command.go b/cmd/agent/subcommands/run/command.go index 261cb79e7a72e..b52522c07de86 100644 --- a/cmd/agent/subcommands/run/command.go +++ b/cmd/agent/subcommands/run/command.go @@ -135,6 +135,7 @@ import ( commonsettings "github.com/DataDog/datadog-agent/pkg/config/settings" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/jmxfetch" + proccontainers "github.com/DataDog/datadog-agent/pkg/process/util/containers" "github.com/DataDog/datadog-agent/pkg/serializer" clusteragentStatus "github.com/DataDog/datadog-agent/pkg/status/clusteragent" endpointsStatus "github.com/DataDog/datadog-agent/pkg/status/endpoints" @@ -395,10 +396,13 @@ func getSharedFxOption() fx.Option { fx.Provide(tagger.NewTaggerParamsForCoreAgent), taggerimpl.Module(), autodiscoveryimpl.Module(), - fx.Provide(func(ac autodiscovery.Component) optional.Option[autodiscovery.Component] { - return optional.NewOption[autodiscovery.Component](ac) + // InitSharedContainerProvider must be called before the application starts so the workloadmeta collector can be initiailized correctly. + // Since the tagger depends on the workloadmeta collector, we can not make the tagger a dependency of workloadmeta as it would create a circular dependency. + // TODO: (component) - once we remove the dependency of workloadmeta component from the tagger component + // we can include the tagger as part of the workloadmeta component. + fx.Invoke(func(wmeta workloadmeta.Component, tagger tagger.Component) { + proccontainers.InitSharedContainerProvider(wmeta, tagger) }), - // TODO: (components) - some parts of the agent (such as the logs agent) implicitly depend on the global state // set up by LoadComponents. In order for components to use lifecycle hooks that also depend on this global state, we // have to ensure this code gets run first. Once the common package is made into a component, this can be removed. @@ -580,7 +584,7 @@ func startAgent( // Set up check collector commonchecks.RegisterChecks(wmeta, tagger, cfg, telemetry) - ac.AddScheduler("check", pkgcollector.InitCheckScheduler(optional.NewOption(collector), demultiplexer, logReceiver), true) + ac.AddScheduler("check", pkgcollector.InitCheckScheduler(optional.NewOption(collector), demultiplexer, logReceiver, tagger), true) demultiplexer.AddAgentStartupTelemetry(version.AgentVersion) diff --git a/cmd/agent/subcommands/run/internal/settings/runtime_settings_test.go b/cmd/agent/subcommands/run/internal/settings/runtime_settings_test.go index 547bf4d4940b2..4503bfecdca68 100644 --- a/cmd/agent/subcommands/run/internal/settings/runtime_settings_test.go +++ b/cmd/agent/subcommands/run/internal/settings/runtime_settings_test.go @@ -15,6 +15,8 @@ import ( "github.com/DataDog/datadog-agent/comp/aggregator/demultiplexer/demultiplexerimpl" "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" "github.com/DataDog/datadog-agent/comp/dogstatsd" @@ -38,12 +40,17 @@ func TestDogstatsdMetricsStats(t *testing.T) { assert := assert.New(t) var err error + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + deps := fxutil.Test[testDeps](t, fx.Options( core.MockBundle(), fx.Supply(core.BundleParams{}), demultiplexerimpl.MockModule(), dogstatsd.Bundle(server.Params{Serverless: false}), defaultforwarder.MockModule(), + fx.Provide(func() tagger.Component { + return taggerComponent + }), workloadmetafxmock.MockModule(workloadmeta.NewParams()), )) diff --git a/cmd/agent/subcommands/snmp/command.go b/cmd/agent/subcommands/snmp/command.go index 49e56e1248d1b..9ca08528338af 100644 --- a/cmd/agent/subcommands/snmp/command.go +++ b/cmd/agent/subcommands/snmp/command.go @@ -21,6 +21,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/config" log "github.com/DataDog/datadog-agent/comp/core/log/def" "github.com/DataDog/datadog-agent/comp/core/secrets" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/comp/forwarder" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" @@ -141,6 +142,7 @@ func Commands(globalParams *command.GlobalParams) []*cobra.Command { forwarder.Bundle(defaultforwarder.NewParams(defaultforwarder.WithFeatures(defaultforwarder.CoreFeatures))), orchestratorimpl.Module(orchestratorimpl.NewDefaultParams()), eventplatformimpl.Module(eventplatformimpl.NewDefaultParams()), + nooptagger.Module(), compressionimpl.Module(), eventplatformreceiverimpl.Module(), ) @@ -197,6 +199,7 @@ func Commands(globalParams *command.GlobalParams) []*cobra.Command { forwarder.Bundle(defaultforwarder.NewParams(defaultforwarder.WithFeatures(defaultforwarder.CoreFeatures))), eventplatformimpl.Module(eventplatformimpl.NewDefaultParams()), eventplatformreceiverimpl.Module(), + nooptagger.Module(), compressionimpl.Module(), snmpscanfx.Module(), ) diff --git a/cmd/cluster-agent-cloudfoundry/subcommands/run/command.go b/cmd/cluster-agent-cloudfoundry/subcommands/run/command.go index aac5d3639a948..d9fdf6db14a4d 100644 --- a/cmd/cluster-agent-cloudfoundry/subcommands/run/command.go +++ b/cmd/cluster-agent-cloudfoundry/subcommands/run/command.go @@ -55,6 +55,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/clusteragent/clusterchecks" pkgcollector "github.com/DataDog/datadog-agent/pkg/collector" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" + proccontainers "github.com/DataDog/datadog-agent/pkg/process/util/containers" "github.com/DataDog/datadog-agent/pkg/serializer" "github.com/DataDog/datadog-agent/pkg/status/health" "github.com/DataDog/datadog-agent/pkg/util/cloudproviders/cloudfoundry" @@ -119,6 +120,13 @@ func Commands(globalParams *command.GlobalParams) []*cobra.Command { } }), healthprobefx.Module(), + // InitSharedContainerProvider must be called before the application starts so the workloadmeta collector can be initiailized correctly. + // Since the tagger depends on the workloadmeta collector, we can not make the tagger a dependency of workloadmeta as it would create a circular dependency. + // TODO: (component) - once we remove the dependency of workloadmeta component from the tagger component + // we can include the tagger as part of the workloadmeta component. + fx.Invoke(func(wmeta workloadmeta.Component, tagger tagger.Component) { + proccontainers.InitSharedContainerProvider(wmeta, tagger) + }), ) }, } @@ -176,7 +184,7 @@ func run( common.LoadComponents(secretResolver, wmeta, ac, pkgconfigsetup.Datadog().GetString("confd_path")) // Set up check collector - ac.AddScheduler("check", pkgcollector.InitCheckScheduler(optional.NewOption(collector), demultiplexer, logReceiver), true) + ac.AddScheduler("check", pkgcollector.InitCheckScheduler(optional.NewOption(collector), demultiplexer, logReceiver, taggerComp), true) // start the autoconfig, this will immediately run any configured check ac.LoadAndRun(mainCtx) diff --git a/cmd/cluster-agent-cloudfoundry/subcommands/run/command_test.go b/cmd/cluster-agent-cloudfoundry/subcommands/run/command_test.go index 8c98dbc20eec4..3b33852f3a82a 100644 --- a/cmd/cluster-agent-cloudfoundry/subcommands/run/command_test.go +++ b/cmd/cluster-agent-cloudfoundry/subcommands/run/command_test.go @@ -8,16 +8,33 @@ package run import ( + "os" + "path" "testing" + "github.com/stretchr/testify/require" + "github.com/DataDog/datadog-agent/cmd/cluster-agent-cloudfoundry/command" "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) func TestCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"run"}, run, func() {}) } + +func newGlobalParamsTest(t *testing.T) *command.GlobalParams { + // Because run uses fx.Invoke, demultiplexer, and workloadmeta component are built + // which lead to build: + // - config.Component which requires a valid datadog.yaml + config := path.Join(t.TempDir(), "datadog.yaml") + err := os.WriteFile(config, []byte("hostname: test"), 0644) + require.NoError(t, err) + + return &command.GlobalParams{ + ConfFilePath: config, + } +} diff --git a/cmd/cluster-agent/api/agent/agent.go b/cmd/cluster-agent/api/agent/agent.go index d5d3ded9ebdb3..22f5e25ae0075 100644 --- a/cmd/cluster-agent/api/agent/agent.go +++ b/cmd/cluster-agent/api/agent/agent.go @@ -32,7 +32,7 @@ import ( ) // SetupHandlers adds the specific handlers for cluster agent endpoints -func SetupHandlers(r *mux.Router, wmeta workloadmeta.Component, ac autodiscovery.Component, statusComponent status.Component, settings settings.Component) { +func SetupHandlers(r *mux.Router, wmeta workloadmeta.Component, ac autodiscovery.Component, statusComponent status.Component, settings settings.Component, taggerComp tagger.Component) { r.HandleFunc("/version", getVersion).Methods("GET") r.HandleFunc("/hostname", getHostname).Methods("GET") r.HandleFunc("/flare", func(w http.ResponseWriter, r *http.Request) { @@ -48,7 +48,7 @@ func SetupHandlers(r *mux.Router, wmeta workloadmeta.Component, ac autodiscovery r.HandleFunc("/config/list-runtime", settings.ListConfigurable).Methods("GET") r.HandleFunc("/config/{setting}", settings.GetValue).Methods("GET") r.HandleFunc("/config/{setting}", settings.SetValue).Methods("POST") - r.HandleFunc("/tagger-list", getTaggerList).Methods("GET") + r.HandleFunc("/tagger-list", func(w http.ResponseWriter, r *http.Request) { getTaggerList(w, r, taggerComp) }).Methods("GET") r.HandleFunc("/workload-list", func(w http.ResponseWriter, r *http.Request) { getWorkloadList(w, r, wmeta) }).Methods("GET") @@ -177,8 +177,8 @@ func getConfigCheck(w http.ResponseWriter, _ *http.Request, ac autodiscovery.Com } //nolint:revive // TODO(CINT) Fix revive linter -func getTaggerList(w http.ResponseWriter, _ *http.Request) { - response := tagger.List() +func getTaggerList(w http.ResponseWriter, _ *http.Request, taggerComp tagger.Component) { + response := taggerComp.List() jsonTags, err := json.Marshal(response) if err != nil { diff --git a/cmd/cluster-agent/api/server.go b/cmd/cluster-agent/api/server.go index 350777aa8c8b0..171ab4fd6e59c 100644 --- a/cmd/cluster-agent/api/server.go +++ b/cmd/cluster-agent/api/server.go @@ -60,7 +60,7 @@ func StartServer(ctx context.Context, w workloadmeta.Component, taggerComp tagge apiRouter = router.PathPrefix("/api/v1").Subrouter() // IPC REST API server - agent.SetupHandlers(router, w, ac, statusComponent, settings) + agent.SetupHandlers(router, w, ac, statusComponent, settings, taggerComp) // API V1 Metadata APIs v1.InstallMetadataEndpoints(apiRouter, w) diff --git a/cmd/cluster-agent/subcommands/start/command.go b/cmd/cluster-agent/subcommands/start/command.go index b768b277fce03..1ed69b0ee41f5 100644 --- a/cmd/cluster-agent/subcommands/start/command.go +++ b/cmd/cluster-agent/subcommands/start/command.go @@ -115,6 +115,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/collector/corechecks/system/uptime" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/system/winproc" "github.com/DataDog/datadog-agent/pkg/collector/python" + proccontainers "github.com/DataDog/datadog-agent/pkg/process/util/containers" ) // Commands returns a slice of subcommands for the 'cluster-agent' command. @@ -196,6 +197,13 @@ func Commands(globalParams *command.GlobalParams) []*cobra.Command { }), settingsimpl.Module(), datadogclientmodule.Module(), + // InitSharedContainerProvider must be called before the application starts so the workloadmeta collector can be initiailized correctly. + // Since the tagger depends on the workloadmeta collector, we can not make the tagger a dependency of workloadmeta as it would create a circular dependency. + // TODO: (component) - once we remove the dependency of workloadmeta component from the tagger component + // we can include the tagger as part of the workloadmeta component. + fx.Invoke(func(wmeta workloadmeta.Component, tagger tagger.Component) { + proccontainers.InitSharedContainerProvider(wmeta, tagger) + }), ) }, } @@ -373,7 +381,7 @@ func start(log log.Component, // Set up check collector registerChecks(wmeta, taggerComp, config) - ac.AddScheduler("check", pkgcollector.InitCheckScheduler(optional.NewOption(collector), demultiplexer, logReceiver), true) + ac.AddScheduler("check", pkgcollector.InitCheckScheduler(optional.NewOption(collector), demultiplexer, logReceiver, taggerComp), true) // start the autoconfig, this will immediately run any configured check ac.LoadAndRun(mainCtx) @@ -590,6 +598,6 @@ func registerChecks(wlm workloadmeta.Component, tagger tagger.Component, cfg con corecheckLoader.RegisterCheck(ksm.CheckName, ksm.Factory()) corecheckLoader.RegisterCheck(helm.CheckName, helm.Factory()) corecheckLoader.RegisterCheck(disk.CheckName, disk.Factory()) - corecheckLoader.RegisterCheck(orchestrator.CheckName, orchestrator.Factory(wlm, cfg)) + corecheckLoader.RegisterCheck(orchestrator.CheckName, orchestrator.Factory(wlm, cfg, tagger)) corecheckLoader.RegisterCheck(winproc.CheckName, winproc.Factory()) } diff --git a/cmd/cluster-agent/subcommands/start/command_test.go b/cmd/cluster-agent/subcommands/start/command_test.go index aea6e818c4bfc..a620fa0d9a10f 100644 --- a/cmd/cluster-agent/subcommands/start/command_test.go +++ b/cmd/cluster-agent/subcommands/start/command_test.go @@ -8,16 +8,33 @@ package start import ( + "os" + "path" "testing" + "github.com/stretchr/testify/require" + "github.com/DataDog/datadog-agent/cmd/cluster-agent/command" "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) func TestCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"start"}, start, func() {}) } + +func newGlobalParamsTest(t *testing.T) *command.GlobalParams { + // Because run uses fx.Invoke, demultiplexer, and workloadmeta component are built + // which lead to build: + // - config.Component which requires a valid datadog.yaml + config := path.Join(t.TempDir(), "datadog.yaml") + err := os.WriteFile(config, []byte("hostname: test"), 0644) + require.NoError(t, err) + + return &command.GlobalParams{ + ConfFilePath: config, + } +} diff --git a/cmd/dogstatsd/subcommands/start/command.go b/cmd/dogstatsd/subcommands/start/command.go index 0e1193634a0b0..8be7d95034864 100644 --- a/cmd/dogstatsd/subcommands/start/command.go +++ b/cmd/dogstatsd/subcommands/start/command.go @@ -137,17 +137,10 @@ func RunDogstatsdFct(cliParams *CLIParams, defaultConfPath string, defaultLogFil forwarder.Bundle(defaultforwarder.NewParams()), // workloadmeta setup wmcatalog.GetCatalog(), - workloadmetafx.ModuleWithProvider(func(config config.Component) workloadmeta.Params { - catalog := workloadmeta.NodeAgent - instantiate := config.GetBool("dogstatsd_origin_detection") - - return workloadmeta.Params{ - AgentType: catalog, - InitHelper: common.GetWorkloadmetaInit(), - NoInstance: !instantiate, - } + workloadmetafx.Module(workloadmeta.Params{ + AgentType: workloadmeta.NodeAgent, + InitHelper: common.GetWorkloadmetaInit(), }), - compressionimpl.Module(), demultiplexerimpl.Module(demultiplexerimpl.NewDefaultParams( demultiplexerimpl.WithContinueOnMissingHostname(), @@ -158,7 +151,8 @@ func RunDogstatsdFct(cliParams *CLIParams, defaultConfPath string, defaultLogFil eventplatformimpl.Module(eventplatformimpl.NewDisabledParams()), eventplatformreceiverimpl.Module(), hostnameimpl.Module(), - taggerimpl.OptionalModule(), + taggerimpl.Module(), + fx.Provide(tagger.NewTaggerParams), // injecting the shared Serializer to FX until we migrate it to a prpoper component. This allows other // already migrated components to request it. fx.Provide(func(demuxInstance demultiplexer.Component) serializer.MetricSerializer { @@ -190,8 +184,8 @@ func start( params *Params, server dogstatsdServer.Component, _ defaultforwarder.Component, - wmeta optional.Option[workloadmeta.Component], - _ optional.Option[tagger.Component], + wmeta workloadmeta.Component, + _ tagger.Component, demultiplexer demultiplexer.Component, _ runner.Component, _ resources.Component, @@ -203,10 +197,9 @@ func start( // Main context passed to components ctx, cancel := context.WithCancel(context.Background()) - w, _ := wmeta.Get() components := &DogstatsdComponents{ DogstatsdServer: server, - WorkloadMeta: w, + WorkloadMeta: wmeta, } defer StopAgent(cancel, components) diff --git a/cmd/process-agent/api/server.go b/cmd/process-agent/api/server.go index 17ea655bac5ff..69bf9083dbc31 100644 --- a/cmd/process-agent/api/server.go +++ b/cmd/process-agent/api/server.go @@ -15,6 +15,7 @@ import ( log "github.com/DataDog/datadog-agent/comp/core/log/def" "github.com/DataDog/datadog-agent/comp/core/settings" "github.com/DataDog/datadog-agent/comp/core/status" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" ) @@ -27,6 +28,7 @@ type APIServerDeps struct { WorkloadMeta workloadmeta.Component Status status.Component Settings settings.Component + Tagger tagger.Component } func injectDeps(deps APIServerDeps, handler func(APIServerDeps, http.ResponseWriter, *http.Request)) http.HandlerFunc { diff --git a/cmd/process-agent/api/tagger_list.go b/cmd/process-agent/api/tagger_list.go index 78c94e334adfa..48b5cab2140bd 100644 --- a/cmd/process-agent/api/tagger_list.go +++ b/cmd/process-agent/api/tagger_list.go @@ -9,13 +9,12 @@ import ( "encoding/json" "net/http" - "github.com/DataDog/datadog-agent/comp/core/tagger" httputils "github.com/DataDog/datadog-agent/pkg/util/http" ) //nolint:revive // TODO(PROC) Fix revive linter func getTaggerList(deps APIServerDeps, w http.ResponseWriter, _ *http.Request) { - response := tagger.List() + response := deps.Tagger.List() jsonTags, err := json.Marshal(response) if err != nil { diff --git a/cmd/process-agent/command/main_common.go b/cmd/process-agent/command/main_common.go index 7c68bf17a73de..e3a235ad91ad1 100644 --- a/cmd/process-agent/command/main_common.go +++ b/cmd/process-agent/command/main_common.go @@ -49,6 +49,7 @@ import ( "github.com/DataDog/datadog-agent/comp/process/profiler" "github.com/DataDog/datadog-agent/comp/process/status/statusimpl" "github.com/DataDog/datadog-agent/comp/process/types" + rdnsquerierfx "github.com/DataDog/datadog-agent/comp/rdnsquerier/fx" remoteconfig "github.com/DataDog/datadog-agent/comp/remote-config" "github.com/DataDog/datadog-agent/comp/remote-config/rcclient" "github.com/DataDog/datadog-agent/pkg/collector/python" @@ -57,6 +58,7 @@ import ( commonsettings "github.com/DataDog/datadog-agent/pkg/config/settings" "github.com/DataDog/datadog-agent/pkg/process/metadata/workloadmeta/collector" "github.com/DataDog/datadog-agent/pkg/process/util" + proccontainers "github.com/DataDog/datadog-agent/pkg/process/util/containers" ddutil "github.com/DataDog/datadog-agent/pkg/util" "github.com/DataDog/datadog-agent/pkg/util/fxutil" "github.com/DataDog/datadog-agent/pkg/util/fxutil/logging" @@ -132,6 +134,9 @@ func runApp(ctx context.Context, globalParams *GlobalParams) error { eventplatformreceiverimpl.Module(), eventplatformimpl.Module(eventplatformimpl.NewDefaultParams()), + // Provides the rdnssquerier module + rdnsquerierfx.Module(), + // Provide network path bundle networkpath.Bundle(), @@ -277,6 +282,7 @@ type miscDeps struct { HostInfo hostinfo.Component WorkloadMeta workloadmeta.Component Logger logcomp.Component + Tagger tagger.Component } // initMisc initializes modules that cannot, or have not yet been componetized. @@ -287,6 +293,12 @@ func initMisc(deps miscDeps) error { deps.Logger.Warnf("Can't setup core dumps: %v, core dumps might not be available after a crash", err) } + // InitSharedContainerProvider must be called before the application starts so the workloadmeta collector can be initiailized correctly. + // Since the tagger depends on the workloadmeta collector, we can not make the tagger a dependency of workloadmeta as it would create a circular dependency. + // TODO: (component) - once we remove the dependency of workloadmeta component from the tagger component + // we can include the tagger as part of the workloadmeta component. + proccontainers.InitSharedContainerProvider(deps.WorkloadMeta, deps.Tagger) + processCollectionServer := collector.NewProcessCollector(deps.Config, deps.Syscfg) // TODO(components): still unclear how the initialization of workloadmeta diff --git a/cmd/process-agent/subcommands/check/check.go b/cmd/process-agent/subcommands/check/check.go index be338e8df2252..c68b0fe850dd2 100644 --- a/cmd/process-agent/subcommands/check/check.go +++ b/cmd/process-agent/subcommands/check/check.go @@ -39,7 +39,9 @@ import ( processComponent "github.com/DataDog/datadog-agent/comp/process" "github.com/DataDog/datadog-agent/comp/process/hostinfo" "github.com/DataDog/datadog-agent/comp/process/types" + rdnsquerierfx "github.com/DataDog/datadog-agent/comp/rdnsquerier/fx" "github.com/DataDog/datadog-agent/pkg/process/checks" + proccontainers "github.com/DataDog/datadog-agent/pkg/process/util/containers" "github.com/DataDog/datadog-agent/pkg/util/fxutil" "github.com/DataDog/datadog-agent/pkg/version" ) @@ -124,6 +126,11 @@ func MakeCommand(globalParamsGetter func() *command.GlobalParams, name string, a // Provide eventplatformimpl module eventplatformreceiverimpl.Module(), eventplatformimpl.Module(eventplatformimpl.NewDefaultParams()), + + // Provide rdnsquerier module + rdnsquerierfx.Module(), + + // Provide npcollector module npcollectorimpl.Module(), // Provide the corresponding workloadmeta Params to configure the catalog wmcatalog.GetCatalog(), @@ -149,6 +156,13 @@ func MakeCommand(globalParamsGetter func() *command.GlobalParams, name string, a return tagger.NewTaggerParams() }), processComponent.Bundle(), + // InitSharedContainerProvider must be called before the application starts so the workloadmeta collector can be initiailized correctly. + // Since the tagger depends on the workloadmeta collector, we can not make the tagger a dependency of workloadmeta as it would create a circular dependency. + // TODO: (component) - once we remove the dependency of workloadmeta component from the tagger component + // we can include the tagger as part of the workloadmeta component. + fx.Invoke(func(wmeta workloadmeta.Component, tagger tagger.Component) { + proccontainers.InitSharedContainerProvider(wmeta, tagger) + }), ) }, SilenceUsage: true, diff --git a/cmd/process-agent/subcommands/check/check_test.go b/cmd/process-agent/subcommands/check/check_test.go index 4876508bc3eb9..c750585a6f4de 100644 --- a/cmd/process-agent/subcommands/check/check_test.go +++ b/cmd/process-agent/subcommands/check/check_test.go @@ -6,17 +6,32 @@ package check import ( + "os" + "path" "testing" + "github.com/stretchr/testify/require" + "github.com/DataDog/datadog-agent/cmd/process-agent/command" "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) func TestRunCheckCmdCommand(t *testing.T) { fxutil.TestOneShotSubcommand(t, - Commands(&command.GlobalParams{}), + Commands(newGlobalParamsTest(t)), []string{"check", "process"}, RunCheckCmd, func(_ *CliParams) {}, ) } + +func newGlobalParamsTest(t *testing.T) *command.GlobalParams { + // Because we uses fx.Invoke some components are built + config := path.Join(t.TempDir(), "datadog.yaml") + err := os.WriteFile(config, []byte("hostname: test"), 0644) + require.NoError(t, err) + + return &command.GlobalParams{ + ConfFilePath: config, + } +} diff --git a/cmd/security-agent/subcommands/runtime/command.go b/cmd/security-agent/subcommands/runtime/command.go index 8451c549889f2..0b32529c60d36 100644 --- a/cmd/security-agent/subcommands/runtime/command.go +++ b/cmd/security-agent/subcommands/runtime/command.go @@ -223,6 +223,7 @@ type processCacheDumpCliParams struct { *command.GlobalParams withArgs bool + format string } //nolint:unused // TODO(SEC) Fix unused linter @@ -246,6 +247,7 @@ func processCacheCommands(globalParams *command.GlobalParams) []*cobra.Command { }, } processCacheDumpCmd.Flags().BoolVar(&cliParams.withArgs, "with-args", false, "add process arguments to the dump") + processCacheDumpCmd.Flags().StringVar(&cliParams.format, "format", "dot", "process cache dump format") processCacheCmd := &cobra.Command{ Use: "process-cache", @@ -328,7 +330,7 @@ func dumpProcessCache(_ log.Component, _ config.Component, _ secrets.Component, } defer client.Close() - filename, err := client.DumpProcessCache(processCacheDumpArgs.withArgs) + filename, err := client.DumpProcessCache(processCacheDumpArgs.withArgs, processCacheDumpArgs.format) if err != nil { return fmt.Errorf("unable to get a process cache dump: %w", err) } diff --git a/cmd/security-agent/subcommands/start/command.go b/cmd/security-agent/subcommands/start/command.go index b8631b19a4d8b..317adad3c0b9b 100644 --- a/cmd/security-agent/subcommands/start/command.go +++ b/cmd/security-agent/subcommands/start/command.go @@ -346,8 +346,6 @@ func StopAgent(log log.Component) { func setupInternalProfiling(config config.Component) error { if config.GetBool(secAgentKey("internal_profiling.enabled")) { - v, _ := version.Agent() - cfgSite := config.GetString(secAgentKey("internal_profiling.site")) cfgURL := config.GetString(secAgentKey("internal_profiling.profile_dd_url")) @@ -363,7 +361,7 @@ func setupInternalProfiling(config config.Component) error { } tags := config.GetStringSlice(secAgentKey("internal_profiling.extra_tags")) - tags = append(tags, fmt.Sprintf("version:%v", v)) + tags = append(tags, fmt.Sprintf("version:%v", version.AgentVersion)) profSettings := profiling.Settings{ ProfilingURL: site, diff --git a/cmd/serverless-init/main.go b/cmd/serverless-init/main.go index 0db7244b7774b..c7484233528fd 100644 --- a/cmd/serverless-init/main.go +++ b/cmd/serverless-init/main.go @@ -140,9 +140,9 @@ func setup(_ mode.Conf, tagger tagger.Component) (cloudservice.CloudService, *se } logsAgent := serverlessInitLog.SetupLogAgent(agentLogConfig, tags, tagger) - traceAgent := setupTraceAgent(tags) + traceAgent := setupTraceAgent(tags, tagger) - metricAgent := setupMetricAgent(tags) + metricAgent := setupMetricAgent(tags, tagger) metric.AddColdStartMetric(prefix, metricAgent.GetExtraTags(), time.Now(), metricAgent.Demux) setupOtlpAgent(metricAgent) @@ -150,8 +150,8 @@ func setup(_ mode.Conf, tagger tagger.Component) (cloudservice.CloudService, *se go flushMetricsAgent(metricAgent) return cloudService, agentLogConfig, traceAgent, metricAgent, logsAgent } -func setupTraceAgent(tags map[string]string) trace.ServerlessTraceAgent { - traceAgent := trace.StartServerlessTraceAgent(pkgconfigsetup.Datadog().GetBool("apm_config.enabled"), &trace.LoadConfig{Path: datadogConfigPath}, nil, random.Random.Uint64()) +func setupTraceAgent(tags map[string]string, tagger tagger.Component) trace.ServerlessTraceAgent { + traceAgent := trace.StartServerlessTraceAgent(pkgconfigsetup.Datadog().GetBool("apm_config.enabled"), &trace.LoadConfig{Path: datadogConfigPath, Tagger: tagger}, nil, random.Random.Uint64()) traceAgent.SetTags(tags) go func() { for range time.Tick(3 * time.Second) { @@ -161,12 +161,13 @@ func setupTraceAgent(tags map[string]string) trace.ServerlessTraceAgent { return traceAgent } -func setupMetricAgent(tags map[string]string) *metrics.ServerlessMetricAgent { +func setupMetricAgent(tags map[string]string, tagger tagger.Component) *metrics.ServerlessMetricAgent { pkgconfigsetup.Datadog().Set("use_v2_api.series", false, model.SourceAgentRuntime) pkgconfigsetup.Datadog().Set("dogstatsd_socket", "", model.SourceAgentRuntime) metricAgent := &metrics.ServerlessMetricAgent{ SketchesBucketOffset: time.Second * 0, + Tagger: tagger, } // we don't want to add the container_id tag to metrics for cardinality reasons tags = serverlessInitTag.WithoutContainerID(tags) diff --git a/cmd/serverless-init/main_test.go b/cmd/serverless-init/main_test.go index 4d0c534ce328d..ce9eda80f5b13 100644 --- a/cmd/serverless-init/main_test.go +++ b/cmd/serverless-init/main_test.go @@ -29,7 +29,6 @@ func TestTagsSetup(t *testing.T) { t.Skip() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() configmock.New(t) diff --git a/cmd/serverless/main.go b/cmd/serverless/main.go index 68865f96aa14e..0970277ae0a89 100644 --- a/cmd/serverless/main.go +++ b/cmd/serverless/main.go @@ -111,13 +111,13 @@ func runAgent(tagger tagger.Component) { lambdaInitMetricChan := make(chan *serverlessLogs.LambdaInitMetric) //nolint:revive // TODO(SERV) Fix revive linter coldStartSpanId := random.Random.Uint64() - metricAgent := startMetricAgent(serverlessDaemon, logChannel, lambdaInitMetricChan) + metricAgent := startMetricAgent(serverlessDaemon, logChannel, lambdaInitMetricChan, tagger) // Concurrently start heavyweight features var wg sync.WaitGroup wg.Add(3) - go startTraceAgent(&wg, lambdaSpanChan, coldStartSpanId, serverlessDaemon) + go startTraceAgent(&wg, lambdaSpanChan, coldStartSpanId, serverlessDaemon, tagger) go startOtlpAgent(&wg, metricAgent, serverlessDaemon) go startTelemetryCollection(&wg, serverlessID, logChannel, serverlessDaemon, tagger) @@ -205,9 +205,10 @@ func setupProxy(appsecProxyProcessor *httpsec.ProxyLifecycleProcessor, ta trace. } } -func startMetricAgent(serverlessDaemon *daemon.Daemon, logChannel chan *logConfig.ChannelMessage, lambdaInitMetricChan chan *serverlessLogs.LambdaInitMetric) *metrics.ServerlessMetricAgent { +func startMetricAgent(serverlessDaemon *daemon.Daemon, logChannel chan *logConfig.ChannelMessage, lambdaInitMetricChan chan *serverlessLogs.LambdaInitMetric, tagger tagger.Component) *metrics.ServerlessMetricAgent { metricAgent := &metrics.ServerlessMetricAgent{ SketchesBucketOffset: time.Second * 10, + Tagger: tagger, } metricAgent.Start(daemon.FlushTimeout, &metrics.MetricConfig{}, &metrics.MetricDogStatsD{}) serverlessDaemon.SetStatsdServer(metricAgent) @@ -334,9 +335,9 @@ func startOtlpAgent(wg *sync.WaitGroup, metricAgent *metrics.ServerlessMetricAge } -func startTraceAgent(wg *sync.WaitGroup, lambdaSpanChan chan *pb.Span, coldStartSpanId uint64, serverlessDaemon *daemon.Daemon) { +func startTraceAgent(wg *sync.WaitGroup, lambdaSpanChan chan *pb.Span, coldStartSpanId uint64, serverlessDaemon *daemon.Daemon, tagger tagger.Component) { defer wg.Done() - traceAgent := trace.StartServerlessTraceAgent(pkgconfigsetup.Datadog().GetBool("apm_config.enabled"), &trace.LoadConfig{Path: datadogConfigPath}, lambdaSpanChan, coldStartSpanId) + traceAgent := trace.StartServerlessTraceAgent(pkgconfigsetup.Datadog().GetBool("apm_config.enabled"), &trace.LoadConfig{Path: datadogConfigPath, Tagger: tagger}, lambdaSpanChan, coldStartSpanId) serverlessDaemon.SetTraceAgent(traceAgent) } diff --git a/cmd/system-probe/api/server.go b/cmd/system-probe/api/server.go index a2d20995b9804..5c6c31df8beab 100644 --- a/cmd/system-probe/api/server.go +++ b/cmd/system-probe/api/server.go @@ -11,6 +11,7 @@ import ( "expvar" "fmt" "net/http" + "runtime" gorilla "github.com/gorilla/mux" @@ -21,6 +22,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/settings" "github.com/DataDog/datadog-agent/comp/core/telemetry" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" + "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/process/net" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -53,6 +55,10 @@ func StartServer(cfg *sysconfigtypes.Config, telemetry telemetry.Component, wmet mux.Handle("/debug/vars", http.DefaultServeMux) mux.Handle("/telemetry", telemetry.Handler()) + if runtime.GOOS == "linux" { + mux.HandleFunc("/debug/ebpf_btf_loader_info", ebpf.HandleBTFLoaderInfo) + } + go func() { err = http.Serve(conn.GetListener(), mux) if err != nil && !errors.Is(err, http.ErrServerClosed) { diff --git a/cmd/system-probe/config/adjust.go b/cmd/system-probe/config/adjust.go index 37c0fb29cfeb9..f1b6eb2205ce5 100644 --- a/cmd/system-probe/config/adjust.go +++ b/cmd/system-probe/config/adjust.go @@ -42,6 +42,9 @@ func Adjust(cfg model.Config) { validateString(cfg, spNS("sysprobe_socket"), defaultSystemProbeAddress, ValidateSocketAddress) + deprecateBool(cfg, spNS("allow_precompiled_fallback"), spNS("allow_prebuilt_fallback")) + allowPrebuiltEbpfFallback(cfg) + adjustNetwork(cfg) adjustUSM(cfg) adjustSecurity(cfg) diff --git a/cmd/system-probe/config/config_darwin.go b/cmd/system-probe/config/config_darwin.go index 76534ca7e505d..ef5d2091298e4 100644 --- a/cmd/system-probe/config/config_darwin.go +++ b/cmd/system-probe/config/config_darwin.go @@ -7,7 +7,12 @@ package config +import "github.com/DataDog/datadog-agent/pkg/config/model" + // ProcessEventDataStreamSupported returns true if process event data stream is supported func ProcessEventDataStreamSupported() bool { return false } + +func allowPrebuiltEbpfFallback(_ model.Config) { +} diff --git a/cmd/system-probe/config/config_linux.go b/cmd/system-probe/config/config_linux.go index 5a52c230b5c3e..6d9aec23e0774 100644 --- a/cmd/system-probe/config/config_linux.go +++ b/cmd/system-probe/config/config_linux.go @@ -8,10 +8,17 @@ package config import ( + "github.com/DataDog/datadog-agent/pkg/config/model" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" ebpfkernel "github.com/DataDog/datadog-agent/pkg/security/ebpf/kernel" "github.com/DataDog/datadog-agent/pkg/util/log" ) +var ( + allowPrebuiltFallbackKey = spNS("allow_prebuilt_fallback") + allowPrecompiledFallbackKey = spNS("allow_precompiled_fallback") +) + // ProcessEventDataStreamSupported returns true if process event data stream is supported func ProcessEventDataStreamSupported() bool { kernelVersion, err := ebpfkernel.NewKernelVersion() @@ -28,3 +35,12 @@ func ProcessEventDataStreamSupported() bool { return true } + +func allowPrebuiltEbpfFallback(cfg model.Config) { + // only allow falling back to prebuilt eBPF if the config + // is not explicitly set and prebuilt eBPF is not deprecated + // on the platform + if !cfg.IsSet(allowPrebuiltFallbackKey) && !prebuilt.IsDeprecated() { + cfg.Set(allowPrebuiltFallbackKey, true, model.SourceAgentRuntime) + } +} diff --git a/cmd/system-probe/config/config_linux_test.go b/cmd/system-probe/config/config_linux_test.go index 883edaaab88c9..7554e65f33d1f 100644 --- a/cmd/system-probe/config/config_linux_test.go +++ b/cmd/system-probe/config/config_linux_test.go @@ -15,6 +15,9 @@ import ( "github.com/stretchr/testify/require" "github.com/DataDog/datadog-agent/pkg/config/mock" + "github.com/DataDog/datadog-agent/pkg/config/model" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" + "github.com/DataDog/datadog-agent/pkg/util/kernel" ) func TestNetworkProcessEventMonitoring(t *testing.T) { @@ -109,3 +112,79 @@ func TestNPMEnabled(t *testing.T) { }) } } + +func TestEbpfPrebuiltFallbackDeprecation(t *testing.T) { + family, err := kernel.Family() + require.NoError(t, err, "could not determine kernel family") + + kv, err := kernel.HostVersion() + require.NoError(t, err, "could not determine kernel version") + + deprecateVersion := prebuilt.DeprecatedKernelVersion + if family == "rhel" { + deprecateVersion = prebuilt.DeprecatedKernelVersionRhel + } + + t.Run("default", func(t *testing.T) { + cfg := mock.NewSystemProbe(t) + assert.False(t, cfg.GetBool(allowPrebuiltFallbackKey)) + assert.False(t, cfg.GetBool(allowPrecompiledFallbackKey)) + }) + + t.Run("not set in config", func(t *testing.T) { + cfg := mock.NewSystemProbe(t) + Adjust(cfg) + + switch { + case kv < deprecateVersion: + assert.True(t, cfg.GetBool(allowPrebuiltFallbackKey)) + default: + // deprecated + assert.False(t, cfg.GetBool(allowPrebuiltFallbackKey)) + } + }) + + // if system_probe_config.allow_precompiled_fallback is set + // in config, that value should not be changed by Adjust() and + // the new key, `system_probe_config.allow_prebuilt_fallback` + // should be set to the same value + t.Run("allow_precompiled_fallback set in config", func(t *testing.T) { + t.Run("true", func(t *testing.T) { + cfg := mock.NewSystemProbe(t) + cfg.Set(allowPrecompiledFallbackKey, true, model.SourceDefault) + Adjust(cfg) + + assert.True(t, cfg.GetBool(allowPrecompiledFallbackKey)) + assert.Equal(t, cfg.GetBool(allowPrecompiledFallbackKey), cfg.GetBool(allowPrebuiltFallbackKey)) + }) + + t.Run("false", func(t *testing.T) { + cfg := mock.NewSystemProbe(t) + cfg.Set(allowPrecompiledFallbackKey, false, model.SourceDefault) + Adjust(cfg) + + assert.False(t, cfg.GetBool(allowPrecompiledFallbackKey)) + assert.Equal(t, cfg.GetBool(allowPrecompiledFallbackKey), cfg.GetBool(allowPrebuiltFallbackKey)) + }) + }) + + // if system_probe_config.allow_prebuilt_fallback is set + // in config, that value should not be changed by Adjust() + t.Run("allow_prebuilt_fallback set in config", func(t *testing.T) { + t.Run("true", func(t *testing.T) { + cfg := mock.NewSystemProbe(t) + cfg.Set(allowPrebuiltFallbackKey, true, model.SourceDefault) + Adjust(cfg) + + assert.True(t, cfg.GetBool(allowPrebuiltFallbackKey)) + }) + + t.Run("false", func(t *testing.T) { + cfg := mock.NewSystemProbe(t) + cfg.Set(allowPrebuiltFallbackKey, false, model.SourceDefault) + Adjust(cfg) + + assert.False(t, cfg.GetBool(allowPrebuiltFallbackKey)) + }) + }) +} diff --git a/cmd/system-probe/config/config_unsupported.go b/cmd/system-probe/config/config_unsupported.go index 3ad7cbbd460e8..164e25b747224 100644 --- a/cmd/system-probe/config/config_unsupported.go +++ b/cmd/system-probe/config/config_unsupported.go @@ -7,7 +7,11 @@ package config -import "fmt" +import ( + "fmt" + + "github.com/DataDog/datadog-agent/pkg/config/model" +) const ( defaultConfigDir = "" @@ -23,3 +27,6 @@ func ValidateSocketAddress(sockPath string) error { func ProcessEventDataStreamSupported() bool { return false } + +func allowPrebuiltEbpfFallback(_ model.Config) { +} diff --git a/cmd/system-probe/config/config_windows.go b/cmd/system-probe/config/config_windows.go index 54e1e09b273a8..54074b4042ab5 100644 --- a/cmd/system-probe/config/config_windows.go +++ b/cmd/system-probe/config/config_windows.go @@ -11,6 +11,7 @@ import ( "fmt" "net" + "github.com/DataDog/datadog-agent/pkg/config/model" "github.com/DataDog/datadog-agent/pkg/util/winutil" ) @@ -45,3 +46,6 @@ func ValidateSocketAddress(sockAddress string) error { func ProcessEventDataStreamSupported() bool { return true } + +func allowPrebuiltEbpfFallback(_ model.Config) { +} diff --git a/cmd/system-probe/modules/eventmonitor_linux.go b/cmd/system-probe/modules/eventmonitor_linux.go index bf63a33276723..ad85abd48a6da 100644 --- a/cmd/system-probe/modules/eventmonitor_linux.go +++ b/cmd/system-probe/modules/eventmonitor_linux.go @@ -28,7 +28,7 @@ var EventMonitor = module.Factory{ }, } -func createProcessMonitorConsumer(evm *eventmonitor.EventMonitor, config *netconfig.Config) (eventmonitor.EventConsumerInterface, error) { +func createProcessMonitorConsumer(evm *eventmonitor.EventMonitor, config *netconfig.Config) (eventmonitor.EventConsumer, error) { if !usmconfig.IsUSMSupportedAndEnabled(config) || !usmconfig.NeedProcessMonitor(config) || usmstate.Get() != usmstate.Running { return nil, nil } diff --git a/cmd/system-probe/modules/eventmonitor_windows.go b/cmd/system-probe/modules/eventmonitor_windows.go index 465d123796cd3..aa81d0f428f5e 100644 --- a/cmd/system-probe/modules/eventmonitor_windows.go +++ b/cmd/system-probe/modules/eventmonitor_windows.go @@ -21,6 +21,6 @@ var EventMonitor = module.Factory{ Fn: createEventMonitorModule, } -func createProcessMonitorConsumer(_ *eventmonitor.EventMonitor, _ *netconfig.Config) (eventmonitor.EventConsumerInterface, error) { +func createProcessMonitorConsumer(_ *eventmonitor.EventMonitor, _ *netconfig.Config) (eventmonitor.EventConsumer, error) { return nil, nil } diff --git a/cmd/system-probe/modules/gpu.go b/cmd/system-probe/modules/gpu.go index 3cd54e27293e5..27f3f0cc87890 100644 --- a/cmd/system-probe/modules/gpu.go +++ b/cmd/system-probe/modules/gpu.go @@ -20,11 +20,12 @@ import ( sysconfigtypes "github.com/DataDog/datadog-agent/cmd/system-probe/config/types" "github.com/DataDog/datadog-agent/cmd/system-probe/utils" "github.com/DataDog/datadog-agent/pkg/gpu" + gpuconfig "github.com/DataDog/datadog-agent/pkg/gpu/config" "github.com/DataDog/datadog-agent/pkg/util/log" ) var _ module.Module = &GPUMonitoringModule{} -var gpuMonitoringConfigNamespaces = []string{gpu.GPUNS} +var gpuMonitoringConfigNamespaces = []string{gpuconfig.GPUNS} // GPUMonitoring Factory var GPUMonitoring = module.Factory{ @@ -32,7 +33,7 @@ var GPUMonitoring = module.Factory{ ConfigNamespaces: gpuMonitoringConfigNamespaces, Fn: func(_ *sysconfigtypes.Config, deps module.FactoryDependencies) (module.Module, error) { - c := gpu.NewConfig() + c := gpuconfig.NewConfig() probeDeps := gpu.ProbeDependencies{ Telemetry: deps.Telemetry, //if the config parameter doesn't exist or is empty string, the default value is used as defined in go-nvml library diff --git a/cmd/system-probe/modules/network_tracer.go b/cmd/system-probe/modules/network_tracer.go index 97d27189f2706..b605a3f0e99c3 100644 --- a/cmd/system-probe/modules/network_tracer.go +++ b/cmd/system-probe/modules/network_tracer.go @@ -295,6 +295,7 @@ func (nt *networkTracer) Register(httpMux *module.Router) error { httpMux.HandleFunc("/debug/usm_telemetry", telemetry.Handler) httpMux.HandleFunc("/debug/usm/traced_programs", usm.TracedProgramsEndpoint) httpMux.HandleFunc("/debug/usm/blocked_processes", usm.BlockedPathIDEndpoint) + httpMux.HandleFunc("/debug/usm/clear_blocked", usm.ClearBlockedEndpoint) httpMux.HandleFunc("/debug/usm/attach-pid", usm.AttachPIDEndpoint) httpMux.HandleFunc("/debug/usm/detach-pid", usm.DetachPIDEndpoint) diff --git a/cmd/system-probe/modules/network_tracer_test.go b/cmd/system-probe/modules/network_tracer_test.go index 34340f448ed8f..bbe67d3d3df99 100644 --- a/cmd/system-probe/modules/network_tracer_test.go +++ b/cmd/system-probe/modules/network_tracer_test.go @@ -27,9 +27,16 @@ func TestDecode(t *testing.T) { in := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.1.1.1"), Dest: util.AddressFromString("10.2.2.2"), + Pid: 6000, + NetNS: 7, + SPort: 1000, + DPort: 9000, + Type: network.UDP, + Family: network.AFINET6, + }, Monotonic: network.StatCounters{ SentBytes: 1, RecvBytes: 100, @@ -41,19 +48,12 @@ func TestDecode(t *testing.T) { Retransmits: 201, }, LastUpdateEpoch: 50, - Pid: 6000, - NetNS: 7, - SPort: 1000, - DPort: 9000, IPTranslation: &network.IPTranslation{ ReplSrcIP: util.AddressFromString("20.1.1.1"), ReplDstIP: util.AddressFromString("20.1.1.1"), ReplSrcPort: 40, ReplDstPort: 70, }, - - Type: network.UDP, - Family: network.AFINET6, Direction: network.LOCAL, }, }, diff --git a/cmd/system-probe/modules/traceroute.go b/cmd/system-probe/modules/traceroute.go index 6e0667e120784..c860b2c068a30 100644 --- a/cmd/system-probe/modules/traceroute.go +++ b/cmd/system-probe/modules/traceroute.go @@ -101,7 +101,7 @@ func logTracerouteRequests(cfg tracerouteutil.Config, client string, runCount ui args := []interface{}{cfg.DestHostname, client, cfg.DestPort, cfg.MaxTTL, cfg.Timeout, cfg.Protocol, runCount, time.Since(start)} msg := "Got request on /traceroute/%s?client_id=%s&port=%d&maxTTL=%d&timeout=%d&protocol=%s (count: %d): retrieved traceroute in %s" switch { - case runCount <= 5, runCount%20 == 0: + case runCount <= 5, runCount%200 == 0: log.Infof(msg, args...) default: log.Debugf(msg, args...) diff --git a/cmd/system-probe/subcommands/run/command.go b/cmd/system-probe/subcommands/run/command.go index e5461f8c483db..4459dce978347 100644 --- a/cmd/system-probe/subcommands/run/command.go +++ b/cmd/system-probe/subcommands/run/command.go @@ -91,7 +91,7 @@ func Commands(globalParams *command.GlobalParams) []*cobra.Command { fx.Supply(config.NewAgentParams("", config.WithConfigMissingOK(true))), fx.Supply(sysprobeconfigimpl.NewParams(sysprobeconfigimpl.WithSysProbeConfFilePath(globalParams.ConfFilePath), sysprobeconfigimpl.WithFleetPoliciesDirPath(globalParams.FleetPoliciesDirPath))), fx.Supply(log.ForDaemon("SYS-PROBE", "log_file", common.DefaultLogFile)), - fx.Supply(rcclient.Params{AgentName: "system-probe", AgentVersion: version.AgentVersion}), + fx.Supply(rcclient.Params{AgentName: "system-probe", AgentVersion: version.AgentVersion, IsSystemProbe: true}), fx.Supply(optional.NewNoneOption[secrets.Component]()), compstatsd.Module(), config.Module(), @@ -254,7 +254,7 @@ func runSystemProbe(ctxChan <-chan context.Context, errChan chan error) error { fx.Supply(config.NewAgentParams("", config.WithConfigMissingOK(true))), fx.Supply(sysprobeconfigimpl.NewParams(sysprobeconfigimpl.WithSysProbeConfFilePath(""))), fx.Supply(log.ForDaemon("SYS-PROBE", "log_file", common.DefaultLogFile)), - fx.Supply(rcclient.Params{AgentName: "system-probe", AgentVersion: version.AgentVersion}), + fx.Supply(rcclient.Params{AgentName: "system-probe", AgentVersion: version.AgentVersion, IsSystemProbe: true}), fx.Supply(optional.NewNoneOption[secrets.Component]()), rcclientimpl.Module(), config.Module(), diff --git a/cmd/system-probe/subcommands/runtime/command.go b/cmd/system-probe/subcommands/runtime/command.go index 9e9a7f77a63cd..e6030500a9b17 100644 --- a/cmd/system-probe/subcommands/runtime/command.go +++ b/cmd/system-probe/subcommands/runtime/command.go @@ -217,6 +217,7 @@ type processCacheDumpCliParams struct { *command.GlobalParams withArgs bool + format string } //nolint:unused // TODO(SEC) Fix unused linter @@ -240,6 +241,7 @@ func processCacheCommands(globalParams *command.GlobalParams) []*cobra.Command { }, } processCacheDumpCmd.Flags().BoolVar(&cliParams.withArgs, "with-args", false, "add process arguments to the dump") + processCacheDumpCmd.Flags().StringVar(&cliParams.format, "format", "dot", "process cache dump format") processCacheCmd := &cobra.Command{ Use: "process-cache", @@ -322,7 +324,7 @@ func dumpProcessCache(_ log.Component, _ config.Component, _ secrets.Component, } defer client.Close() - filename, err := client.DumpProcessCache(processCacheDumpArgs.withArgs) + filename, err := client.DumpProcessCache(processCacheDumpArgs.withArgs, processCacheDumpArgs.format) if err != nil { return fmt.Errorf("unable to get a process cache dump: %w", err) } diff --git a/cmd/systray/command/command.go b/cmd/systray/command/command.go index c237b0aa65bb3..4a2b3fa74714f 100644 --- a/cmd/systray/command/command.go +++ b/cmd/systray/command/command.go @@ -21,10 +21,11 @@ import ( authtokenimpl "github.com/DataDog/datadog-agent/comp/api/authtoken/fetchonlyimpl" "github.com/DataDog/datadog-agent/comp/collector/collector" "github.com/DataDog/datadog-agent/comp/core" - "github.com/DataDog/datadog-agent/comp/core/autodiscovery" + noopAutodiscover "github.com/DataDog/datadog-agent/comp/core/autodiscovery/noopimpl" "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/flare" log "github.com/DataDog/datadog-agent/comp/core/log/def" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/comp/metadata/inventoryagent/inventoryagentimpl" "github.com/DataDog/datadog-agent/comp/serializer/compression/compressionimpl" @@ -105,11 +106,12 @@ func MakeCommand() *cobra.Command { defaultpaths.DogstatsDLogFile, defaultpaths.StreamlogsLogFile, )), - fx.Supply(optional.NewNoneOption[autodiscovery.Component]()), + noopAutodiscover.Module(), fx.Supply(optional.NewNoneOption[workloadmeta.Component]()), fx.Supply(optional.NewNoneOption[collector.Component]()), compressionimpl.Module(), diagnosesendermanagerimpl.Module(), + nooptagger.Module(), authtokenimpl.Module(), // We need inventoryagent to fill the status page generated by the flare. inventoryagentimpl.Module(), diff --git a/cmd/trace-agent/subcommands/info/command.go b/cmd/trace-agent/subcommands/info/command.go index f30ebc0559cd8..af45099dacef0 100644 --- a/cmd/trace-agent/subcommands/info/command.go +++ b/cmd/trace-agent/subcommands/info/command.go @@ -17,6 +17,7 @@ import ( coreconfig "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/secrets" "github.com/DataDog/datadog-agent/comp/core/secrets/secretsimpl" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/comp/trace/config" "github.com/DataDog/datadog-agent/pkg/trace/info" "github.com/DataDog/datadog-agent/pkg/util/fxutil" @@ -45,6 +46,7 @@ func runTraceAgentInfoFct(params *subcommands.GlobalParams, fct interface{}) err fx.Supply(secrets.NewEnabledParams()), coreconfig.Module(), secretsimpl.Module(), + nooptagger.Module(), // TODO: (component) // fx.Supply(logimpl.ForOneShot(params.LoggerName, "off", true)), // log.Module(), diff --git a/cmd/trace-agent/test/testsuite/otlp_test.go b/cmd/trace-agent/test/testsuite/otlp_test.go index cc08366fbc0cb..253bcd5f009bf 100644 --- a/cmd/trace-agent/test/testsuite/otlp_test.go +++ b/cmd/trace-agent/test/testsuite/otlp_test.go @@ -313,6 +313,7 @@ otlp_config: endpoint: 0.0.0.0:5111 apm_config: env: my-env + compute_stats_by_span_kind: false `, port) if err := r.RunAgent([]byte(c)); err != nil { t.Fatal(err) diff --git a/comp/README.md b/comp/README.md index d500299327f9f..bcce1bd49a980 100644 --- a/comp/README.md +++ b/comp/README.md @@ -322,7 +322,7 @@ Package systemprobe is the metadata provider for system-probe process ## [comp/ndmtmp](https://pkg.go.dev/github.com/DataDog/datadog-agent/comp/ndmtmp) (Component Bundle) -*Datadog Team*: network-device-monitoring +*Datadog Team*: ndm-core Package ndmtmp implements the "ndmtmp" bundle, which exposes the default sender.Sender and the event platform forwarder. This is a temporary module @@ -334,7 +334,7 @@ Package forwarder exposes the event platform forwarder for netflow. ## [comp/netflow](https://pkg.go.dev/github.com/DataDog/datadog-agent/comp/netflow) (Component Bundle) -*Datadog Team*: network-device-monitoring +*Datadog Team*: ndm-integrations Package netflow implements the "netflow" bundle, which listens for netflow packets, processes them, and forwards relevant data to the backend. @@ -482,7 +482,7 @@ Package rctelemetryreporter provides a component that sends RC-specific metrics ## [comp/snmptraps](https://pkg.go.dev/github.com/DataDog/datadog-agent/comp/snmptraps) (Component Bundle) -*Datadog Team*: network-device-monitoring +*Datadog Team*: ndm-core Package snmptraps implements the a server that listens for SNMP trap data and sends it to the backend. @@ -602,7 +602,7 @@ Package client implements a component to send process metadata to the Cluster-Ag ### [comp/rdnsquerier](https://pkg.go.dev/github.com/DataDog/datadog-agent/comp/rdnsquerier) -*Datadog Team*: network-device-monitoring +*Datadog Team*: ndm-integrations Package rdnsquerier provides the reverse DNS querier component. @@ -614,6 +614,6 @@ Package compression provides a compression implementation based on the configura ### [comp/snmpscan](https://pkg.go.dev/github.com/DataDog/datadog-agent/comp/snmpscan) -*Datadog Team*: network-device-monitoring +*Datadog Team*: ndm-core Package snmpscan is a light component that can be used to perform a scan or a walk of a particular device diff --git a/comp/aggregator/bundle_test.go b/comp/aggregator/bundle_test.go index d1a4cb2d4ecbd..387d88ad8e375 100644 --- a/comp/aggregator/bundle_test.go +++ b/comp/aggregator/bundle_test.go @@ -10,6 +10,7 @@ import ( "github.com/DataDog/datadog-agent/comp/aggregator/demultiplexer/demultiplexerimpl" "github.com/DataDog/datadog-agent/comp/core" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" orchestratorForwarderImpl "github.com/DataDog/datadog-agent/comp/forwarder/orchestrator/orchestratorimpl" @@ -24,5 +25,6 @@ func TestBundleDependencies(t *testing.T) { defaultforwarder.MockModule(), orchestratorForwarderImpl.MockModule(), eventplatformimpl.MockModule(), + nooptagger.Module(), ) } diff --git a/comp/aggregator/demultiplexer/demultiplexerimpl/demultiplexer.go b/comp/aggregator/demultiplexer/demultiplexerimpl/demultiplexer.go index d51c825f847d1..11e6b774524a7 100644 --- a/comp/aggregator/demultiplexer/demultiplexerimpl/demultiplexer.go +++ b/comp/aggregator/demultiplexer/demultiplexerimpl/demultiplexer.go @@ -16,6 +16,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/config" log "github.com/DataDog/datadog-agent/comp/core/log/def" "github.com/DataDog/datadog-agent/comp/core/status" + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" orchestratorforwarder "github.com/DataDog/datadog-agent/comp/forwarder/orchestrator" @@ -42,6 +43,7 @@ type dependencies struct { OrchestratorForwarder orchestratorforwarder.Component EventPlatformForwarder eventplatform.Component Compressor compression.Component + Tagger tagger.Component Params Params } @@ -85,7 +87,9 @@ func newDemultiplexer(deps dependencies) (provides, error) { options, deps.EventPlatformForwarder, deps.Compressor, - hostnameDetected) + deps.Tagger, + hostnameDetected, + ) demultiplexer := demultiplexer{ AgentDemultiplexer: agentDemultiplexer, } diff --git a/comp/aggregator/demultiplexer/demultiplexerimpl/status_test.go b/comp/aggregator/demultiplexer/demultiplexerimpl/status_test.go index 8ec83cb0cddf0..cecacf1aa9bb0 100644 --- a/comp/aggregator/demultiplexer/demultiplexerimpl/status_test.go +++ b/comp/aggregator/demultiplexer/demultiplexerimpl/status_test.go @@ -15,6 +15,8 @@ import ( "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/status" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" "github.com/DataDog/datadog-agent/comp/forwarder/orchestrator/orchestratorimpl" @@ -53,12 +55,17 @@ func TestStatusOutPut(t *testing.T) { }}, } + mockTagger := taggerimpl.SetupFakeTagger(t) + deps := fxutil.Test[dependencies](t, fx.Options( core.MockBundle(), compressionimpl.MockModule(), defaultforwarder.MockModule(), orchestratorimpl.MockModule(), eventplatformimpl.MockModule(), + fx.Provide(func() tagger.Component { + return mockTagger + }), fx.Supply( Params{ continueOnMissingHostname: true, diff --git a/comp/aggregator/demultiplexer/demultiplexerimpl/test_agent_demultiplexer.go b/comp/aggregator/demultiplexer/demultiplexerimpl/test_agent_demultiplexer.go index cec4437ab09f8..a227f78af631b 100644 --- a/comp/aggregator/demultiplexer/demultiplexerimpl/test_agent_demultiplexer.go +++ b/comp/aggregator/demultiplexer/demultiplexerimpl/test_agent_demultiplexer.go @@ -14,6 +14,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/hostname" log "github.com/DataDog/datadog-agent/comp/core/log/def" + "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" @@ -184,6 +185,6 @@ func initTestAgentDemultiplexerWithFlushInterval(log log.Component, hostname hos sharedForwarder := defaultforwarder.NewDefaultForwarder(pkgconfigsetup.Datadog(), log, sharedForwarderOptions) orchestratorForwarder := optional.NewOption[defaultforwarder.Forwarder](defaultforwarder.NoopForwarder{}) eventPlatformForwarder := optional.NewOptionPtr[eventplatform.Forwarder](eventplatformimpl.NewNoopEventPlatformForwarder(hostname)) - demux := aggregator.InitAndStartAgentDemultiplexer(log, sharedForwarder, &orchestratorForwarder, opts, eventPlatformForwarder, compressor, "hostname") + demux := aggregator.InitAndStartAgentDemultiplexer(log, sharedForwarder, &orchestratorForwarder, opts, eventPlatformForwarder, compressor, noopimpl.NewTaggerClient(), "hostname") return NewTestAgentDemultiplexer(demux) } diff --git a/comp/aggregator/diagnosesendermanager/diagnosesendermanagerimpl/sendermanager.go b/comp/aggregator/diagnosesendermanager/diagnosesendermanagerimpl/sendermanager.go index 8e68564313db2..8ac9a86d7ec27 100644 --- a/comp/aggregator/diagnosesendermanager/diagnosesendermanagerimpl/sendermanager.go +++ b/comp/aggregator/diagnosesendermanager/diagnosesendermanagerimpl/sendermanager.go @@ -15,6 +15,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/hostname" log "github.com/DataDog/datadog-agent/comp/core/log/def" + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" @@ -37,6 +38,7 @@ type dependencies struct { Config config.Component Hostname hostname.Component Compressor compression.Component + Tagger tagger.Component } type diagnoseSenderManager struct { @@ -77,6 +79,7 @@ func (sender *diagnoseSenderManager) LazyGetSenderManager() (sender.SenderManage opts, eventPlatformForwarder, sender.deps.Compressor, + sender.deps.Tagger, hostnameDetected) sender.senderManager.Set(senderManager) diff --git a/comp/api/api/apiimpl/grpc.go b/comp/api/api/apiimpl/grpc.go index da998b0e6ecb9..9f9cd16a57d04 100644 --- a/comp/api/api/apiimpl/grpc.go +++ b/comp/api/api/apiimpl/grpc.go @@ -99,7 +99,7 @@ func (s *serverSecure) DogstatsdSetTaggerState(_ context.Context, req *pb.Tagger // Reset and return if no state pushed if req == nil || req.State == nil { log.Debugf("API: empty request or state") - tagger.ResetCaptureTagger() + s.taggerComp.ResetCaptureTagger() s.pidMap.SetPidMap(nil) return &pb.TaggerStateResponse{Loaded: false}, nil } @@ -131,7 +131,7 @@ func (s *serverSecure) DogstatsdSetTaggerState(_ context.Context, req *pb.Tagger taggerReplay.LoadState(state) log.Debugf("API: setting capture state tagger") - tagger.SetNewCaptureTagger(taggerReplay) + s.taggerComp.SetNewCaptureTagger(taggerReplay) s.pidMap.SetPidMap(req.PidMap) log.Debugf("API: loaded state successfully") diff --git a/comp/api/api/apiimpl/internal/agent/agent.go b/comp/api/api/apiimpl/internal/agent/agent.go index 58624ec1c82ed..05faf3e7b7334 100644 --- a/comp/api/api/apiimpl/internal/agent/agent.go +++ b/comp/api/api/apiimpl/internal/agent/agent.go @@ -10,7 +10,6 @@ package agent import ( "encoding/json" - "errors" "io" "net/http" "sort" @@ -24,6 +23,7 @@ import ( "github.com/DataDog/datadog-agent/comp/collector/collector" "github.com/DataDog/datadog-agent/comp/core/autodiscovery" "github.com/DataDog/datadog-agent/comp/core/secrets" + "github.com/DataDog/datadog-agent/comp/core/tagger" httputils "github.com/DataDog/datadog-agent/pkg/util/http" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" @@ -46,6 +46,7 @@ func SetupHandlers( collector optional.Option[collector.Component], ac autodiscovery.Component, providers []api.EndpointProvider, + tagger tagger.Component, ) *mux.Router { // Register the handlers from the component providers sort.Slice(providers, func(i, j int) bool { return providers[i].Route() < providers[j].Route() }) @@ -58,7 +59,7 @@ func SetupHandlers( r.HandleFunc("/{component}/status", componentStatusHandler).Methods("POST") r.HandleFunc("/{component}/configs", componentConfigHandler).Methods("GET") r.HandleFunc("/diagnose", func(w http.ResponseWriter, r *http.Request) { - diagnoseDeps := diagnose.NewSuitesDeps(senderManager, collector, secretResolver, optional.NewOption(wmeta), optional.NewOption[autodiscovery.Component](ac)) + diagnoseDeps := diagnose.NewSuitesDeps(senderManager, collector, secretResolver, optional.NewOption(wmeta), ac, tagger) getDiagnose(w, r, diagnoseDeps) }).Methods("POST") @@ -146,12 +147,7 @@ func getDiagnose(w http.ResponseWriter, r *http.Request, diagnoseDeps diagnose.S if ok { diagnoseResult, err = diagnose.RunInAgentProcess(diagCfg, diagnose.NewSuitesDepsInAgentProcess(collector)) } else { - ac, ok := diagnoseDeps.AC.Get() - if ok { - diagnoseResult, err = diagnose.RunInCLIProcess(diagCfg, diagnose.NewSuitesDepsInCLIProcess(diagnoseDeps.SenderManager, diagnoseDeps.SecretResolver, diagnoseDeps.WMeta, ac)) - } else { - err = errors.New("collector or autoDiscovery not found") - } + diagnoseResult, err = diagnose.RunInCLIProcess(diagCfg, diagnose.NewSuitesDepsInCLIProcess(diagnoseDeps.SenderManager, diagnoseDeps.SecretResolver, diagnoseDeps.WMeta, diagnoseDeps.AC, diagnoseDeps.Tagger)) } if err != nil { httputils.SetJSONError(w, log.Errorf("Running diagnose in Agent process failed: %s", err), 500) diff --git a/comp/api/api/apiimpl/internal/agent/agent_test.go b/comp/api/api/apiimpl/internal/agent/agent_test.go index a4943394dc043..7209428009126 100644 --- a/comp/api/api/apiimpl/internal/agent/agent_test.go +++ b/comp/api/api/apiimpl/internal/agent/agent_test.go @@ -126,6 +126,7 @@ func setupRoutes(t *testing.T) *mux.Router { deps.Collector, deps.Ac, deps.EndpointProviders, + deps.Tagger, ) return router diff --git a/comp/api/api/apiimpl/server_cmd.go b/comp/api/api/apiimpl/server_cmd.go index 75db2d6815de3..57530c12c9d37 100644 --- a/comp/api/api/apiimpl/server_cmd.go +++ b/comp/api/api/apiimpl/server_cmd.go @@ -120,6 +120,7 @@ func (server *apiServer) startCMDServer( server.collector, server.autoConfig, server.endpointProviders, + server.taggerComp, ))) cmdMux.Handle("/check/", http.StripPrefix("/check", check.SetupHandlers(checkMux))) cmdMux.Handle("/", gwmux) diff --git a/comp/checks/bundle_test.go b/comp/checks/bundle_test.go index 934e475914f3a..1a54dabf68530 100644 --- a/comp/checks/bundle_test.go +++ b/comp/checks/bundle_test.go @@ -10,17 +10,23 @@ package checks import ( "testing" + "go.uber.org/fx" + "github.com/DataDog/datadog-agent/comp/core" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" comptraceconfig "github.com/DataDog/datadog-agent/comp/trace/config" "github.com/DataDog/datadog-agent/pkg/util/crashreport" "github.com/DataDog/datadog-agent/pkg/util/fxutil" - "go.uber.org/fx" ) func TestBundleDependencies(t *testing.T) { + fakeTagger := taggerimpl.SetupFakeTagger(t) + fxutil.TestBundle(t, Bundle(), comptraceconfig.Module(), core.MockBundle(), + fx.Provide(func() tagger.Component { return fakeTagger }), fx.Supply(core.BundleParams{}), fx.Supply(crashreport.WinCrashReporter{}), ) diff --git a/comp/collector/collector/collectorimpl/agent_check_metadata.go b/comp/collector/collector/collectorimpl/agent_check_metadata.go index 73b7b22677d35..987d4a0e449a8 100644 --- a/comp/collector/collector/collectorimpl/agent_check_metadata.go +++ b/comp/collector/collector/collectorimpl/agent_check_metadata.go @@ -55,12 +55,12 @@ func (p *Payload) SplitPayload(_ int) ([]marshaler.AbstractMarshaler, error) { // GetPayload builds a payload of all the agentchecks metadata func (c *collectorImpl) GetPayload(ctx context.Context) *Payload { - hostname, _ := hostname.Get(ctx) + hostnameData, _ := hostname.Get(ctx) meta := hostMetadataUtils.GetMetaFromCache(ctx, c.config) - meta.Hostname = hostname + meta.Hostname = hostnameData - cp := hostMetadataUtils.GetCommonPayload(hostname, c.config) + cp := hostMetadataUtils.GetCommonPayload(hostnameData, c.config) payload := &Payload{ CommonPayload: *cp, Meta: *meta, diff --git a/comp/core/agenttelemetry/impl/sender.go b/comp/core/agenttelemetry/impl/sender.go index a11e0312790e0..eaf1125d6a2e7 100644 --- a/comp/core/agenttelemetry/impl/sender.go +++ b/comp/core/agenttelemetry/impl/sender.go @@ -336,9 +336,9 @@ func (s *senderImpl) flushSession(ss *senderSession) error { // Log return status (and URL if unsuccessful) if resp.StatusCode >= 200 && resp.StatusCode < 300 { - s.logComp.Infof("Telemetery enpoint response status: %s, status code: %d", resp.Status, resp.StatusCode) + s.logComp.Debugf("Telemetery enpoint response status: %s, status code: %d", resp.Status, resp.StatusCode) } else { - s.logComp.Warnf("Telemetery enpoint response status: %s, status code: %d, url: %s", resp.Status, resp.StatusCode, url) + s.logComp.Debugf("Telemetery enpoint response status: %s, status code: %d, url: %s", resp.Status, resp.StatusCode, url) } } diff --git a/comp/core/autodiscovery/autodiscoveryimpl/autoconfig.go b/comp/core/autodiscovery/autodiscoveryimpl/autoconfig.go index 48047e5b06d0f..3849294925160 100644 --- a/comp/core/autodiscovery/autodiscoveryimpl/autoconfig.go +++ b/comp/core/autodiscovery/autodiscoveryimpl/autoconfig.go @@ -126,13 +126,12 @@ func newProvides(deps dependencies) provides { var _ autodiscovery.Component = (*AutoConfig)(nil) type listenerCandidate struct { - factory listeners.ServiceListenerFactory - config listeners.Config - telemetryStore *acTelemetry.Store + factory listeners.ServiceListenerFactory + options listeners.ServiceListernerDeps } func (l *listenerCandidate) try() (listeners.ServiceListener, error) { - return l.factory(l.config, l.telemetryStore) + return l.factory(l.options) } // newAutoConfig creates an AutoConfig instance and starts it. @@ -339,7 +338,7 @@ func (ac *AutoConfig) fillFlare(fb flaretypes.FlareBuilder) error { // Usually, Start and Stop methods should not be in the component interface as it should be handled using Lifecycle hooks. // We make exceptions here because we need to disable it at runtime. func (ac *AutoConfig) Start() { - listeners.RegisterListeners(ac.serviceListenerFactories, ac.wmeta) + listeners.RegisterListeners(ac.serviceListenerFactories) providers.RegisterProviders(ac.providerCatalog) setupAcErrors() ac.started = true @@ -507,7 +506,14 @@ func (ac *AutoConfig) addListenerCandidates(listenerConfigs []pkgconfigsetup.Lis continue } log.Debugf("Listener %s was registered", c.Name) - ac.listenerCandidates[c.Name] = &listenerCandidate{factory: factory, config: &c, telemetryStore: ac.telemetryStore} + factoryOptions := listeners.ServiceListernerDeps{ + Config: &c, + Telemetry: ac.telemetryStore, + Tagger: ac.taggerComp, + Wmeta: ac.wmeta, + } + + ac.listenerCandidates[c.Name] = &listenerCandidate{factory: factory, options: factoryOptions} } } @@ -728,33 +734,3 @@ func configType(c integration.Config) string { return "unknown" } - -// optionalModuleDeps has an optional tagger component -type optionalModuleDeps struct { - fx.In - Lc fx.Lifecycle - Config configComponent.Component - Log logComp.Component - TaggerComp optional.Option[tagger.Component] - Secrets secrets.Component - WMeta optional.Option[workloadmeta.Component] - Telemetry telemetry.Component -} - -// OptionalModule defines the fx options when ac should be used as an optional and not started -func OptionalModule() fxutil.Module { - return fxutil.Component( - fx.Provide( - newOptionalAutoConfig, - )) -} - -// newOptionalAutoConfig creates an optional AutoConfig instance if tagger is available -func newOptionalAutoConfig(deps optionalModuleDeps) optional.Option[autodiscovery.Component] { - taggerComp, ok := deps.TaggerComp.Get() - if !ok { - return optional.NewNoneOption[autodiscovery.Component]() - } - return optional.NewOption[autodiscovery.Component]( - createNewAutoConfig(scheduler.NewController(), deps.Secrets, deps.WMeta, taggerComp, deps.Log, deps.Telemetry)) -} diff --git a/comp/core/autodiscovery/autodiscoveryimpl/autoconfig_mock.go b/comp/core/autodiscovery/autodiscoveryimpl/autoconfig_mock.go index 89913817367ae..3f69ebd0918e4 100644 --- a/comp/core/autodiscovery/autodiscoveryimpl/autoconfig_mock.go +++ b/comp/core/autodiscovery/autodiscoveryimpl/autoconfig_mock.go @@ -16,6 +16,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/autodiscovery" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/scheduler" log "github.com/DataDog/datadog-agent/comp/core/log/def" + "github.com/DataDog/datadog-agent/comp/core/secrets" "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/telemetry" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" @@ -40,6 +41,7 @@ type mockdependencies struct { TaggerComp tagger.Mock LogsComp log.Component Telemetry telemetry.Component + Secrets secrets.Component } type mockprovides struct { @@ -50,7 +52,7 @@ type mockprovides struct { } func newMockAutoConfig(deps mockdependencies) mockprovides { - ac := createNewAutoConfig(deps.Params.Scheduler, nil, deps.WMeta, deps.TaggerComp, deps.LogsComp, deps.Telemetry) + ac := createNewAutoConfig(deps.Params.Scheduler, deps.Secrets, deps.WMeta, deps.TaggerComp, deps.LogsComp, deps.Telemetry) return mockprovides{ Comp: ac, Endpoint: api.NewAgentEndpointProvider(ac.mockHandleRequest, "/config-check", "GET"), diff --git a/comp/core/autodiscovery/autodiscoveryimpl/autoconfig_test.go b/comp/core/autodiscovery/autodiscoveryimpl/autoconfig_test.go index 61c5abe56402d..dadc4cc1a3039 100644 --- a/comp/core/autodiscovery/autodiscoveryimpl/autoconfig_test.go +++ b/comp/core/autodiscovery/autodiscoveryimpl/autoconfig_test.go @@ -26,7 +26,6 @@ import ( "github.com/DataDog/datadog-agent/comp/core/autodiscovery/providers" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/providers/names" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/scheduler" - acTelemetry "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" log "github.com/DataDog/datadog-agent/comp/core/log/def" "github.com/DataDog/datadog-agent/comp/core/secrets" "github.com/DataDog/datadog-agent/comp/core/tagger" @@ -83,7 +82,7 @@ func (l *MockListener) Stop() { l.stopReceived = true } -func (l *MockListener) fakeFactory(listeners.Config, *acTelemetry.Store) (listeners.ServiceListener, error) { +func (l *MockListener) fakeFactory(listeners.ServiceListernerDeps) (listeners.ServiceListener, error) { return l, nil } @@ -99,7 +98,7 @@ type factoryMock struct { returnError error } -func (o *factoryMock) make(listeners.Config, *acTelemetry.Store) (listeners.ServiceListener, error) { +func (o *factoryMock) make(listeners.ServiceListernerDeps) (listeners.ServiceListener, error) { o.Lock() defer o.Unlock() if o.callChan != nil { diff --git a/comp/core/autodiscovery/listeners/cloudfoundry.go b/comp/core/autodiscovery/listeners/cloudfoundry.go index d82436fba67bb..0b53e200f1c7b 100644 --- a/comp/core/autodiscovery/listeners/cloudfoundry.go +++ b/comp/core/autodiscovery/listeners/cloudfoundry.go @@ -16,7 +16,6 @@ import ( "time" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" - "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" "github.com/DataDog/datadog-agent/pkg/util/cloudproviders/cloudfoundry" "github.com/DataDog/datadog-agent/pkg/util/containers" "github.com/DataDog/datadog-agent/pkg/util/log" @@ -51,7 +50,7 @@ type CloudFoundryService struct { var _ Service = &CloudFoundryService{} // NewCloudFoundryListener creates a CloudFoundryListener -func NewCloudFoundryListener(Config, *telemetry.Store) (ServiceListener, error) { +func NewCloudFoundryListener(ServiceListernerDeps) (ServiceListener, error) { bbsCache, err := cloudfoundry.GetGlobalBBSCache() if err != nil { return nil, err diff --git a/comp/core/autodiscovery/listeners/container.go b/comp/core/autodiscovery/listeners/container.go index d4f8ebc52b0d4..8be5cdd24154c 100644 --- a/comp/core/autodiscovery/listeners/container.go +++ b/comp/core/autodiscovery/listeners/container.go @@ -14,7 +14,6 @@ import ( "time" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/common/utils" - "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/types" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" @@ -23,7 +22,6 @@ import ( pkgcontainersimage "github.com/DataDog/datadog-agent/pkg/util/containers/image" "github.com/DataDog/datadog-agent/pkg/util/docker" "github.com/DataDog/datadog-agent/pkg/util/log" - "github.com/DataDog/datadog-agent/pkg/util/optional" ) const ( @@ -35,25 +33,27 @@ const ( // workloadmeta store. type ContainerListener struct { workloadmetaListener + tagger tagger.Component } // NewContainerListener returns a new ContainerListener. -func NewContainerListener(_ Config, wmeta optional.Option[workloadmeta.Component], telemetryStore *telemetry.Store) (ServiceListener, error) { +func NewContainerListener(options ServiceListernerDeps) (ServiceListener, error) { const name = "ad-containerlistener" l := &ContainerListener{} filter := workloadmeta.NewFilterBuilder(). SetSource(workloadmeta.SourceAll). AddKind(workloadmeta.KindContainer).Build() - wmetaInstance, ok := wmeta.Get() + wmetaInstance, ok := options.Wmeta.Get() if !ok { return nil, errors.New("workloadmeta store is not initialized") } var err error - l.workloadmetaListener, err = newWorkloadmetaListener(name, filter, l.createContainerService, wmetaInstance, telemetryStore) + l.workloadmetaListener, err = newWorkloadmetaListener(name, filter, l.createContainerService, wmetaInstance, options.Telemetry) if err != nil { return nil, err } + l.tagger = options.Tagger return l, nil } @@ -114,7 +114,7 @@ func (l *ContainerListener) createContainerService(entity workloadmeta.Entity) { svc := &service{ entity: container, - tagsHash: tagger.GetEntityHash(types.NewEntityID(types.ContainerID, container.ID), tagger.ChecksCardinality()), + tagsHash: l.tagger.GetEntityHash(types.NewEntityID(types.ContainerID, container.ID), l.tagger.ChecksCardinality()), adIdentifiers: computeContainerServiceIDs( containers.BuildEntityName(string(container.Runtime), container.ID), containerImg.RawName, @@ -123,6 +123,7 @@ func (l *ContainerListener) createContainerService(entity workloadmeta.Entity) { ports: ports, pid: container.PID, hostname: container.Hostname, + tagger: l.tagger, } if pod != nil { diff --git a/comp/core/autodiscovery/listeners/container_nop.go b/comp/core/autodiscovery/listeners/container_nop.go index e65adc04de7cc..0204f92003b8b 100644 --- a/comp/core/autodiscovery/listeners/container_nop.go +++ b/comp/core/autodiscovery/listeners/container_nop.go @@ -7,12 +7,4 @@ package listeners -import ( - "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" - workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" - "github.com/DataDog/datadog-agent/pkg/util/optional" -) - -type noopServiceListenerFactory func(c Config, wmeta optional.Option[workloadmeta.Component], telemetryStore *telemetry.Store) (ServiceListener, error) - -var NewContainerListener noopServiceListenerFactory +var NewContainerListener func(ServiceListernerDeps) (ServiceListener, error) diff --git a/comp/core/autodiscovery/listeners/container_test.go b/comp/core/autodiscovery/listeners/container_test.go index d496a701b10c9..825b9ed2bd811 100644 --- a/comp/core/autodiscovery/listeners/container_test.go +++ b/comp/core/autodiscovery/listeners/container_test.go @@ -14,8 +14,11 @@ import ( "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetamock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/mock" + "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) func TestCreateContainerService(t *testing.T) { @@ -159,6 +162,8 @@ func TestCreateContainerService(t *testing.T) { Ready: false, } + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + tests := []struct { name string container *workloadmeta.Container @@ -171,6 +176,7 @@ func TestCreateContainerService(t *testing.T) { expectedServices: map[string]wlmListenerSvc{ "container://foobarquux": { service: &service{ + tagger: taggerComponent, entity: basicContainer, adIdentifiers: []string{ "docker://foobarquux", @@ -207,6 +213,7 @@ func TestCreateContainerService(t *testing.T) { expectedServices: map[string]wlmListenerSvc{ "container://foobarquux": { service: &service{ + tagger: taggerComponent, entity: runningContainerWithFinishedAtTime, adIdentifiers: []string{ "docker://foobarquux", @@ -226,6 +233,7 @@ func TestCreateContainerService(t *testing.T) { expectedServices: map[string]wlmListenerSvc{ "container://foobarquux": { service: &service{ + tagger: taggerComponent, entity: multiplePortsContainer, adIdentifiers: []string{ "docker://foobarquux", @@ -254,6 +262,7 @@ func TestCreateContainerService(t *testing.T) { expectedServices: map[string]wlmListenerSvc{ "container://foo": { service: &service{ + tagger: taggerComponent, entity: kubernetesContainer, adIdentifiers: []string{ "docker://foo", @@ -277,7 +286,7 @@ func TestCreateContainerService(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - listener, wlm := newContainerListener(t) + listener, wlm := newContainerListener(t, taggerComponent) if tt.container != nil { listener.Store().(workloadmetamock.Mock).Set(tt.container) @@ -348,8 +357,8 @@ func TestComputeContainerServiceIDs(t *testing.T) { } } -func newContainerListener(t *testing.T) (*ContainerListener, *testWorkloadmetaListener) { +func newContainerListener(t *testing.T, tagger tagger.Component) (*ContainerListener, *testWorkloadmetaListener) { wlm := newTestWorkloadmetaListener(t) - return &ContainerListener{workloadmetaListener: wlm}, wlm + return &ContainerListener{workloadmetaListener: wlm, tagger: tagger}, wlm } diff --git a/comp/core/autodiscovery/listeners/dbm_aurora.go b/comp/core/autodiscovery/listeners/dbm_aurora.go index 062a7f24a400d..bce4704331fa1 100644 --- a/comp/core/autodiscovery/listeners/dbm_aurora.go +++ b/comp/core/autodiscovery/listeners/dbm_aurora.go @@ -16,7 +16,6 @@ import ( "time" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" - "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" "github.com/DataDog/datadog-agent/pkg/databasemonitoring/aws" dbmconfig "github.com/DataDog/datadog-agent/pkg/databasemonitoring/config" "github.com/DataDog/datadog-agent/pkg/util/containers" @@ -68,7 +67,7 @@ type DBMAuroraService struct { } // NewDBMAuroraListener returns a new DBMAuroraListener -func NewDBMAuroraListener(Config, *telemetry.Store) (ServiceListener, error) { +func NewDBMAuroraListener(ServiceListernerDeps) (ServiceListener, error) { config, err := dbmconfig.NewAuroraAutodiscoveryConfig() if err != nil { return nil, err diff --git a/comp/core/autodiscovery/listeners/environment.go b/comp/core/autodiscovery/listeners/environment.go index f49152d95b106..765a4bb6d391c 100644 --- a/comp/core/autodiscovery/listeners/environment.go +++ b/comp/core/autodiscovery/listeners/environment.go @@ -9,7 +9,6 @@ import ( "context" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" - "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" "github.com/DataDog/datadog-agent/pkg/config/env" "github.com/DataDog/datadog-agent/pkg/util/containers" "github.com/DataDog/datadog-agent/pkg/util/log" @@ -29,7 +28,7 @@ type EnvironmentService struct { var _ Service = &EnvironmentService{} // NewEnvironmentListener creates an EnvironmentListener -func NewEnvironmentListener(Config, *telemetry.Store) (ServiceListener, error) { +func NewEnvironmentListener(ServiceListernerDeps) (ServiceListener, error) { return &EnvironmentListener{}, nil } diff --git a/comp/core/autodiscovery/listeners/kube_endpoints.go b/comp/core/autodiscovery/listeners/kube_endpoints.go index c3ac90d6ea208..bef63091c68fb 100644 --- a/comp/core/autodiscovery/listeners/kube_endpoints.go +++ b/comp/core/autodiscovery/listeners/kube_endpoints.go @@ -66,7 +66,7 @@ type KubeEndpointService struct { var _ Service = &KubeEndpointService{} // NewKubeEndpointsListener returns the kube endpoints implementation of the ServiceListener interface -func NewKubeEndpointsListener(conf Config, telemetryStore *telemetry.Store) (ServiceListener, error) { +func NewKubeEndpointsListener(options ServiceListernerDeps) (ServiceListener, error) { // Using GetAPIClient (no wait) as Client should already be initialized by Cluster Agent main entrypoint before ac, err := apiserver.GetAPIClient() if err != nil { @@ -95,9 +95,9 @@ func NewKubeEndpointsListener(conf Config, telemetryStore *telemetry.Store) (Ser serviceInformer: serviceInformer, serviceLister: serviceInformer.Lister(), promInclAnnot: getPrometheusIncludeAnnotations(), - targetAllEndpoints: conf.IsProviderEnabled(names.KubeEndpointsFileRegisterName), + targetAllEndpoints: options.Config.IsProviderEnabled(names.KubeEndpointsFileRegisterName), containerFilters: containerFilters, - telemetryStore: telemetryStore, + telemetryStore: options.Telemetry, }, nil } diff --git a/comp/core/autodiscovery/listeners/kube_services.go b/comp/core/autodiscovery/listeners/kube_services.go index c9019e21b8b30..ea8d93ba1e2f8 100644 --- a/comp/core/autodiscovery/listeners/kube_services.go +++ b/comp/core/autodiscovery/listeners/kube_services.go @@ -81,7 +81,7 @@ func isServiceAnnotated(ksvc *v1.Service, annotationKey string) bool { } // NewKubeServiceListener returns the kube service implementation of the ServiceListener interface -func NewKubeServiceListener(conf Config, telemetryStore *telemetry.Store) (ServiceListener, error) { +func NewKubeServiceListener(options ServiceListernerDeps) (ServiceListener, error) { // Using GetAPIClient (no wait) as Client should already be initialized by Cluster Agent main entrypoint before ac, err := apiserver.GetAPIClient() if err != nil { @@ -102,9 +102,9 @@ func NewKubeServiceListener(conf Config, telemetryStore *telemetry.Store) (Servi services: make(map[k8stypes.UID]Service), informer: servicesInformer, promInclAnnot: getPrometheusIncludeAnnotations(), - targetAllServices: conf.IsProviderEnabled(names.KubeServicesFileRegisterName), + targetAllServices: options.Config.IsProviderEnabled(names.KubeServicesFileRegisterName), containerFilters: containerFilters, - telemetryStore: telemetryStore, + telemetryStore: options.Telemetry, }, nil } diff --git a/comp/core/autodiscovery/listeners/kubelet.go b/comp/core/autodiscovery/listeners/kubelet.go index e685b3b085b55..c713eb69bee83 100644 --- a/comp/core/autodiscovery/listeners/kubelet.go +++ b/comp/core/autodiscovery/listeners/kubelet.go @@ -13,7 +13,6 @@ import ( "time" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/common/utils" - "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/common" "github.com/DataDog/datadog-agent/comp/core/tagger/types" @@ -22,17 +21,17 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/containers" "github.com/DataDog/datadog-agent/pkg/util/kubernetes/kubelet" "github.com/DataDog/datadog-agent/pkg/util/log" - "github.com/DataDog/datadog-agent/pkg/util/optional" ) // KubeletListener listens to pod creation through a subscription // to the workloadmeta store. type KubeletListener struct { workloadmetaListener + tagger tagger.Component } // NewKubeletListener returns a new KubeletListener. -func NewKubeletListener(_ Config, wmeta optional.Option[workloadmeta.Component], telemetryStore *telemetry.Store) (ServiceListener, error) { +func NewKubeletListener(options ServiceListernerDeps) (ServiceListener, error) { const name = "ad-kubeletlistener" l := &KubeletListener{} @@ -41,15 +40,16 @@ func NewKubeletListener(_ Config, wmeta optional.Option[workloadmeta.Component], AddKind(workloadmeta.KindKubernetesPod). Build() - wmetaInstance, ok := wmeta.Get() + wmetaInstance, ok := options.Wmeta.Get() if !ok { return nil, errors.New("workloadmeta store is not initialized") } var err error - l.workloadmetaListener, err = newWorkloadmetaListener(name, filter, l.processPod, wmetaInstance, telemetryStore) + l.workloadmetaListener, err = newWorkloadmetaListener(name, filter, l.processPod, wmetaInstance, options.Telemetry) if err != nil { return nil, err } + l.tagger = options.Tagger return l, nil } @@ -96,11 +96,12 @@ func (l *KubeletListener) createPodService( taggerEntityID := common.BuildTaggerEntityID(pod.GetID()) svc := &service{ entity: pod, - tagsHash: tagger.GetEntityHash(taggerEntityID, tagger.ChecksCardinality()), + tagsHash: l.tagger.GetEntityHash(taggerEntityID, l.tagger.ChecksCardinality()), adIdentifiers: []string{entity}, hosts: map[string]string{"pod": pod.IP}, ports: ports, ready: true, + tagger: l.tagger, } svcID := buildSvcID(pod.GetID()) @@ -158,7 +159,7 @@ func (l *KubeletListener) createContainerService( entity := containers.BuildEntityName(string(container.Runtime), container.ID) svc := &service{ entity: container, - tagsHash: tagger.GetEntityHash(types.NewEntityID(types.ContainerID, container.ID), tagger.ChecksCardinality()), + tagsHash: l.tagger.GetEntityHash(types.NewEntityID(types.ContainerID, container.ID), l.tagger.ChecksCardinality()), ready: pod.Ready, ports: ports, extraConfig: map[string]string{ @@ -184,6 +185,7 @@ func (l *KubeletListener) createContainerService( containerImg.RawName, pod.Namespace, ), + tagger: l.tagger, } adIdentifier := containerName diff --git a/comp/core/autodiscovery/listeners/kubelet_nop.go b/comp/core/autodiscovery/listeners/kubelet_nop.go index 116e271c6a484..a2ba0d736e4c4 100644 --- a/comp/core/autodiscovery/listeners/kubelet_nop.go +++ b/comp/core/autodiscovery/listeners/kubelet_nop.go @@ -7,4 +7,4 @@ package listeners -var NewKubeletListener noopServiceListenerFactory +var NewKubeletListener func(ServiceListernerDeps) (ServiceListener, error) diff --git a/comp/core/autodiscovery/listeners/kubelet_test.go b/comp/core/autodiscovery/listeners/kubelet_test.go index ff3193712aa85..d5823f07edf97 100644 --- a/comp/core/autodiscovery/listeners/kubelet_test.go +++ b/comp/core/autodiscovery/listeners/kubelet_test.go @@ -12,7 +12,10 @@ import ( "testing" "time" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" + "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) const ( @@ -36,6 +39,9 @@ func TestKubeletCreatePodService(t *testing.T) { }, IP: "127.0.0.1", } + + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + tests := []struct { name string pod *workloadmeta.KubernetesPod @@ -81,7 +87,8 @@ func TestKubeletCreatePodService(t *testing.T) { hosts: map[string]string{ "pod": "127.0.0.1", }, - ready: true, + ready: true, + tagger: taggerComponent, }, }, }, @@ -90,7 +97,7 @@ func TestKubeletCreatePodService(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - listener, wlm := newKubeletListener(t) + listener, wlm := newKubeletListener(t, taggerComponent) listener.createPodService(tt.pod, tt.containers) @@ -219,6 +226,8 @@ func TestKubeletCreateContainerService(t *testing.T) { Runtime: workloadmeta.ContainerRuntimeDocker, } + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + tests := []struct { name string pod *workloadmeta.KubernetesPod @@ -254,6 +263,7 @@ func TestKubeletCreateContainerService(t *testing.T) { "pod_name": podName, "pod_uid": podID, }, + tagger: taggerComponent, }, }, }, @@ -286,6 +296,7 @@ func TestKubeletCreateContainerService(t *testing.T) { "pod_name": podName, "pod_uid": podID, }, + tagger: taggerComponent, }, }, }, @@ -340,6 +351,7 @@ func TestKubeletCreateContainerService(t *testing.T) { "pod_name": podName, "pod_uid": podID, }, + tagger: taggerComponent, }, }, }, @@ -380,6 +392,7 @@ func TestKubeletCreateContainerService(t *testing.T) { "pod_name": podName, "pod_uid": podID, }, + tagger: taggerComponent, }, }, }, @@ -413,6 +426,7 @@ func TestKubeletCreateContainerService(t *testing.T) { "pod_name": podName, "pod_uid": podID, }, + tagger: taggerComponent, }, }, }, @@ -458,6 +472,7 @@ func TestKubeletCreateContainerService(t *testing.T) { "pod_uid": podID, }, metricsExcluded: true, + tagger: taggerComponent, }, }, }, @@ -492,6 +507,7 @@ func TestKubeletCreateContainerService(t *testing.T) { "pod_uid": podID, }, logsExcluded: true, + tagger: taggerComponent, }, }, }, @@ -500,7 +516,7 @@ func TestKubeletCreateContainerService(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - listener, wlm := newKubeletListener(t) + listener, wlm := newKubeletListener(t, taggerComponent) listener.createContainerService(tt.pod, tt.podContainer, tt.container) @@ -509,8 +525,8 @@ func TestKubeletCreateContainerService(t *testing.T) { } } -func newKubeletListener(t *testing.T) (*KubeletListener, *testWorkloadmetaListener) { +func newKubeletListener(t *testing.T, tagger tagger.Component) (*KubeletListener, *testWorkloadmetaListener) { wlm := newTestWorkloadmetaListener(t) - return &KubeletListener{workloadmetaListener: wlm}, wlm + return &KubeletListener{workloadmetaListener: wlm, tagger: tagger}, wlm } diff --git a/comp/core/autodiscovery/listeners/listeners.go b/comp/core/autodiscovery/listeners/listeners.go index 9741cfd4dcc98..e291332b0a089 100644 --- a/comp/core/autodiscovery/listeners/listeners.go +++ b/comp/core/autodiscovery/listeners/listeners.go @@ -6,12 +6,6 @@ // Package listeners is a wrapper that registers the available autodiscovery listerners. package listeners -import ( - "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" - workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" - "github.com/DataDog/datadog-agent/pkg/util/optional" -) - const ( cloudFoundryBBSListenerName = "cloudfoundry_bbs" containerListenerName = "container" @@ -25,18 +19,14 @@ const ( ) // RegisterListeners registers the available autodiscovery listerners. -func RegisterListeners(serviceListenerFactories map[string]ServiceListenerFactory, wmeta optional.Option[workloadmeta.Component]) { +func RegisterListeners(serviceListenerFactories map[string]ServiceListenerFactory) { // register the available listeners Register(cloudFoundryBBSListenerName, NewCloudFoundryListener, serviceListenerFactories) - Register(containerListenerName, func(config Config, telemetryStore *telemetry.Store) (ServiceListener, error) { - return NewContainerListener(config, wmeta, telemetryStore) - }, serviceListenerFactories) + Register(containerListenerName, NewContainerListener, serviceListenerFactories) Register(environmentListenerName, NewEnvironmentListener, serviceListenerFactories) Register(kubeEndpointsListenerName, NewKubeEndpointsListener, serviceListenerFactories) Register(kubeServicesListenerName, NewKubeServiceListener, serviceListenerFactories) - Register(kubeletListenerName, func(config Config, telemetryStore *telemetry.Store) (ServiceListener, error) { - return NewKubeletListener(config, wmeta, telemetryStore) - }, serviceListenerFactories) + Register(kubeletListenerName, NewKubeletListener, serviceListenerFactories) Register(snmpListenerName, NewSNMPListener, serviceListenerFactories) Register(staticConfigListenerName, NewStaticConfigListener, serviceListenerFactories) Register(dbmAuroraListenerName, NewDBMAuroraListener, serviceListenerFactories) diff --git a/comp/core/autodiscovery/listeners/service.go b/comp/core/autodiscovery/listeners/service.go index 372b079766324..d44dae080673d 100644 --- a/comp/core/autodiscovery/listeners/service.go +++ b/comp/core/autodiscovery/listeners/service.go @@ -37,6 +37,7 @@ type service struct { extraConfig map[string]string metricsExcluded bool logsExcluded bool + tagger tagger.Component } var _ Service = &service{} @@ -90,14 +91,14 @@ func (s *service) GetPorts(_ context.Context) ([]ContainerPort, error) { // GetTags returns the tags associated with the service. func (s *service) GetTags() ([]string, error) { - return tagger.Tag(taggercommon.BuildTaggerEntityID(s.entity.GetID()), tagger.ChecksCardinality()) + return s.tagger.Tag(taggercommon.BuildTaggerEntityID(s.entity.GetID()), s.tagger.ChecksCardinality()) } // GetTagsWithCardinality returns the tags with given cardinality. func (s *service) GetTagsWithCardinality(cardinality string) ([]string, error) { checkCard, err := types.StringToTagCardinality(cardinality) if err == nil { - return tagger.Tag(taggercommon.BuildTaggerEntityID(s.entity.GetID()), checkCard) + return s.tagger.Tag(taggercommon.BuildTaggerEntityID(s.entity.GetID()), checkCard) } log.Warnf("error converting cardinality %s to TagCardinality: %v", cardinality, err) return s.GetTags() diff --git a/comp/core/autodiscovery/listeners/snmp.go b/comp/core/autodiscovery/listeners/snmp.go index dbc12b7ac4a1d..95319218b7a7c 100644 --- a/comp/core/autodiscovery/listeners/snmp.go +++ b/comp/core/autodiscovery/listeners/snmp.go @@ -16,7 +16,6 @@ import ( "time" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" - "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" "github.com/DataDog/datadog-agent/pkg/persistentcache" "github.com/DataDog/datadog-agent/pkg/snmp" "github.com/DataDog/datadog-agent/pkg/util/containers" @@ -67,7 +66,7 @@ type snmpJob struct { } // NewSNMPListener creates a SNMPListener -func NewSNMPListener(Config, *telemetry.Store) (ServiceListener, error) { +func NewSNMPListener(ServiceListernerDeps) (ServiceListener, error) { snmpConfig, err := snmp.NewListenerConfig() if err != nil { return nil, err diff --git a/comp/core/autodiscovery/listeners/snmp_test.go b/comp/core/autodiscovery/listeners/snmp_test.go index 0e63b1a2e1376..8268311f1c3ec 100644 --- a/comp/core/autodiscovery/listeners/snmp_test.go +++ b/comp/core/autodiscovery/listeners/snmp_test.go @@ -11,7 +11,6 @@ import ( "testing" configmock "github.com/DataDog/datadog-agent/pkg/config/mock" - pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/snmp" "github.com/DataDog/datadog-agent/pkg/snmp/snmpintegration" @@ -43,7 +42,7 @@ func TestSNMPListener(t *testing.T) { } } - l, err := NewSNMPListener(&pkgconfigsetup.Listeners{}, nil) + l, err := NewSNMPListener(ServiceListernerDeps{}) assert.Equal(t, nil, err) l.Listen(newSvc, delSvc) @@ -142,7 +141,7 @@ func TestSNMPListenerIgnoredAdresses(t *testing.T) { } } - l, err := NewSNMPListener(&pkgconfigsetup.Listeners{}, nil) + l, err := NewSNMPListener(ServiceListernerDeps{}) assert.Equal(t, nil, err) l.Listen(newSvc, delSvc) diff --git a/comp/core/autodiscovery/listeners/staticconfig.go b/comp/core/autodiscovery/listeners/staticconfig.go index ad06ab28eb49f..8c2621b21f374 100644 --- a/comp/core/autodiscovery/listeners/staticconfig.go +++ b/comp/core/autodiscovery/listeners/staticconfig.go @@ -9,7 +9,6 @@ import ( "context" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" - "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/util/containers" ) @@ -28,7 +27,7 @@ type StaticConfigService struct { var _ Service = &StaticConfigService{} // NewStaticConfigListener creates a StaticConfigListener -func NewStaticConfigListener(Config, *telemetry.Store) (ServiceListener, error) { +func NewStaticConfigListener(ServiceListernerDeps) (ServiceListener, error) { return &StaticConfigListener{}, nil } diff --git a/comp/core/autodiscovery/listeners/types.go b/comp/core/autodiscovery/listeners/types.go index bcdbe1aeebaeb..356c8437df608 100644 --- a/comp/core/autodiscovery/listeners/types.go +++ b/comp/core/autodiscovery/listeners/types.go @@ -11,8 +11,11 @@ import ( "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" + "github.com/DataDog/datadog-agent/comp/core/tagger" + workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/util/containers" "github.com/DataDog/datadog-agent/pkg/util/log" + "github.com/DataDog/datadog-agent/pkg/util/optional" ) // ContainerPort represents a network port in a Service. @@ -62,8 +65,16 @@ type Config interface { IsProviderEnabled(string) bool } +// ServiceListernerDeps are the service listerner dependencies +type ServiceListernerDeps struct { + Config Config + Telemetry *telemetry.Store + Tagger tagger.Component + Wmeta optional.Option[workloadmeta.Component] +} + // ServiceListenerFactory builds a service listener -type ServiceListenerFactory func(Config, *telemetry.Store) (ServiceListener, error) +type ServiceListenerFactory func(ServiceListernerDeps) (ServiceListener, error) // Register registers a service listener factory func Register(name string, diff --git a/comp/core/autodiscovery/noopimpl/autoconfig.go b/comp/core/autodiscovery/noopimpl/autoconfig.go new file mode 100644 index 0000000000000..9893a70e4dcf2 --- /dev/null +++ b/comp/core/autodiscovery/noopimpl/autoconfig.go @@ -0,0 +1,96 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +// Package noopautoconfig provides a noop implementation for the autodiscovery component +package noopautoconfig + +import ( + "context" + "time" + + "go.uber.org/fx" + + "github.com/DataDog/datadog-agent/comp/core/autodiscovery" + "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/autodiscovery/providers" + "github.com/DataDog/datadog-agent/comp/core/autodiscovery/scheduler" + "github.com/DataDog/datadog-agent/comp/core/autodiscovery/telemetry" + checkid "github.com/DataDog/datadog-agent/pkg/collector/check/id" + pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" + "github.com/DataDog/datadog-agent/pkg/util/fxutil" +) + +// Module defines the fx options for this component. +func Module() fxutil.Module { + return fxutil.Component( + fx.Provide( + newAutoConfig, + ), + ) +} + +type noopAutoConfig struct{} + +func (n *noopAutoConfig) AddConfigProvider(providers.ConfigProvider, bool, time.Duration) {} + +func (n *noopAutoConfig) LoadAndRun(context.Context) {} + +func (n *noopAutoConfig) ForceRanOnceFlag() {} + +func (n *noopAutoConfig) HasRunOnce() bool { + return false +} + +func (n *noopAutoConfig) GetAllConfigs() []integration.Config { + return []integration.Config{} +} + +func (n *noopAutoConfig) AddListeners([]pkgconfigsetup.Listeners) {} + +func (n *noopAutoConfig) AddScheduler(string, scheduler.Scheduler, bool) {} + +func (n *noopAutoConfig) RemoveScheduler(string) {} + +func (n *noopAutoConfig) MapOverLoadedConfigs(func(map[string]integration.Config)) {} + +func (n *noopAutoConfig) LoadedConfigs() []integration.Config { + return []integration.Config{} +} + +func (n *noopAutoConfig) GetUnresolvedTemplates() map[string][]integration.Config { + return map[string][]integration.Config{} +} + +func (n *noopAutoConfig) GetIDOfCheckWithEncryptedSecrets(checkid.ID) checkid.ID { + return "" +} + +func (n *noopAutoConfig) GetAutodiscoveryErrors() map[string]map[string]providers.ErrorMsgSet { + return map[string]map[string]providers.ErrorMsgSet{} +} + +func (n *noopAutoConfig) GetProviderCatalog() map[string]providers.ConfigProviderFactory { + return map[string]providers.ConfigProviderFactory{} +} + +func (n *noopAutoConfig) GetTelemetryStore() *telemetry.Store { + return nil +} + +func (n *noopAutoConfig) Start() {} + +func (n *noopAutoConfig) Stop() {} + +func (n *noopAutoConfig) GetConfigCheck() integration.ConfigCheckResponse { + return integration.ConfigCheckResponse{} +} + +func (n *noopAutoConfig) IsStarted() bool { + return false +} + +func newAutoConfig() autodiscovery.Component { + return &noopAutoConfig{} +} diff --git a/comp/core/flare/flare.go b/comp/core/flare/flare.go index 6983272a95137..edcb2174094a3 100644 --- a/comp/core/flare/flare.go +++ b/comp/core/flare/flare.go @@ -28,6 +28,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/flare/types" log "github.com/DataDog/datadog-agent/comp/core/log/def" "github.com/DataDog/datadog-agent/comp/core/secrets" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" rcclienttypes "github.com/DataDog/datadog-agent/comp/remote-config/rcclient/types" "github.com/DataDog/datadog-agent/pkg/config/utils" @@ -51,7 +52,8 @@ type dependencies struct { Collector optional.Option[collector.Component] WMeta optional.Option[workloadmeta.Component] Secrets secrets.Component - AC optional.Option[autodiscovery.Component] + AC autodiscovery.Component + Tagger tagger.Component } type provides struct { @@ -71,7 +73,7 @@ type flare struct { } func newFlare(deps dependencies) provides { - diagnoseDeps := diagnose.NewSuitesDeps(deps.Diagnosesendermanager, deps.Collector, deps.Secrets, deps.WMeta, deps.AC) + diagnoseDeps := diagnose.NewSuitesDeps(deps.Diagnosesendermanager, deps.Collector, deps.Secrets, deps.WMeta, deps.AC, deps.Tagger) f := &flare{ log: deps.Log, config: deps.Config, diff --git a/comp/core/flare/flare_test.go b/comp/core/flare/flare_test.go index b85b9de27311d..fb4ffd9d7733a 100644 --- a/comp/core/flare/flare_test.go +++ b/comp/core/flare/flare_test.go @@ -14,24 +14,31 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/fx" - "github.com/DataDog/datadog-agent/comp/aggregator/diagnosesendermanager" + "github.com/DataDog/datadog-agent/comp/aggregator/demultiplexer/demultiplexerimpl" "github.com/DataDog/datadog-agent/comp/collector/collector" "github.com/DataDog/datadog-agent/comp/core/autodiscovery" + "github.com/DataDog/datadog-agent/comp/core/autodiscovery/autodiscoveryimpl" + "github.com/DataDog/datadog-agent/comp/core/autodiscovery/scheduler" "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/flare/helpers" "github.com/DataDog/datadog-agent/comp/core/flare/types" + "github.com/DataDog/datadog-agent/comp/core/hostname/hostnameimpl" log "github.com/DataDog/datadog-agent/comp/core/log/def" logmock "github.com/DataDog/datadog-agent/comp/core/log/mock" "github.com/DataDog/datadog-agent/comp/core/secrets/secretsimpl" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" nooptelemetry "github.com/DataDog/datadog-agent/comp/core/telemetry/noopsimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" + workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" "github.com/DataDog/datadog-agent/pkg/util/fxutil" - "github.com/DataDog/datadog-agent/pkg/util/optional" ) func TestFlareCreation(t *testing.T) { realProvider := func(_ types.FlareBuilder) error { return nil } + fakeTagger := taggerimpl.SetupFakeTagger(t) + f := newFlare( fxutil.Test[dependencies]( t, @@ -39,11 +46,16 @@ func TestFlareCreation(t *testing.T) { config.MockModule(), secretsimpl.MockModule(), nooptelemetry.Module(), - fx.Provide(func() diagnosesendermanager.Component { return nil }), + hostnameimpl.MockModule(), + demultiplexerimpl.MockModule(), fx.Provide(func() Params { return Params{} }), collector.NoneModule(), - fx.Supply(optional.NewNoneOption[workloadmeta.Component]()), - fx.Supply(optional.NewNoneOption[autodiscovery.Component]()), + workloadmetafxmock.MockModule(workloadmeta.NewParams()), + autodiscoveryimpl.MockModule(), + fx.Supply(autodiscoveryimpl.MockParams{Scheduler: scheduler.NewController()}), + fx.Provide(func(ac autodiscovery.Mock) autodiscovery.Component { return ac.(autodiscovery.Component) }), + fx.Provide(func() tagger.Mock { return fakeTagger }), + fx.Provide(func() tagger.Component { return fakeTagger }), // provider a nil FlareCallback fx.Provide(fx.Annotate( func() types.FlareCallback { return nil }, @@ -66,17 +78,24 @@ func TestRunProviders(t *testing.T) { var secondRan atomic.Bool var secondDone atomic.Bool + fakeTagger := taggerimpl.SetupFakeTagger(t) + deps := fxutil.Test[dependencies]( t, fx.Provide(func() log.Component { return logmock.New(t) }), config.MockModule(), secretsimpl.MockModule(), nooptelemetry.Module(), - fx.Provide(func() diagnosesendermanager.Component { return nil }), + hostnameimpl.MockModule(), + demultiplexerimpl.MockModule(), fx.Provide(func() Params { return Params{} }), collector.NoneModule(), - fx.Supply(optional.NewNoneOption[workloadmeta.Component]()), - fx.Supply(optional.NewNoneOption[autodiscovery.Component]()), + workloadmetafxmock.MockModule(workloadmeta.NewParams()), + autodiscoveryimpl.MockModule(), + fx.Supply(autodiscoveryimpl.MockParams{Scheduler: scheduler.NewController()}), + fx.Provide(func(ac autodiscovery.Mock) autodiscovery.Component { return ac.(autodiscovery.Component) }), + fx.Provide(func() tagger.Mock { return fakeTagger }), + fx.Provide(func() tagger.Component { return fakeTagger }), // provider a nil FlareCallback fx.Provide(fx.Annotate( func() types.FlareCallback { return nil }, diff --git a/comp/core/tagger/component.go b/comp/core/tagger/component.go index 00c4fab6d4729..54e137578dffb 100644 --- a/comp/core/tagger/component.go +++ b/comp/core/tagger/component.go @@ -38,6 +38,11 @@ type Component interface { Stop() error ReplayTagger() ReplayTagger GetTaggerTelemetryStore() *telemetry.Store + // LegacyTag has the same behaviour as the Tag method, but it receives the entity id as a string and parses it. + // If possible, avoid using this function, and use the Tag method instead. + // This function exists in order not to break backward compatibility with rtloader and python + // integrations using the tagger + LegacyTag(entity string, cardinality types.TagCardinality) ([]string, error) Tag(entityID types.EntityID, cardinality types.TagCardinality) ([]string, error) AccumulateTagsFor(entityID types.EntityID, cardinality types.TagCardinality, tb tagset.TagsAccumulator) error Standard(entityID types.EntityID) ([]string, error) diff --git a/comp/core/tagger/component_mock.go b/comp/core/tagger/component_mock.go index e3643c67b2e7a..6d52dbf4d51c8 100644 --- a/comp/core/tagger/component_mock.go +++ b/comp/core/tagger/component_mock.go @@ -19,7 +19,4 @@ type Mock interface { // SetGlobalTags allows to set tags in store for the global entity SetGlobalTags(low, orch, high, std []string) - - // ResetTagger for testing only - ResetTagger() } diff --git a/comp/core/tagger/global.go b/comp/core/tagger/global.go deleted file mode 100644 index 626cc604434aa..0000000000000 --- a/comp/core/tagger/global.go +++ /dev/null @@ -1,141 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -package tagger - -import ( - "errors" - "sync" - - "github.com/DataDog/datadog-agent/comp/core/tagger/common" - "github.com/DataDog/datadog-agent/comp/core/tagger/types" - taggertypes "github.com/DataDog/datadog-agent/pkg/tagger/types" - "github.com/DataDog/datadog-agent/pkg/tagset" -) - -var ( - // globalTagger is the global tagger instance backing the global Tag functions - // // TODO(components) (tagger): globalTagger is a legacy global variable but still in use, to be eliminated - globalTagger Component - - // initOnce ensures that the global tagger is only initialized once. It is reset every - // time the default tagger is set. - initOnce sync.Once -) - -// SetGlobalTaggerClient sets the global taggerClient instance -func SetGlobalTaggerClient(t Component) { - initOnce.Do(func() { - globalTagger = t - }) -} - -// UnlockGlobalTaggerClient releases the initOnce lock on the global tagger. For testing only. -func UnlockGlobalTaggerClient() { - initOnce = sync.Once{} -} - -// GetEntity returns the hash for the provided entity id. -func GetEntity(entityID types.EntityID) (*types.Entity, error) { - if globalTagger == nil { - return nil, errors.New("a global tagger must be set before calling GetEntity") - } - return globalTagger.GetEntity(entityID) -} - -// LegacyTag is an interface function that queries taggerclient singleton -// If possible, avoid using this function, and use the Tag interface function instead. -// This function exists in order not to break backward compatibility with rtloader and python -// integrations using the tagger -func LegacyTag(entity string, cardinality types.TagCardinality) ([]string, error) { - if globalTagger == nil { - return nil, errors.New("a global tagger must be set before calling Tag") - } - - prefix, id, err := common.ExtractPrefixAndID(entity) - if err != nil { - return nil, err - } - - entityID := types.NewEntityID(prefix, id) - return globalTagger.Tag(entityID, cardinality) -} - -// Tag is an interface function that queries taggerclient singleton -func Tag(entity types.EntityID, cardinality types.TagCardinality) ([]string, error) { - if globalTagger == nil { - return nil, errors.New("a global tagger must be set before calling Tag") - } - return globalTagger.Tag(entity, cardinality) -} - -// GetEntityHash is an interface function that queries taggerclient singleton -func GetEntityHash(entityID types.EntityID, cardinality types.TagCardinality) string { - if globalTagger != nil { - return globalTagger.GetEntityHash(entityID, cardinality) - } - return "" -} - -// AgentTags is an interface function that queries taggerclient singleton -func AgentTags(cardinality types.TagCardinality) ([]string, error) { - if globalTagger == nil { - return nil, errors.New("a global tagger must be set before calling AgentTags") - } - return globalTagger.AgentTags(cardinality) -} - -// GlobalTags is an interface function that queries taggerclient singleton -func GlobalTags(cardinality types.TagCardinality) ([]string, error) { - if globalTagger == nil { - return nil, errors.New("a global tagger must be set before calling GlobalTags") - } - return globalTagger.GlobalTags(cardinality) -} - -// List the content of the defaulTagger -func List() types.TaggerListResponse { - if globalTagger != nil { - return globalTagger.List() - } - return types.TaggerListResponse{} -} - -// SetNewCaptureTagger will set capture tagger in global tagger instance by using provided capture tagger -func SetNewCaptureTagger(newCaptureTagger Component) { - if globalTagger != nil { - globalTagger.SetNewCaptureTagger(newCaptureTagger) - } -} - -// ResetCaptureTagger will reset capture tagger -func ResetCaptureTagger() { - if globalTagger != nil { - globalTagger.ResetCaptureTagger() - } -} - -// EnrichTags is an interface function that queries taggerclient singleton -func EnrichTags(tb tagset.TagsAccumulator, originInfo taggertypes.OriginInfo) { - if globalTagger != nil { - globalTagger.EnrichTags(tb, originInfo) - } -} - -// ChecksCardinality is an interface function that queries taggerclient singleton -func ChecksCardinality() types.TagCardinality { - if globalTagger != nil { - return globalTagger.ChecksCardinality() - } - return types.LowCardinality -} - -// DogstatsdCardinality is an interface function that queries taggerclient singleton -func DogstatsdCardinality() types.TagCardinality { - if globalTagger != nil { - return globalTagger.DogstatsdCardinality() - } - return types.LowCardinality -} diff --git a/comp/core/tagger/noopimpl/tagger.go b/comp/core/tagger/noopimpl/tagger.go index 3b07469f975e7..905082da82469 100644 --- a/comp/core/tagger/noopimpl/tagger.go +++ b/comp/core/tagger/noopimpl/tagger.go @@ -31,9 +31,10 @@ import ( func Module() fxutil.Module { return fxutil.Component( fx.Provide( - newTaggerClient, + NewTaggerClient, ), ) + } type noopTagger struct{} @@ -58,6 +59,10 @@ func (n *noopTagger) Tag(types.EntityID, types.TagCardinality) ([]string, error) return nil, nil } +func (n *noopTagger) LegacyTag(string, types.TagCardinality) ([]string, error) { + return nil, nil +} + func (n *noopTagger) AccumulateTagsFor(types.EntityID, types.TagCardinality, tagset.TagsAccumulator) error { return nil } @@ -104,6 +109,7 @@ func (n *noopTagger) DogstatsdCardinality() types.TagCardinality { return types.LowCardinality } -func newTaggerClient() tagger.Component { +// NewTaggerClient returns a new noop tagger client +func NewTaggerClient() tagger.Component { return &noopTagger{} } diff --git a/comp/core/tagger/taggerimpl/local/fake_tagger.go b/comp/core/tagger/taggerimpl/local/fake_tagger.go index 74bdbe26b642c..19404d821a7c7 100644 --- a/comp/core/tagger/taggerimpl/local/fake_tagger.go +++ b/comp/core/tagger/taggerimpl/local/fake_tagger.go @@ -12,7 +12,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/tagger" - "github.com/DataDog/datadog-agent/comp/core/tagger/common" + taggercommon "github.com/DataDog/datadog-agent/comp/core/tagger/common" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl/empty" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl/tagstore" "github.com/DataDog/datadog-agent/comp/core/tagger/telemetry" @@ -56,7 +56,7 @@ func (f *FakeTagger) SetTags(entityID types.EntityID, source string, low, orch, // SetGlobalTags allows to set tags in store for the global entity func (f *FakeTagger) SetGlobalTags(low, orch, high, std []string) { - f.SetTags(common.GetGlobalEntityID(), "static", low, orch, high, std) + f.SetTags(taggercommon.GetGlobalEntityID(), "static", low, orch, high, std) } // SetTagsFromInfo allows to set tags from list of TagInfo @@ -108,9 +108,23 @@ func (f *FakeTagger) Tag(entityID types.EntityID, cardinality types.TagCardinali return tags, nil } +// LegacyTag has the same behaviour as the Tag method, but it receives the entity id as a string and parses it. +// If possible, avoid using this function, and use the Tag method instead. +// This function exists in order not to break backward compatibility with rtloader and python +// integrations using the tagger +func (f *FakeTagger) LegacyTag(entity string, cardinality types.TagCardinality) ([]string, error) { + prefix, id, err := taggercommon.ExtractPrefixAndID(entity) + if err != nil { + return nil, err + } + + entityID := types.NewEntityID(prefix, id) + return f.Tag(entityID, cardinality) +} + // GlobalTags fake implementation func (f *FakeTagger) GlobalTags(cardinality types.TagCardinality) ([]string, error) { - return f.Tag(common.GetGlobalEntityID(), cardinality) + return f.Tag(taggercommon.GetGlobalEntityID(), cardinality) } // AccumulateTagsFor fake implementation diff --git a/comp/core/tagger/taggerimpl/local/tagger.go b/comp/core/tagger/taggerimpl/local/tagger.go index 7fcce587c2937..e9193da317c42 100644 --- a/comp/core/tagger/taggerimpl/local/tagger.go +++ b/comp/core/tagger/taggerimpl/local/tagger.go @@ -13,6 +13,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/tagger" + taggercommon "github.com/DataDog/datadog-agent/comp/core/tagger/common" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl/collectors" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl/empty" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl/tagstore" @@ -105,6 +106,20 @@ func (t *Tagger) Tag(entityID types.EntityID, cardinality types.TagCardinality) return tags.Copy(), nil } +// LegacyTag has the same behaviour as the Tag method, but it receives the entity id as a string and parses it. +// If possible, avoid using this function, and use the Tag method instead. +// This function exists in order not to break backward compatibility with rtloader and python +// integrations using the tagger +func (t *Tagger) LegacyTag(entity string, cardinality types.TagCardinality) ([]string, error) { + prefix, id, err := taggercommon.ExtractPrefixAndID(entity) + if err != nil { + return nil, err + } + + entityID := types.NewEntityID(prefix, id) + return t.Tag(entityID, cardinality) +} + // Standard returns standard tags for a given entity // It triggers a tagger fetch if the no tags are found func (t *Tagger) Standard(entityID types.EntityID) ([]string, error) { diff --git a/comp/core/tagger/taggerimpl/remote/tagger.go b/comp/core/tagger/taggerimpl/remote/tagger.go index 6c32a179ed600..ec0ef90d65779 100644 --- a/comp/core/tagger/taggerimpl/remote/tagger.go +++ b/comp/core/tagger/taggerimpl/remote/tagger.go @@ -24,13 +24,14 @@ import ( "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/tagger" + taggercommon "github.com/DataDog/datadog-agent/comp/core/tagger/common" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl/empty" "github.com/DataDog/datadog-agent/comp/core/tagger/telemetry" "github.com/DataDog/datadog-agent/comp/core/tagger/types" "github.com/DataDog/datadog-agent/pkg/api/security" + "github.com/DataDog/datadog-agent/pkg/config/utils" pb "github.com/DataDog/datadog-agent/pkg/proto/pbgo/core" "github.com/DataDog/datadog-agent/pkg/tagset" - "github.com/DataDog/datadog-agent/pkg/util/clusteragent" grpcutil "github.com/DataDog/datadog-agent/pkg/util/grpc" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -99,7 +100,7 @@ func CLCRunnerOptions(config config.Component) (Options, error) { } if !opts.Disabled { - target, err := clusteragent.GetClusterAgentEndpoint() + target, err := utils.GetClusterAgentEndpoint() if err != nil { return opts, fmt.Errorf("unable to get cluster agent endpoint: %w", err) } @@ -212,6 +213,20 @@ func (t *Tagger) Tag(entityID types.EntityID, cardinality types.TagCardinality) return []string{}, nil } +// LegacyTag has the same behaviour as the Tag method, but it receives the entity id as a string and parses it. +// If possible, avoid using this function, and use the Tag method instead. +// This function exists in order not to break backward compatibility with rtloader and python +// integrations using the tagger +func (t *Tagger) LegacyTag(entity string, cardinality types.TagCardinality) ([]string, error) { + prefix, id, err := taggercommon.ExtractPrefixAndID(entity) + if err != nil { + return nil, err + } + + entityID := types.NewEntityID(prefix, id) + return t.Tag(entityID, cardinality) +} + // AccumulateTagsFor returns tags for a given entity at the desired cardinality. func (t *Tagger) AccumulateTagsFor(entityID types.EntityID, cardinality types.TagCardinality, tb tagset.TagsAccumulator) error { tags, err := t.Tag(entityID, cardinality) diff --git a/comp/core/tagger/taggerimpl/replay/tagger.go b/comp/core/tagger/taggerimpl/replay/tagger.go index 16d36c5a022ec..c13ded9685009 100644 --- a/comp/core/tagger/taggerimpl/replay/tagger.go +++ b/comp/core/tagger/taggerimpl/replay/tagger.go @@ -13,6 +13,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/tagger" + taggercommon "github.com/DataDog/datadog-agent/comp/core/tagger/common" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl/empty" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl/tagstore" "github.com/DataDog/datadog-agent/comp/core/tagger/telemetry" @@ -69,6 +70,20 @@ func (t *Tagger) Tag(entityID types.EntityID, cardinality types.TagCardinality) return tags, nil } +// LegacyTag has the same behaviour as the Tag method, but it receives the entity id as a string and parses it. +// If possible, avoid using this function, and use the Tag method instead. +// This function exists in order not to break backward compatibility with rtloader and python +// integrations using the tagger +func (t *Tagger) LegacyTag(entity string, cardinality types.TagCardinality) ([]string, error) { + prefix, id, err := taggercommon.ExtractPrefixAndID(entity) + if err != nil { + return nil, err + } + + entityID := types.NewEntityID(prefix, id) + return t.Tag(entityID, cardinality) +} + // AccumulateTagsFor returns tags for a given entity at the desired cardinality. func (t *Tagger) AccumulateTagsFor(entityID types.EntityID, cardinality types.TagCardinality, tb tagset.TagsAccumulator) error { tags := t.store.LookupHashed(entityID, cardinality) diff --git a/comp/core/tagger/taggerimpl/tagger.go b/comp/core/tagger/taggerimpl/tagger.go index 3e9e5f2c6904b..37a84f40bfbbc 100644 --- a/comp/core/tagger/taggerimpl/tagger.go +++ b/comp/core/tagger/taggerimpl/tagger.go @@ -169,7 +169,6 @@ func newTaggerClient(deps dependencies) provides { taggerClient.telemetryStore = telemetryStore deps.Log.Info("TaggerClient is created, defaultTagger type: ", reflect.TypeOf(taggerClient.defaultTagger)) - taggerComp.SetGlobalTaggerClient(taggerClient) deps.Lc.Append(fx.Hook{OnStart: func(_ context.Context) error { var err error checkCard := deps.Config.GetString("checks_tag_cardinality") @@ -273,6 +272,20 @@ func (t *TaggerClient) Tag(entityID types.EntityID, cardinality types.TagCardina return t.defaultTagger.Tag(entityID, cardinality) } +// LegacyTag has the same behaviour as the Tag method, but it receives the entity id as a string and parses it. +// If possible, avoid using this function, and use the Tag method instead. +// This function exists in order not to break backward compatibility with rtloader and python +// integrations using the tagger +func (t *TaggerClient) LegacyTag(entity string, cardinality types.TagCardinality) ([]string, error) { + prefix, id, err := taggercommon.ExtractPrefixAndID(entity) + if err != nil { + return nil, err + } + + entityID := types.NewEntityID(prefix, id) + return t.Tag(entityID, cardinality) +} + // AccumulateTagsFor queries the defaultTagger to get entity tags from cache or // sources and appends them to the TagsAccumulator. It can return tags at high // cardinality (with tags about individual containers), or at orchestrator @@ -573,41 +586,3 @@ func taggerCardinality(cardinality string, func (t *TaggerClient) Subscribe(subscriptionID string, filter *types.Filter) (types.Subscription, error) { return t.defaultTagger.Subscribe(subscriptionID, filter) } - -type optionalTaggerDeps struct { - fx.In - - Lc fx.Lifecycle - Config config.Component - Log log.Component - Wmeta optional.Option[workloadmeta.Component] - Telemetry coretelemetry.Component -} - -// OptionalModule defines the fx options when tagger should be used as an optional -func OptionalModule() fxutil.Module { - return fxutil.Component( - fx.Provide( - NewOptionalTagger, - ), - ) -} - -// NewOptionalTagger returns a tagger component if workloadmeta is available -func NewOptionalTagger(deps optionalTaggerDeps) optional.Option[taggerComp.Component] { - w, ok := deps.Wmeta.Get() - if !ok { - return optional.NewNoneOption[taggerComp.Component]() - } - return optional.NewOption[taggerComp.Component](newTaggerClient(dependencies{ - In: deps.In, - Lc: deps.Lc, - Config: deps.Config, - Log: deps.Log, - Wmeta: w, - Params: taggerComp.Params{ - AgentTypeForTagger: taggerComp.LocalTaggerAgent, - }, - Telemetry: deps.Telemetry, - }).Comp) -} diff --git a/comp/core/tagger/taggerimpl/tagger_mock.go b/comp/core/tagger/taggerimpl/tagger_mock.go index 6a03dd399ef24..94fc806bd2bc5 100644 --- a/comp/core/tagger/taggerimpl/tagger_mock.go +++ b/comp/core/tagger/taggerimpl/tagger_mock.go @@ -99,8 +99,3 @@ func (m *MockTaggerClient) SetGlobalTags(low, orch, high, std []string) { func SetupFakeTagger(t *testing.T) tagger.Mock { return fxutil.Test[tagger.Mock](t, MockModule()) } - -// ResetTagger resets the tagger -func (m *MockTaggerClient) ResetTagger() { - tagger.UnlockGlobalTaggerClient() -} diff --git a/comp/core/tagger/taggerimpl/tagger_test.go b/comp/core/tagger/taggerimpl/tagger_test.go index d101ccf9ba803..a62f68403ed8c 100644 --- a/comp/core/tagger/taggerimpl/tagger_test.go +++ b/comp/core/tagger/taggerimpl/tagger_test.go @@ -6,6 +6,7 @@ package taggerimpl import ( + "fmt" "testing" "time" @@ -14,14 +15,16 @@ import ( logmock "github.com/DataDog/datadog-agent/comp/core/log/mock" "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/types" + workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" configmock "github.com/DataDog/datadog-agent/pkg/config/mock" taggertypes "github.com/DataDog/datadog-agent/pkg/tagger/types" "github.com/DataDog/datadog-agent/pkg/tagset" + "github.com/DataDog/datadog-agent/pkg/util/containers/metrics" + collectormock "github.com/DataDog/datadog-agent/pkg/util/containers/metrics/mock" "github.com/DataDog/datadog-agent/pkg/util/fxutil" + "github.com/DataDog/datadog-agent/pkg/util/optional" ) -// TODO Improve test coverage with dogstatsd/enrich tests once Origin Detection is refactored. - type fakeCIDProvider struct { entries map[string]string initEntries map[string]string @@ -35,50 +38,60 @@ func (f *fakeCIDProvider) ContainerIDForPodUIDAndContName(podUID, contName strin return f.entries[id], nil } +// Sets up the fake metrics provider and returns a function to reset the original metrics provider +func setupFakeMetricsProvider(mockMetricsProvider metrics.Provider) func() { + originalMetricsProvider := metrics.GetProvider + metrics.GetProvider = func(_ optional.Option[workloadmeta.Component]) metrics.Provider { + return mockMetricsProvider + } + return func() { metrics.GetProvider = originalMetricsProvider } +} + func TestEnrichTags(t *testing.T) { // Create fake tagger fakeTagger := fxutil.Test[tagger.Mock](t, MockModule()) - defer fakeTagger.ResetTagger() + containerName, initContainerName, containerID, initContainerID, podUID := "container-name", "init-container-name", "container-id", "init-container-id", "pod-uid" // Fill fake tagger with entities - fakeTagger.SetTags(types.NewEntityID(types.KubernetesPodUID, "pod"), "host", []string{"pod-low"}, []string{"pod-orch"}, []string{"pod-high"}, []string{"pod-std"}) - fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "container"), "host", []string{"container-low"}, []string{"container-orch"}, []string{"container-high"}, []string{"container-std"}) + fakeTagger.SetTags(types.NewEntityID(types.KubernetesPodUID, podUID), "host", []string{"pod-low"}, []string{"pod-orch"}, []string{"pod-high"}, []string{"pod-std"}) + fakeTagger.SetTags(types.NewEntityID(types.ContainerID, containerID), "host", []string{"container-low"}, []string{"container-orch"}, []string{"container-high"}, []string{"container-std"}) + fakeTagger.SetTags(types.NewEntityID(types.ContainerID, initContainerID), "host", []string{"init-container-low"}, []string{"init-container-orch"}, []string{"init-container-high"}, []string{"init-container-std"}) + // Local data tests for _, tt := range []struct { name string originInfo taggertypes.OriginInfo - cidProvider *fakeCIDProvider expectedTags []string }{ { name: "no origin", originInfo: taggertypes.OriginInfo{}, expectedTags: []string{}, - cidProvider: &fakeCIDProvider{}, }, { name: "with local data (containerID) and low cardinality", - originInfo: taggertypes.OriginInfo{ContainerID: "container", Cardinality: "low"}, + originInfo: taggertypes.OriginInfo{ContainerID: containerID, Cardinality: "low"}, expectedTags: []string{"container-low"}, - cidProvider: &fakeCIDProvider{}, }, { name: "with local data (containerID) and high cardinality", - originInfo: taggertypes.OriginInfo{ContainerID: "container", Cardinality: "high"}, + originInfo: taggertypes.OriginInfo{ContainerID: containerID, Cardinality: "high"}, expectedTags: []string{"container-low", "container-orch", "container-high"}, - cidProvider: &fakeCIDProvider{}, }, { name: "with local data (podUID) and low cardinality", - originInfo: taggertypes.OriginInfo{PodUID: "pod", Cardinality: "low"}, + originInfo: taggertypes.OriginInfo{PodUID: podUID, Cardinality: "low"}, expectedTags: []string{"pod-low"}, - cidProvider: &fakeCIDProvider{}, }, { name: "with local data (podUID) and high cardinality", - originInfo: taggertypes.OriginInfo{PodUID: "pod", Cardinality: "high"}, + originInfo: taggertypes.OriginInfo{PodUID: podUID, Cardinality: "high"}, expectedTags: []string{"pod-low", "pod-orch", "pod-high"}, - cidProvider: &fakeCIDProvider{}, + }, + { + name: "with local data (podUID, containerIDFromSocket) and high cardinality, APM origin", + originInfo: taggertypes.OriginInfo{PodUID: podUID, Cardinality: "high", ContainerIDFromSocket: fmt.Sprintf("container_id://%s", containerID), ProductOrigin: taggertypes.ProductOriginAPM}, + expectedTags: []string{"container-low", "container-orch", "container-high", "pod-low", "pod-orch", "pod-high"}, }, } { t.Run(tt.name, func(t *testing.T) { @@ -87,27 +100,80 @@ func TestEnrichTags(t *testing.T) { assert.Equal(t, tt.expectedTags, tb.Get()) }) } + + // External data tests + + // Overriding the GetProvider function to use the mock metrics provider + mockMetricsProvider := collectormock.NewMetricsProvider() + initContainerMetaCollector := collectormock.MetaCollector{ContainerID: initContainerID, CIDFromPodUIDContName: map[string]string{fmt.Sprint("i-", podUID, "/", initContainerName): initContainerID}} + containerMetaCollector := collectormock.MetaCollector{ContainerID: containerID, CIDFromPodUIDContName: map[string]string{fmt.Sprint(podUID, "/", containerName): containerID}} + cleanUp := setupFakeMetricsProvider(mockMetricsProvider) + defer cleanUp() + + for _, tt := range []struct { + name string + originInfo taggertypes.OriginInfo + expectedTags []string + setup func() // register the proper meta collector for the test + }{ + { + name: "with external data (containerName) and high cardinality", + originInfo: taggertypes.OriginInfo{ProductOrigin: taggertypes.ProductOriginAPM, ExternalData: fmt.Sprintf("cn-%s,it-false", containerName), Cardinality: "high"}, + expectedTags: []string{}, + setup: func() { mockMetricsProvider.RegisterMetaCollector(&containerMetaCollector) }, + }, + { + name: "with external data (containerName, podUID) and low cardinality", + originInfo: taggertypes.OriginInfo{ProductOrigin: taggertypes.ProductOriginAPM, ExternalData: fmt.Sprintf("it-invalid,cn-%s,pu-%s", containerName, podUID), Cardinality: "low"}, + expectedTags: []string{"pod-low", "container-low"}, + setup: func() { mockMetricsProvider.RegisterMetaCollector(&containerMetaCollector) }, + }, + { + name: "with external data (podUID) and high cardinality", + originInfo: taggertypes.OriginInfo{ProductOrigin: taggertypes.ProductOriginAPM, ExternalData: fmt.Sprintf("pu-%s,it-false", podUID), Cardinality: "high"}, + expectedTags: []string{"pod-low", "pod-orch", "pod-high"}, + setup: func() { mockMetricsProvider.RegisterMetaCollector(&containerMetaCollector) }, + }, + { + name: "with external data (containerName, podUID) and high cardinality", + originInfo: taggertypes.OriginInfo{ProductOrigin: taggertypes.ProductOriginAPM, ExternalData: fmt.Sprintf("pu-%s,it-false,cn-%s", podUID, containerName), Cardinality: "high"}, + expectedTags: []string{"pod-low", "pod-orch", "pod-high", "container-low", "container-orch", "container-high"}, + setup: func() { mockMetricsProvider.RegisterMetaCollector(&containerMetaCollector) }, + }, + { + name: "with external data (containerName, podUID, initContainer) and low cardinality", + originInfo: taggertypes.OriginInfo{ProductOrigin: taggertypes.ProductOriginAPM, ExternalData: fmt.Sprintf("pu-%s,cn-%s,it-true", podUID, initContainerName), Cardinality: "low"}, + expectedTags: []string{"pod-low", "init-container-low"}, + setup: func() { mockMetricsProvider.RegisterMetaCollector(&initContainerMetaCollector) }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + tb := tagset.NewHashingTagsAccumulator() + fakeTagger.EnrichTags(tb, tt.originInfo) + assert.Equal(t, tt.expectedTags, tb.Get()) + }) + } } func TestEnrichTagsOrchestrator(t *testing.T) { fakeTagger := fxutil.Test[tagger.Mock](t, MockModule()) - defer fakeTagger.ResetTagger() - fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "bar"), "fooSource", []string{"lowTag"}, []string{"orchTag"}, nil, nil) + fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "bar"), "fooSource", []string{"container-low"}, []string{"container-orch"}, nil, nil) tb := tagset.NewHashingTagsAccumulator() fakeTagger.EnrichTags(tb, taggertypes.OriginInfo{ContainerIDFromSocket: "container_id://bar", Cardinality: "orchestrator"}) - assert.Equal(t, []string{"lowTag", "orchTag"}, tb.Get()) + assert.Equal(t, []string{"container-low", "container-orch"}, tb.Get()) } func TestEnrichTagsOptOut(t *testing.T) { fakeTagger := fxutil.Test[tagger.Mock](t, MockModule()) - defer fakeTagger.ResetTagger() + cfg := configmock.New(t) cfg.SetWithoutSource("dogstatsd_origin_optout_enabled", true) - fakeTagger.SetTags(types.NewEntityID(types.EntityIDPrefix("foo"), "bar"), "fooSource", []string{"lowTag"}, []string{"orchTag"}, nil, nil) + fakeTagger.SetTags(types.NewEntityID(types.EntityIDPrefix("foo"), "bar"), "fooSource", []string{"container-low"}, []string{"container-orch"}, nil, nil) tb := tagset.NewHashingTagsAccumulator() - fakeTagger.EnrichTags(tb, taggertypes.OriginInfo{ContainerIDFromSocket: "foo://originID", PodUID: "pod-uid", ContainerID: "container-id", Cardinality: "none", ProductOrigin: taggertypes.ProductOriginDogStatsD}) + fakeTagger.EnrichTags(tb, taggertypes.OriginInfo{ContainerIDFromSocket: "foo://bar", PodUID: "pod-uid", ContainerID: "container-id", Cardinality: "none", ProductOrigin: taggertypes.ProductOriginDogStatsD}) assert.Equal(t, []string{}, tb.Get()) - fakeTagger.EnrichTags(tb, taggertypes.OriginInfo{ContainerIDFromSocket: "foo://originID", ContainerID: "container-id", Cardinality: "none", ProductOrigin: taggertypes.ProductOriginDogStatsD}) + fakeTagger.EnrichTags(tb, taggertypes.OriginInfo{ContainerIDFromSocket: "foo://bar", ContainerID: "container-id", Cardinality: "none", ProductOrigin: taggertypes.ProductOriginDogStatsD}) assert.Equal(t, []string{}, tb.Get()) } @@ -179,7 +245,48 @@ func TestGenerateContainerIDFromExternalData(t *testing.T) { } } +func TestAgentTags(t *testing.T) { + fakeTagger := fxutil.Test[tagger.Mock](t, MockModule()) + + agentContainerID, podUID := "agentContainerID", "podUID" + mockMetricsProvider := collectormock.NewMetricsProvider() + cleanUp := setupFakeMetricsProvider(mockMetricsProvider) + defer cleanUp() + + fakeTagger.SetTags(types.NewEntityID(types.KubernetesPodUID, podUID), "fooSource", []string{"pod-low"}, []string{"pod-orch"}, nil, nil) + fakeTagger.SetTags(types.NewEntityID(types.ContainerID, agentContainerID), "fooSource", []string{"container-low"}, []string{"container-orch"}, nil, nil) + + // Expect metrics provider to return an empty container ID so no tags can be found + containerMetaCollector := collectormock.MetaCollector{ContainerID: ""} + mockMetricsProvider.RegisterMetaCollector(&containerMetaCollector) + tagList, err := fakeTagger.AgentTags(types.OrchestratorCardinality) + assert.Nil(t, err) + assert.Nil(t, tagList) + + // Expect metrics provider to return the agent container ID so tags can be found + containerMetaCollector = collectormock.MetaCollector{ContainerID: agentContainerID} + mockMetricsProvider.RegisterMetaCollector(&containerMetaCollector) + tagList, err = fakeTagger.AgentTags(types.OrchestratorCardinality) + assert.NoError(t, err) + assert.Equal(t, []string{"container-low", "container-orch"}, tagList) +} + +func TestGlobalTags(t *testing.T) { + fakeTagger := fxutil.Test[tagger.Mock](t, MockModule()) + fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "bar"), "fooSource", []string{"container-low"}, []string{"container-orch"}, []string{"container-high"}, nil) + fakeTagger.SetGlobalTags([]string{"global-low"}, []string{"global-orch"}, []string{"global-high"}, nil) + + globalTags, err := fakeTagger.GlobalTags(types.OrchestratorCardinality) + assert.Nil(t, err) + assert.Equal(t, []string{"global-low", "global-orch"}, globalTags) + + tb := tagset.NewHashingTagsAccumulator() + fakeTagger.EnrichTags(tb, taggertypes.OriginInfo{ContainerIDFromSocket: "container_id://bar", Cardinality: "orchestrator"}) + assert.Equal(t, []string{"container-low", "container-orch", "global-low", "global-orch"}, tb.Get()) +} + func TestTaggerCardinality(t *testing.T) { + fakeTagger := TaggerClient{} tests := []struct { name string cardinality string @@ -208,18 +315,54 @@ func TestTaggerCardinality(t *testing.T) { { name: "empty", cardinality: "", - want: tagger.DogstatsdCardinality(), + want: fakeTagger.DogstatsdCardinality(), }, { name: "unknown", cardinality: "foo", - want: tagger.DogstatsdCardinality(), + want: fakeTagger.DogstatsdCardinality(), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { l := logmock.New(t) - assert.Equal(t, tt.want, taggerCardinality(tt.cardinality, tagger.DogstatsdCardinality(), l)) + assert.Equal(t, tt.want, taggerCardinality(tt.cardinality, fakeTagger.DogstatsdCardinality(), l)) + }) + } +} + +func TestDefaultCardinality(t *testing.T) { + cfg := configmock.New(t) + for _, tt := range []struct { + name string + wantChecksCardinality types.TagCardinality + wantDogstatsdCardinality types.TagCardinality + setup func() + }{ + { + name: "successful parse config values, use config", + wantChecksCardinality: types.HighCardinality, + wantDogstatsdCardinality: types.OrchestratorCardinality, + setup: func() { + cfg.SetWithoutSource("checks_tag_cardinality", types.HighCardinalityString) + cfg.SetWithoutSource("dogstatsd_tag_cardinality", types.OrchestratorCardinalityString) + }, + }, + { + name: "fail parse config values, use default", + wantChecksCardinality: types.LowCardinality, + wantDogstatsdCardinality: types.LowCardinality, + setup: func() { + cfg.SetWithoutSource("checks_tag_cardinality", "foo") + cfg.SetWithoutSource("dogstatsd_tag_cardinality", "foo") + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + fakeTagger := fxutil.Test[tagger.Mock](t, MockModule()) + assert.Equal(t, tt.wantDogstatsdCardinality, fakeTagger.DogstatsdCardinality()) + assert.Equal(t, tt.wantChecksCardinality, fakeTagger.ChecksCardinality()) }) } } diff --git a/comp/core/workloadmeta/collectors/internal/process/process_collector.go b/comp/core/workloadmeta/collectors/internal/process/process_collector.go index 3d677913016bd..608877ce5c826 100644 --- a/comp/core/workloadmeta/collectors/internal/process/process_collector.go +++ b/comp/core/workloadmeta/collectors/internal/process/process_collector.go @@ -84,7 +84,13 @@ func (c *collector) Start(ctx context.Context, store workloadmeta.Component) err if !pkgconfigsetup.Datadog().GetBool("process_config.process_collection.enabled") { collectionTicker := c.collectionClock.Ticker(10 * time.Second) if c.containerProvider == nil { - c.containerProvider = proccontainers.GetSharedContainerProvider(store) + sharedContainerProvider, err := proccontainers.GetSharedContainerProvider() + + if err != nil { + return err + } + + c.containerProvider = sharedContainerProvider } go c.collect(ctx, c.containerProvider, collectionTicker) } diff --git a/comp/core/workloadmeta/collectors/internal/process/process_collector_test.go b/comp/core/workloadmeta/collectors/internal/process/process_collector_test.go index 3f5415f442e49..8cf4c57cd0eaf 100644 --- a/comp/core/workloadmeta/collectors/internal/process/process_collector_test.go +++ b/comp/core/workloadmeta/collectors/internal/process/process_collector_test.go @@ -63,16 +63,19 @@ func setUpCollectorTest(t *testing.T, configOverrides map[string]interface{}) co mockProcessData, probe := NewProcessDataWithMockProbe(t) mockProcessData.Register(wlmExtractor) mockClock := clock.NewMock() + mockCtrl := gomock.NewController(t) + mockProvider := proccontainers.NewMockContainerProvider(mockCtrl) processDiffCh := wlmExtractor.ProcessCacheDiff() processCollector := &collector{ - id: collectorID, - store: mockStore, - catalog: workloadmeta.NodeAgent, - processDiffCh: processDiffCh, - processData: mockProcessData, - pidToCid: make(map[int]string), - wlmExtractor: wlmExtractor, - collectionClock: mockClock, + id: collectorID, + store: mockStore, + catalog: workloadmeta.NodeAgent, + processDiffCh: processDiffCh, + processData: mockProcessData, + pidToCid: make(map[int]string), + wlmExtractor: wlmExtractor, + collectionClock: mockClock, + containerProvider: mockProvider, } return collectorTest{processCollector, probe, mockClock, mockStore} diff --git a/comp/core/workloadmeta/def/params.go b/comp/core/workloadmeta/def/params.go index 7079caf5517dd..7bf914c6e8030 100644 --- a/comp/core/workloadmeta/def/params.go +++ b/comp/core/workloadmeta/def/params.go @@ -9,7 +9,6 @@ package workloadmeta type Params struct { AgentType AgentType InitHelper InitHelper - NoInstance bool } // NewParams creates a Params struct with the default NodeAgent configuration diff --git a/comp/dogstatsd/replay/impl/capture.go b/comp/dogstatsd/replay/impl/capture.go index c2800904f15ee..29817627034f4 100644 --- a/comp/dogstatsd/replay/impl/capture.go +++ b/comp/dogstatsd/replay/impl/capture.go @@ -16,6 +16,7 @@ import ( "github.com/spf13/afero" configComponent "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" compdef "github.com/DataDog/datadog-agent/comp/def" "github.com/DataDog/datadog-agent/comp/dogstatsd/packets" replay "github.com/DataDog/datadog-agent/comp/dogstatsd/replay/def" @@ -26,12 +27,14 @@ import ( type Requires struct { Lc compdef.Lifecycle Config configComponent.Component + Tagger tagger.Component } // trafficCapture allows capturing traffic from our listeners and writing it to file type trafficCapture struct { writer *TrafficCaptureWriter config model.Reader + tagger tagger.Component startUpError error sync.RWMutex @@ -41,6 +44,7 @@ type trafficCapture struct { func NewTrafficCapture(deps Requires) replay.Component { tc := &trafficCapture{ config: deps.Config, + tagger: deps.Tagger, } deps.Lc.Append(compdef.Hook{ OnStart: tc.configure, @@ -50,7 +54,7 @@ func NewTrafficCapture(deps Requires) replay.Component { } func (tc *trafficCapture) configure(_ context.Context) error { - writer := NewTrafficCaptureWriter(tc.config.GetInt("dogstatsd_capture_depth")) + writer := NewTrafficCaptureWriter(tc.config.GetInt("dogstatsd_capture_depth"), tc.tagger) if writer == nil { tc.startUpError = fmt.Errorf("unable to instantiate capture writer") } diff --git a/comp/dogstatsd/replay/impl/writer.go b/comp/dogstatsd/replay/impl/writer.go index 77f7ea7575351..bfe3a03d1397f 100644 --- a/comp/dogstatsd/replay/impl/writer.go +++ b/comp/dogstatsd/replay/impl/writer.go @@ -64,17 +64,19 @@ type TrafficCaptureWriter struct { oobPacketPoolManager *packets.PoolManager[[]byte] taggerState map[int32]string + tagger tagger.Component // Synchronizes access to ongoing, accepting and closing of Traffic sync.RWMutex } // NewTrafficCaptureWriter creates a TrafficCaptureWriter instance. -func NewTrafficCaptureWriter(depth int) *TrafficCaptureWriter { +func NewTrafficCaptureWriter(depth int, tagger tagger.Component) *TrafficCaptureWriter { return &TrafficCaptureWriter{ Traffic: make(chan *replay.CaptureBuffer, depth), taggerState: make(map[int32]string), + tagger: tagger, } } @@ -322,7 +324,7 @@ func (tc *TrafficCaptureWriter) writeState() (int, error) { } entityID := types.NewEntityID(prefix, id) - entity, err := tagger.GetEntity(entityID) + entity, err := tc.tagger.GetEntity(entityID) if err != nil { log.Warnf("There was no entity for container id: %v present in the tagger", entity) continue diff --git a/comp/dogstatsd/replay/impl/writer_test.go b/comp/dogstatsd/replay/impl/writer_test.go index be394e23ba315..bdb3852d03bdb 100644 --- a/comp/dogstatsd/replay/impl/writer_test.go +++ b/comp/dogstatsd/replay/impl/writer_test.go @@ -20,6 +20,8 @@ import ( "go.uber.org/atomic" "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/comp/core/telemetry" telemetrynoop "github.com/DataDog/datadog-agent/comp/core/telemetry/noopsimpl" "github.com/DataDog/datadog-agent/comp/dogstatsd/packets" @@ -38,7 +40,9 @@ func writerTest(t *testing.T, z bool) { cfg := config.NewMock(t) - writer := NewTrafficCaptureWriter(1) + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + + writer := NewTrafficCaptureWriter(1, taggerComponent) // initialize telemeytry store telemetryComponent := fxutil.Test[telemetry.Component](t, telemetrynoop.Module()) diff --git a/comp/dogstatsd/server/server_test.go b/comp/dogstatsd/server/server_test.go index 53c865af4a654..7588e7a5d105e 100644 --- a/comp/dogstatsd/server/server_test.go +++ b/comp/dogstatsd/server/server_test.go @@ -8,7 +8,6 @@ package server import ( - "bytes" "context" "fmt" "net" @@ -1237,10 +1236,7 @@ dogstatsd_mapper_profiles: tags: foo: "$1" ` - testConfig := configmock.New(t) - testConfig.SetConfigType("yaml") - err := testConfig.ReadConfig(bytes.NewBuffer([]byte(datadogYaml))) - require.NoError(t, err) + testConfig := configmock.NewFromYAML(t, datadogYaml) profiles, err := getDogstatsdMappingProfiles(testConfig) require.NoError(t, err) @@ -1282,10 +1278,7 @@ func TestDogstatsdMappingProfilesEmpty(t *testing.T) { datadogYaml := ` dogstatsd_mapper_profiles: ` - testConfig := configmock.New(t) - testConfig.SetConfigType("yaml") - err := testConfig.ReadConfig(bytes.NewBuffer([]byte(datadogYaml))) - require.NoError(t, err) + testConfig := configmock.NewFromYAML(t, datadogYaml) profiles, err := getDogstatsdMappingProfiles(testConfig) @@ -1300,10 +1293,7 @@ func TestDogstatsdMappingProfilesError(t *testing.T) { dogstatsd_mapper_profiles: - abc ` - testConfig := configmock.New(t) - testConfig.SetConfigType("yaml") - err := testConfig.ReadConfig(bytes.NewBuffer([]byte(datadogYaml))) - require.NoError(t, err) + testConfig := configmock.NewFromYAML(t, datadogYaml) profiles, err := getDogstatsdMappingProfiles(testConfig) diff --git a/comp/forwarder/defaultforwarder/default_forwarder.go b/comp/forwarder/defaultforwarder/default_forwarder.go index fee31b333d31d..0ee76612b5580 100644 --- a/comp/forwarder/defaultforwarder/default_forwarder.go +++ b/comp/forwarder/defaultforwarder/default_forwarder.go @@ -20,8 +20,9 @@ import ( log "github.com/DataDog/datadog-agent/comp/core/log/def" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder/endpoints" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder/internal/retry" - "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder/resolver" + pkgresolver "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder/resolver" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder/transaction" + "github.com/DataDog/datadog-agent/pkg/api/security" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/config/utils" "github.com/DataDog/datadog-agent/pkg/telemetry" @@ -102,7 +103,7 @@ type Options struct { DisableAPIKeyChecking bool EnabledFeatures Features APIKeyValidationInterval time.Duration - DomainResolvers map[string]resolver.DomainResolver + DomainResolvers map[string]pkgresolver.DomainResolver ConnectionResetInterval time.Duration CompletionHandler transaction.HTTPCompletionHandler } @@ -121,14 +122,14 @@ func HasFeature(features, flag Features) bool { return features&flag != 0 } // NewOptions creates new Options with default values func NewOptions(config config.Component, log log.Component, keysPerDomain map[string][]string) *Options { - resolvers := resolver.NewSingleDomainResolvers(keysPerDomain) + resolvers := pkgresolver.NewSingleDomainResolvers(keysPerDomain) vectorMetricsURL, err := pkgconfigsetup.GetObsPipelineURL(pkgconfigsetup.Metrics, config) if err != nil { log.Error("Misconfiguration of agent observability_pipelines_worker endpoint for metrics: ", err) } if r, ok := resolvers[utils.GetInfraEndpoint(config)]; ok && vectorMetricsURL != "" { log.Debugf("Configuring forwarder to send metrics to observability_pipelines_worker: %s", vectorMetricsURL) - resolvers[utils.GetInfraEndpoint(config)] = resolver.NewDomainResolverWithMetricToVector( + resolvers[utils.GetInfraEndpoint(config)] = pkgresolver.NewDomainResolverWithMetricToVector( r.GetBaseDomain(), r.GetAPIKeys(), vectorMetricsURL, @@ -138,7 +139,7 @@ func NewOptions(config config.Component, log log.Component, keysPerDomain map[st } // NewOptionsWithResolvers creates new Options with default values -func NewOptionsWithResolvers(config config.Component, log log.Component, domainResolvers map[string]resolver.DomainResolver) *Options { +func NewOptionsWithResolvers(config config.Component, log log.Component, domainResolvers map[string]pkgresolver.DomainResolver) *Options { validationInterval := config.GetInt("forwarder_apikey_validation_interval") if validationInterval <= 0 { log.Warnf( @@ -181,6 +182,18 @@ func NewOptionsWithResolvers(config config.Component, log log.Component, domainR } } + // domainforwarder to local DCA for autoscaling failover metrics + if config.GetBool("autoscaling.failover.enabled") && config.GetBool("cluster_agent.enabled") { + if domain, err := utils.GetClusterAgentEndpoint(); err != nil { + log.Errorf("Could not get cluster agent endpoint for autoscaling failover metrics: %s", err) + } else if authToken, err := security.GetClusterAgentAuthToken(config); err != nil { + log.Errorf("Failed to get cluster agent auth token: ", err) + } else { + log.Infof("Setting cluster agent domain resolver: %s", domain) + option.DomainResolvers[domain] = pkgresolver.NewLocalDomainResolver(domain, authToken) + } + } + return option } @@ -207,7 +220,8 @@ type DefaultForwarder struct { NumberOfWorkers int domainForwarders map[string]*domainForwarder - domainResolvers map[string]resolver.DomainResolver + domainResolvers map[string]pkgresolver.DomainResolver + localForwarder *domainForwarder // domain forward used for communication with the local cluster-agent healthChecker *forwarderHealth internalState *atomic.Uint32 m sync.Mutex // To control Start/Stop races @@ -228,7 +242,7 @@ func NewDefaultForwarder(config config.Component, log log.Component, options *Op log: log, NumberOfWorkers: options.NumberOfWorkers, domainForwarders: map[string]*domainForwarder{}, - domainResolvers: map[string]resolver.DomainResolver{}, + domainResolvers: map[string]pkgresolver.DomainResolver{}, internalState: atomic.NewUint32(Stopped), healthChecker: &forwarderHealth{ log: log, @@ -239,6 +253,7 @@ func NewDefaultForwarder(config config.Component, log log.Component, options *Op }, completionHandler: options.CompletionHandler, agentName: agentName, + localForwarder: nil, } var optionalRemovalPolicy *retry.FileRemovalPolicy storageMaxSize := config.GetInt64("forwarder_storage_max_size_in_bytes") @@ -294,7 +309,9 @@ func NewDefaultForwarder(config config.Component, log log.Component, options *Op } domain, _ := utils.AddAgentVersionToDomain(domain, "app") resolver.SetBaseDomain(domain) - if resolver.GetAPIKeys() == nil || len(resolver.GetAPIKeys()) == 0 { + + _, isLocal := resolver.(*pkgresolver.LocalDomainResolver) + if !isLocal && (resolver.GetAPIKeys() == nil || len(resolver.GetAPIKeys()) == 0) { log.Errorf("No API keys for domain '%s', dropping domain ", domain) } else { var domainFolderPath string @@ -322,6 +339,7 @@ func NewDefaultForwarder(config config.Component, log log.Component, options *Op log, domain, isMRF, + isLocal, transactionContainer, options.NumberOfWorkers, options.ConnectionResetInterval, @@ -474,35 +492,59 @@ func (f *DefaultForwarder) createAdvancedHTTPTransactions(endpoint transaction.E for _, payload := range payloads { for domain, dr := range f.domainResolvers { - for _, apiKey := range dr.GetAPIKeys() { - t := transaction.NewHTTPTransaction() - t.Domain, _ = dr.Resolve(endpoint) - t.Endpoint = endpoint - t.Payload = payload - t.Priority = priority - t.Kind = kind - t.StorableOnDisk = storableOnDisk - t.Destination = payload.Destination - t.Headers.Set(apiHTTPHeaderKey, apiKey) - t.Headers.Set(versionHTTPHeaderKey, version.AgentVersion) - t.Headers.Set(useragentHTTPHeaderKey, fmt.Sprintf("datadog-agent/%s", version.AgentVersion)) - if allowArbitraryTags { - t.Headers.Set(arbitraryTagHTTPHeaderKey, "true") + drDomain, destinationType := dr.Resolve(endpoint) // drDomain is the domain with agent version if not local + if payload.Destination == transaction.LocalOnly { + // if it is local payload, we should not send it to the remote endpoint + if destinationType == pkgresolver.Local && endpoint == endpoints.SeriesEndpoint { + t := transaction.NewHTTPTransaction() + t.Domain = drDomain + t.Endpoint = endpoint + t.Payload = payload + t.Priority = priority + t.Kind = kind + t.StorableOnDisk = storableOnDisk + t.Destination = payload.Destination + t.Headers.Set("Authorization", fmt.Sprintf("Bearer %s", dr.GetBearerAuthToken())) + for key := range extra { + t.Headers.Set(key, extra.Get(key)) + } + tlmTxInputCount.Inc(drDomain, endpoint.Name) + tlmTxInputBytes.Add(float64(t.GetPayloadSize()), domain, endpoint.Name) + transactionsInputCountByEndpoint.Add(endpoint.Name, 1) + transactionsInputBytesByEndpoint.Add(endpoint.Name, int64(t.GetPayloadSize())) + transactions = append(transactions, t) } - - if f.completionHandler != nil { - t.CompletionHandler = f.completionHandler - } - - tlmTxInputCount.Inc(domain, endpoint.Name) - tlmTxInputBytes.Add(float64(t.GetPayloadSize()), domain, endpoint.Name) - transactionsInputCountByEndpoint.Add(endpoint.Name, 1) - transactionsInputBytesByEndpoint.Add(endpoint.Name, int64(t.GetPayloadSize())) - - for key := range extra { - t.Headers.Set(key, extra.Get(key)) + } else { + for _, apiKey := range dr.GetAPIKeys() { + t := transaction.NewHTTPTransaction() + t.Domain = drDomain + t.Endpoint = endpoint + t.Payload = payload + t.Priority = priority + t.Kind = kind + t.StorableOnDisk = storableOnDisk + t.Destination = payload.Destination + t.Headers.Set(apiHTTPHeaderKey, apiKey) + t.Headers.Set(versionHTTPHeaderKey, version.AgentVersion) + t.Headers.Set(useragentHTTPHeaderKey, fmt.Sprintf("datadog-agent/%s", version.AgentVersion)) + if allowArbitraryTags { + t.Headers.Set(arbitraryTagHTTPHeaderKey, "true") + } + + if f.completionHandler != nil { + t.CompletionHandler = f.completionHandler + } + + tlmTxInputCount.Inc(domain, endpoint.Name) + tlmTxInputBytes.Add(float64(t.GetPayloadSize()), domain, endpoint.Name) + transactionsInputCountByEndpoint.Add(endpoint.Name, 1) + transactionsInputBytesByEndpoint.Add(endpoint.Name, int64(t.GetPayloadSize())) + + for key := range extra { + t.Headers.Set(key, extra.Get(key)) + } + transactions = append(transactions, t) } - transactions = append(transactions, t) } } } diff --git a/comp/forwarder/defaultforwarder/domain_forwarder.go b/comp/forwarder/defaultforwarder/domain_forwarder.go index 3264cebc57c56..6c493271caf44 100644 --- a/comp/forwarder/defaultforwarder/domain_forwarder.go +++ b/comp/forwarder/defaultforwarder/domain_forwarder.go @@ -31,6 +31,7 @@ type domainForwarder struct { isRetrying *atomic.Bool domain string isMRF bool + isLocal bool numberOfWorkers int highPrio chan transaction.Transaction // use to receive new transactions lowPrio chan transaction.Transaction // use to retry transactions @@ -52,6 +53,7 @@ func newDomainForwarder( log log.Component, domain string, mrf bool, + isLocal bool, retryQueue *retry.TransactionRetryQueue, numberOfWorkers int, connectionResetInterval time.Duration, @@ -62,6 +64,7 @@ func newDomainForwarder( log: log, isRetrying: atomic.NewBool(false), isMRF: mrf, + isLocal: isLocal, domain: domain, numberOfWorkers: numberOfWorkers, retryQueue: retryQueue, @@ -210,7 +213,7 @@ func (f *domainForwarder) Start() error { f.init() for i := 0; i < f.numberOfWorkers; i++ { - w := NewWorker(f.config, f.log, f.highPrio, f.lowPrio, f.requeuedTransaction, f.blockedList, f.pointCountTelemetry) + w := NewWorker(f.config, f.log, f.highPrio, f.lowPrio, f.requeuedTransaction, f.blockedList, f.pointCountTelemetry, f.isLocal) w.Start() f.workers = append(f.workers, w) } diff --git a/comp/forwarder/defaultforwarder/domain_forwarder_test.go b/comp/forwarder/defaultforwarder/domain_forwarder_test.go index 0fa06c2f8f7fa..fa717a4f932df 100644 --- a/comp/forwarder/defaultforwarder/domain_forwarder_test.go +++ b/comp/forwarder/defaultforwarder/domain_forwarder_test.go @@ -8,7 +8,6 @@ package defaultforwarder import ( - "bytes" "testing" "time" @@ -372,7 +371,7 @@ func TestDomainForwarderRetryQueueAllPayloadsMaxSize(t *testing.T) { retry.NewPointCountTelemetryMock()) mockConfig := mock.New(t) log := logmock.New(t) - forwarder := newDomainForwarder(mockConfig, log, "test", false, transactionRetryQueue, 0, 10, transaction.SortByCreatedTimeAndPriority{HighPriorityFirst: true}, retry.NewPointCountTelemetry("domain")) + forwarder := newDomainForwarder(mockConfig, log, "test", false, false, transactionRetryQueue, 0, 10, transaction.SortByCreatedTimeAndPriority{HighPriorityFirst: true}, retry.NewPointCountTelemetry("domain")) forwarder.blockedList.close("blocked") forwarder.blockedList.errorPerEndpoint["blocked"].until = time.Now().Add(1 * time.Minute) @@ -412,9 +411,7 @@ forwarder_high_prio_buffer_size: 1100 forwarder_low_prio_buffer_size: 1200 forwarder_requeue_buffer_size: 1300 ` - mockConfig.SetConfigType("yaml") - err := mockConfig.ReadConfig(bytes.NewBuffer([]byte(datadogYaml))) - assert.NoError(t, err) + mockConfig = mock.NewFromYAML(t, datadogYaml) forwarder = newDomainForwarderForTest(mockConfig, log, 0, false) forwarder.init() @@ -434,7 +431,7 @@ func newDomainForwarderForTest(config config.Component, log log.Component, conne telemetry, retry.NewPointCountTelemetryMock()) - return newDomainForwarder(config, log, "test", ha, transactionRetryQueue, 1, connectionResetInterval, sorter, retry.NewPointCountTelemetry("domain")) + return newDomainForwarder(config, log, "test", ha, false, transactionRetryQueue, 1, connectionResetInterval, sorter, retry.NewPointCountTelemetry("domain")) } func requireLenForwarderRetryQueue(t *testing.T, forwarder *domainForwarder, expectedValue int) { diff --git a/comp/forwarder/defaultforwarder/forwarder_test.go b/comp/forwarder/defaultforwarder/forwarder_test.go index 80e4f77460dde..2953420a93e8a 100644 --- a/comp/forwarder/defaultforwarder/forwarder_test.go +++ b/comp/forwarder/defaultforwarder/forwarder_test.go @@ -60,6 +60,22 @@ func TestNewDefaultForwarder(t *testing.T) { assert.Equal(t, forwarder.internalState.Load(), Stopped) assert.Equal(t, forwarder.State(), forwarder.internalState.Load()) + + mockConfig.SetWithoutSource("autoscaling.failover.enabled", true) + mockConfig.SetWithoutSource("cluster_agent.enabled", true) + localDomain := "https://localhost" + localAuth := "tokenABCD12345678910109876543210" + mockConfig.SetWithoutSource("cluster_agent.url", localDomain) + mockConfig.SetWithoutSource("cluster_agent.auth_token", localAuth) + forwarder2 := NewDefaultForwarder(mockConfig, log, NewOptionsWithResolvers(mockConfig, log, resolver.NewSingleDomainResolvers(keysPerDomains))) + assert.NotNil(t, forwarder2) + assert.Equal(t, 1, forwarder2.NumberOfWorkers) + require.Len(t, forwarder2.domainForwarders, 2) // 1 remote domain, 1 dca domain + domainResolver := resolver.NewSingleDomainResolvers(validKeysPerDomain) + domainResolver[localDomain] = resolver.NewLocalDomainResolver(localDomain, localAuth) + assert.Equal(t, domainResolver, forwarder2.domainResolvers) + assert.Equal(t, forwarder2.internalState.Load(), Stopped) + assert.Equal(t, forwarder2.State(), forwarder2.internalState.Load()) } func TestFeature(t *testing.T) { diff --git a/comp/forwarder/defaultforwarder/go.mod b/comp/forwarder/defaultforwarder/go.mod index f537057c1b663..9cc8e700dbc0e 100644 --- a/comp/forwarder/defaultforwarder/go.mod +++ b/comp/forwarder/defaultforwarder/go.mod @@ -14,6 +14,7 @@ replace ( github.com/DataDog/datadog-agent/comp/core/telemetry => ../../core/telemetry github.com/DataDog/datadog-agent/comp/def => ../../def github.com/DataDog/datadog-agent/comp/serializer/compression => ../../../comp/serializer/compression/ + github.com/DataDog/datadog-agent/pkg/api => ../../../pkg/api github.com/DataDog/datadog-agent/pkg/collector/check/defaults => ../../../pkg/collector/check/defaults github.com/DataDog/datadog-agent/pkg/config/env => ../../../pkg/config/env github.com/DataDog/datadog-agent/pkg/config/mock => ../../../pkg/config/mock @@ -51,25 +52,26 @@ replace ( ) require ( - github.com/DataDog/datadog-agent/comp/core/config v0.56.0-rc.3 + github.com/DataDog/datadog-agent/comp/core/config v0.57.1 github.com/DataDog/datadog-agent/comp/core/log/def v0.0.0-00010101000000-000000000000 github.com/DataDog/datadog-agent/comp/core/log/mock v0.0.0-00010101000000-000000000000 github.com/DataDog/datadog-agent/comp/core/status v0.56.0-rc.3 + github.com/DataDog/datadog-agent/pkg/api v0.57.1 github.com/DataDog/datadog-agent/pkg/config/mock v0.58.0-devel github.com/DataDog/datadog-agent/pkg/config/model v0.57.1 github.com/DataDog/datadog-agent/pkg/config/setup v0.57.1 - github.com/DataDog/datadog-agent/pkg/config/utils v0.56.0-rc.3 + github.com/DataDog/datadog-agent/pkg/config/utils v0.57.1 github.com/DataDog/datadog-agent/pkg/orchestrator/model v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/status/health v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/telemetry v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/util/backoff v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/util/common v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/util/filesystem v0.57.1 - github.com/DataDog/datadog-agent/pkg/util/fxutil v0.56.0-rc.3 + github.com/DataDog/datadog-agent/pkg/util/fxutil v0.57.1 github.com/DataDog/datadog-agent/pkg/util/http v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/util/optional v0.57.1 github.com/DataDog/datadog-agent/pkg/util/scrubber v0.57.1 - github.com/DataDog/datadog-agent/pkg/version v0.56.0-rc.3 + github.com/DataDog/datadog-agent/pkg/version v0.57.1 github.com/golang/protobuf v1.5.3 github.com/hashicorp/go-multierror v1.1.1 github.com/stretchr/testify v1.9.0 @@ -79,11 +81,11 @@ require ( ) require ( - github.com/DataDog/datadog-agent/comp/core/flare/builder v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/types v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/builder v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/types v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/secrets v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/telemetry v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/def v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/comp/def v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/collector/check/defaults v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/env v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/nodetreemodel v0.60.0-devel // indirect diff --git a/comp/forwarder/defaultforwarder/resolver/domain_resolver.go b/comp/forwarder/defaultforwarder/resolver/domain_resolver.go index 9b5f94b0f7fe9..7966eb23013de 100644 --- a/comp/forwarder/defaultforwarder/resolver/domain_resolver.go +++ b/comp/forwarder/defaultforwarder/resolver/domain_resolver.go @@ -23,6 +23,8 @@ const ( Datadog DestinationType = iota // Vector endpoints Vector + // Local endpoints + Local ) // DomainResolver interface abstracts domain selection by `transaction.Endpoint` @@ -40,6 +42,8 @@ type DomainResolver interface { SetBaseDomain(domain string) // UpdateAPIKey replaces instances of the oldKey with the newKey UpdateAPIKey(oldKey, newKey string) + // GetBearerAuthToken returns Bearer authtoken, used for internal communication + GetBearerAuthToken() string } // SingleDomainResolver will always return the same host @@ -109,6 +113,11 @@ func (r *SingleDomainResolver) UpdateAPIKey(oldKey, newKey string) { r.apiKeys = replace } +// GetBearerAuthToken is not implemented for SingleDomainResolver +func (r *SingleDomainResolver) GetBearerAuthToken() string { + return "" +} + type destination struct { domain string dType DestinationType @@ -196,6 +205,11 @@ func (r *MultiDomainResolver) RegisterAlternateDestination(domain string, forwar r.alternateDomainList = append(r.alternateDomainList, domain) } +// GetBearerAuthToken is not implemented for MultiDomainResolver +func (r *MultiDomainResolver) GetBearerAuthToken() string { + return "" +} + // NewDomainResolverWithMetricToVector initialize a resolver with metrics diverted to a vector endpoint func NewDomainResolverWithMetricToVector(mainEndpoint string, apiKeys []string, vectorEndpoint string) *MultiDomainResolver { r := NewMultiDomainResolver(mainEndpoint, apiKeys) @@ -204,3 +218,52 @@ func NewDomainResolverWithMetricToVector(mainEndpoint string, apiKeys []string, r.RegisterAlternateDestination(vectorEndpoint, endpoints.SketchSeriesEndpoint.Name, Vector) return r } + +// LocalDomainResolver contains domain address in local cluster and authToken for internal communication +type LocalDomainResolver struct { + domain string + authToken string +} + +// NewLocalDomainResolver creates a LocalDomainResolver with domain in local cluster and authToken for internal communication +// For example, the internal cluster-agent endpoint +func NewLocalDomainResolver(domain string, authToken string) *LocalDomainResolver { + return &LocalDomainResolver{ + domain, + authToken, + } +} + +// Resolve returns the domain to be used to send data and local destination type +func (r *LocalDomainResolver) Resolve(transaction.Endpoint) (string, DestinationType) { + return r.domain, Local +} + +// GetBaseDomain returns the base domain for this LocalDomainResolver +func (r *LocalDomainResolver) GetBaseDomain() string { + return r.domain +} + +// GetAPIKeys is not implemented for LocalDomainResolver +func (r *LocalDomainResolver) GetAPIKeys() []string { + return []string{} +} + +// SetBaseDomain sets the base domain to a new value +func (r *LocalDomainResolver) SetBaseDomain(domain string) { + r.domain = domain +} + +// GetAlternateDomains is not implemented for LocalDomainResolver +func (r *LocalDomainResolver) GetAlternateDomains() []string { + return []string{} +} + +// UpdateAPIKey is not implemented for LocalDomainResolver +func (r *LocalDomainResolver) UpdateAPIKey(_, _ string) { +} + +// GetBearerAuthToken returns Bearer authtoken, used for internal communication +func (r *LocalDomainResolver) GetBearerAuthToken() string { + return r.authToken +} diff --git a/comp/forwarder/defaultforwarder/transaction/transaction.go b/comp/forwarder/defaultforwarder/transaction/transaction.go index 35a1ce71a5eec..8516ffea248f4 100644 --- a/comp/forwarder/defaultforwarder/transaction/transaction.go +++ b/comp/forwarder/defaultforwarder/transaction/transaction.go @@ -204,6 +204,8 @@ const ( PrimaryOnly // SecondaryOnly indicates the transaction should be sent to the secondary region during MRF SecondaryOnly + // LocalOnly indicates the transaction should be sent to the local endpoint (cluster-agent) only + LocalOnly ) func (d Destination) String() string { @@ -214,6 +216,8 @@ func (d Destination) String() string { return "PrimaryOnly" case SecondaryOnly: return "SecondaryOnly" + case LocalOnly: + return "LocalOnly" default: return "Unknown" } diff --git a/comp/forwarder/defaultforwarder/worker.go b/comp/forwarder/defaultforwarder/worker.go index bf839d49093de..73552e299a836 100644 --- a/comp/forwarder/defaultforwarder/worker.go +++ b/comp/forwarder/defaultforwarder/worker.go @@ -7,7 +7,9 @@ package defaultforwarder import ( "context" + "crypto/tls" "fmt" + "net" "net/http" "net/http/httptrace" "time" @@ -39,6 +41,8 @@ type Worker struct { stopped chan struct{} blockedList *blockedEndpoints pointSuccessfullySent PointSuccessfullySent + // If the client is for cluster agent + isLocal bool } // PointSuccessfullySent is called when sending successfully a point to the intake. @@ -56,8 +60,9 @@ func NewWorker( requeueChan chan<- transaction.Transaction, blocked *blockedEndpoints, pointSuccessfullySent PointSuccessfullySent, + isLocal bool, ) *Worker { - return &Worker{ + worker := &Worker{ config: config, log: log, HighPrio: highPrioChan, @@ -69,7 +74,14 @@ func NewWorker( Client: NewHTTPClient(config), blockedList: blocked, pointSuccessfullySent: pointSuccessfullySent, + isLocal: isLocal, } + if isLocal { + worker.Client = newBearerAuthHTTPClient() + } else { + worker.Client = NewHTTPClient(config) + } + return worker } // NewHTTPClient creates a new http.Client @@ -82,6 +94,27 @@ func NewHTTPClient(config config.Component) *http.Client { } } +func newBearerAuthHTTPClient() *http.Client { + return &http.Client{ + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 1 * time.Second, + KeepAlive: 20 * time.Second, + }).DialContext, + ForceAttemptHTTP2: false, + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + TLSHandshakeTimeout: 5 * time.Second, + MaxConnsPerHost: 1, + MaxIdleConnsPerHost: 1, + IdleConnTimeout: 60 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + ResponseHeaderTimeout: 3 * time.Second, + }, + Timeout: 10 * time.Second, + } +} + // Stop stops the worker. func (w *Worker) Stop(purgeHighPrio bool) { w.stopChan <- struct{}{} @@ -209,5 +242,9 @@ func (w *Worker) requeue(t transaction.Transaction) { func (w *Worker) resetConnections() { w.log.Debug("Resetting worker's connections") w.Client.CloseIdleConnections() - w.Client = NewHTTPClient(w.config) + if w.isLocal { + w.Client = newBearerAuthHTTPClient() + } else { + w.Client = NewHTTPClient(w.config) + } } diff --git a/comp/forwarder/defaultforwarder/worker_test.go b/comp/forwarder/defaultforwarder/worker_test.go index bf9c9a436bc27..8902992179bcc 100644 --- a/comp/forwarder/defaultforwarder/worker_test.go +++ b/comp/forwarder/defaultforwarder/worker_test.go @@ -29,7 +29,7 @@ func TestNewWorker(t *testing.T) { mockConfig := mock.New(t) log := logmock.New(t) - w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}) + w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}, false) assert.NotNil(t, w) assert.Equal(t, w.Client.Timeout, mockConfig.GetDuration("forwarder_timeout")*time.Second) } @@ -42,7 +42,7 @@ func TestNewNoSSLWorker(t *testing.T) { mockConfig := mock.New(t) mockConfig.SetWithoutSource("skip_ssl_validation", true) log := logmock.New(t) - w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}) + w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}, false) assert.True(t, w.Client.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify) } @@ -53,7 +53,7 @@ func TestWorkerStart(t *testing.T) { sender := &PointSuccessfullySentMock{} mockConfig := mock.New(t) log := logmock.New(t) - w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), sender) + w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), sender, false) mock := newTestTransaction() mock.pointCount = 1 @@ -90,7 +90,7 @@ func TestWorkerRetry(t *testing.T) { requeue := make(chan transaction.Transaction, 1) mockConfig := mock.New(t) log := logmock.New(t) - w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}) + w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}, false) mock := newTestTransaction() mock.On("Process", w.Client).Return(fmt.Errorf("some kind of error")).Times(1) @@ -113,7 +113,7 @@ func TestWorkerRetryBlockedTransaction(t *testing.T) { requeue := make(chan transaction.Transaction, 1) mockConfig := mock.New(t) log := logmock.New(t) - w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}) + w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}, false) mock := newTestTransaction() mock.On("GetTarget").Return("error_url").Times(1) @@ -136,7 +136,7 @@ func TestWorkerResetConnections(t *testing.T) { requeue := make(chan transaction.Transaction, 1) mockConfig := mock.New(t) log := logmock.New(t) - w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}) + w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}, false) mock := newTestTransaction() mock.On("Process", w.Client).Return(nil).Times(1) @@ -181,7 +181,7 @@ func TestWorkerPurgeOnStop(t *testing.T) { requeue := make(chan transaction.Transaction, 1) mockConfig := mock.New(t) log := logmock.New(t) - w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}) + w := NewWorker(mockConfig, log, highPrio, lowPrio, requeue, newBlockedEndpoints(mockConfig, log), &PointSuccessfullySentMock{}, false) // making stopChan non blocking on insert and closing stopped channel // to avoid blocking in the Stop method since we don't actually start // the workder diff --git a/comp/forwarder/orchestrator/orchestratorinterface/go.mod b/comp/forwarder/orchestrator/orchestratorinterface/go.mod index 43eaf8ff9461d..72ca1ccd0fd30 100644 --- a/comp/forwarder/orchestrator/orchestratorinterface/go.mod +++ b/comp/forwarder/orchestrator/orchestratorinterface/go.mod @@ -15,6 +15,7 @@ replace ( github.com/DataDog/datadog-agent/comp/def => ../../../def github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder => ../../defaultforwarder/ github.com/DataDog/datadog-agent/pkg/aggregator/ckey => ../../../../pkg/aggregator/ckey + github.com/DataDog/datadog-agent/pkg/api => ../../../../pkg/api github.com/DataDog/datadog-agent/pkg/collector/check/defaults => ../../../../pkg/collector/check/defaults github.com/DataDog/datadog-agent/pkg/config/env => ../../../../pkg/config/env github.com/DataDog/datadog-agent/pkg/config/mock => ../../../../pkg/config/mock @@ -64,14 +65,15 @@ replace ( ) require ( - github.com/DataDog/datadog-agent/comp/core/config v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/builder v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/types v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/comp/core/config v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/builder v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/types v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/log/def v0.0.0-00010101000000-000000000000 // indirect github.com/DataDog/datadog-agent/comp/core/secrets v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/status v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/comp/core/telemetry v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/def v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/comp/def v0.57.1 // indirect + github.com/DataDog/datadog-agent/pkg/api v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/collector/check/defaults v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/env v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/mock v0.58.0-devel // indirect @@ -79,7 +81,7 @@ require ( github.com/DataDog/datadog-agent/pkg/config/nodetreemodel v0.60.0-devel // indirect github.com/DataDog/datadog-agent/pkg/config/setup v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/teeconfig v0.60.0-devel // indirect - github.com/DataDog/datadog-agent/pkg/config/utils v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/config/utils v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/orchestrator/model v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/status/health v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/telemetry v0.56.0-rc.3 // indirect @@ -87,7 +89,7 @@ require ( github.com/DataDog/datadog-agent/pkg/util/common v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/util/executable v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/filesystem v0.57.1 // indirect - github.com/DataDog/datadog-agent/pkg/util/fxutil v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/util/fxutil v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/hostname/validate v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/http v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/util/log v0.57.1 // indirect @@ -97,7 +99,7 @@ require ( github.com/DataDog/datadog-agent/pkg/util/system v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/system/socket v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/winutil v0.57.1 // indirect - github.com/DataDog/datadog-agent/pkg/version v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/version v0.57.1 // indirect github.com/DataDog/viper v1.13.5 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/comp/logs/agent/agentimpl/agent_core_init.go b/comp/logs/agent/agentimpl/agent_core_init.go index 467e6c66d762c..37d5c029cf0f6 100644 --- a/comp/logs/agent/agentimpl/agent_core_init.go +++ b/comp/logs/agent/agentimpl/agent_core_init.go @@ -64,7 +64,7 @@ func (a *logAgent) SetupPipeline(processingRules []*config.ProcessingRule, wmeta a.flarecontroller, a.tagger)) lnchrs.AddLauncher(listener.NewLauncher(a.config.GetInt("logs_config.frame_size"))) - lnchrs.AddLauncher(journald.NewLauncher(a.flarecontroller)) + lnchrs.AddLauncher(journald.NewLauncher(a.flarecontroller, a.tagger)) lnchrs.AddLauncher(windowsevent.NewLauncher()) lnchrs.AddLauncher(container.NewLauncher(a.sources, wmeta, a.tagger)) lnchrs.AddLauncher(integrationLauncher.NewLauncher( diff --git a/comp/logs/agent/agentimpl/agent_test.go b/comp/logs/agent/agentimpl/agent_test.go index c5cefb6be5113..d419f6aa52399 100644 --- a/comp/logs/agent/agentimpl/agent_test.go +++ b/comp/logs/agent/agentimpl/agent_test.go @@ -106,7 +106,6 @@ func (suite *AgentTestSuite) TearDownTest() { metrics.LogsSent.Set(0) metrics.DestinationErrors.Set(0) metrics.DestinationLogsDropped.Init() - suite.tagger.(tagger.Mock).ResetTagger() } func createAgent(suite *AgentTestSuite, endpoints *config.Endpoints) (*logAgent, *sources.LogSources, *service.Services) { @@ -127,7 +126,6 @@ func createAgent(suite *AgentTestSuite, endpoints *config.Endpoints) (*logAgent, )) fakeTagger := taggerimpl.SetupFakeTagger(suite.T()) - defer fakeTagger.ResetTagger() agent := &logAgent{ log: deps.Log, diff --git a/comp/metadata/host/hostimpl/utils/host.go b/comp/metadata/host/hostimpl/utils/host.go index 72ed11ad307cc..e59019459e5d6 100644 --- a/comp/metadata/host/hostimpl/utils/host.go +++ b/comp/metadata/host/hostimpl/utils/host.go @@ -175,7 +175,7 @@ func GetPayload(ctx context.Context, conf model.Reader) *Payload { hostnameData = hostname.Data{Hostname: "unknown", Provider: "unknown"} } - meta := GetMeta(ctx, conf) + meta := getMeta(ctx, conf) meta.Hostname = hostnameData.Hostname p := &Payload{ diff --git a/comp/metadata/host/hostimpl/utils/meta.go b/comp/metadata/host/hostimpl/utils/meta.go index bbd5f2b479cf9..087bee6cad3f3 100644 --- a/comp/metadata/host/hostimpl/utils/meta.go +++ b/comp/metadata/host/hostimpl/utils/meta.go @@ -25,15 +25,17 @@ var ( // Meta is the metadata nested under the meta key type Meta struct { - SocketHostname string `json:"socket-hostname"` - Timezones []string `json:"timezones"` - SocketFqdn string `json:"socket-fqdn"` - EC2Hostname string `json:"ec2-hostname"` - Hostname string `json:"hostname"` - HostAliases []string `json:"host_aliases"` - InstanceID string `json:"instance-id"` - AgentHostname string `json:"agent-hostname,omitempty"` - ClusterName string `json:"cluster-name,omitempty"` + SocketHostname string `json:"socket-hostname"` + Timezones []string `json:"timezones"` + SocketFqdn string `json:"socket-fqdn"` + EC2Hostname string `json:"ec2-hostname"` + Hostname string `json:"hostname"` + HostAliases []string `json:"host_aliases"` + InstanceID string `json:"instance-id"` + AgentHostname string `json:"agent-hostname,omitempty"` + ClusterName string `json:"cluster-name,omitempty"` + LegacyResolutionHostname string `json:"legacy-resolution-hostname,omitempty"` + HostnameResolutionVersion int `json:"hostname-resolution-version,omitempty"` } // GetMetaFromCache returns the metadata information about the host from the cache and returns it, if the cache is @@ -42,14 +44,14 @@ func GetMetaFromCache(ctx context.Context, conf model.Reader) *Meta { res, _ := cache.Get[*Meta]( metaCacheKey, func() (*Meta, error) { - return GetMeta(ctx, conf), nil + return getMeta(ctx, conf), nil }, ) return res } -// GetMeta returns the metadata information about the host and refreshes the cache -func GetMeta(ctx context.Context, conf model.Reader) *Meta { +// getMeta returns the metadata information about the host and refreshes the cache +func getMeta(ctx context.Context, conf model.Reader) *Meta { osHostname, _ := os.Hostname() tzname, _ := time.Now().Zone() ec2Hostname, _ := ec2.GetHostname(ctx) @@ -63,13 +65,19 @@ func GetMeta(ctx context.Context, conf model.Reader) *Meta { } m := &Meta{ - SocketHostname: osHostname, - Timezones: []string{tzname}, - SocketFqdn: util.Fqdn(osHostname), - EC2Hostname: ec2Hostname, - HostAliases: cloudproviders.GetHostAliases(ctx), - InstanceID: instanceID, - AgentHostname: agentHostname, + SocketHostname: osHostname, + Timezones: []string{tzname}, + SocketFqdn: util.Fqdn(osHostname), + EC2Hostname: ec2Hostname, + HostAliases: cloudproviders.GetHostAliases(ctx), + InstanceID: instanceID, + AgentHostname: agentHostname, + HostnameResolutionVersion: 1, + } + + legacyResolutionHostnameData, _ := hostname.GetWithProviderLegacyResolution(ctx) + if legacyResolutionHostnameData.Hostname != hostnameData.Hostname { + m.LegacyResolutionHostname = legacyResolutionHostnameData.Hostname } if finalClusterName := kubelet.GetMetaClusterNameText(ctx, osHostname); finalClusterName != "" { diff --git a/comp/metadata/host/hostimpl/utils/meta_test.go b/comp/metadata/host/hostimpl/utils/meta_test.go index 6bca2107e9eb4..d628b31e144a7 100644 --- a/comp/metadata/host/hostimpl/utils/meta_test.go +++ b/comp/metadata/host/hostimpl/utils/meta_test.go @@ -18,7 +18,7 @@ func TestGetMeta(t *testing.T) { ctx := context.Background() cfg := config.NewMock(t) - meta := GetMeta(ctx, cfg) + meta := getMeta(ctx, cfg) assert.NotEmpty(t, meta.SocketHostname) assert.NotEmpty(t, meta.Timezones) assert.NotEmpty(t, meta.SocketFqdn) diff --git a/comp/metadata/inventoryagent/README.md b/comp/metadata/inventoryagent/README.md index 855907ff4e9d6..413e08865fb97 100644 --- a/comp/metadata/inventoryagent/README.md +++ b/comp/metadata/inventoryagent/README.md @@ -66,7 +66,7 @@ The payload is a JSON dict with the following fields - `system_probe_core_enabled` - **bool**: True if CO-RE is enabled in the System Probe (see: `system_probe_config.enable_co_re` config option in `system-probe.yaml`). - `system_probe_runtime_compilation_enabled` - **bool**: True if Runtime Compilation is enabled in the System Probe (see: `system_probe_config.enable_runtime_compiler` config option in `system-probe.yaml`). - `system_probe_kernel_headers_download_enabled` - **bool**: True if Kernel header downloading is enabled in the System Probe (see: `system_probe_config.enable_kernel_header_download` config option in `system-probe.yaml`). - - `system_probe_prebuilt_fallback_enabled` - **bool**: True if the System Probe will fallback to prebuilt when other options fail (see: `system_probe_config.allow_precompiled_fallback` config option in `system-probe.yaml`). + - `system_probe_prebuilt_fallback_enabled` - **bool**: True if the System Probe will fallback to prebuilt when other options fail (see: `system_probe_config.allow_prebuilt_fallback` config option in `system-probe.yaml`). - `system_probe_max_connections_per_message` - **int**: The maximum number of connections per message (see: `system_probe_config.max_conns_per_message` config option in `system-probe.yaml`). - `system_probe_track_tcp_4_connections` - **bool**: True if tracking TCPv4 connections is enabled in the System Probe (see: `network_config.collect_tcp_v4` config option in `system-probe.yaml`). - `system_probe_track_tcp_6_connections` - **bool**: True if tracking TCPv6 connections is enabled in the System Probe (see: `network_config.collect_tcp_v6` config option in `system-probe.yaml`). diff --git a/comp/metadata/inventoryagent/inventoryagentimpl/inventoryagent.go b/comp/metadata/inventoryagent/inventoryagentimpl/inventoryagent.go index 1c9435cabc9bd..4af65ceb7dd83 100644 --- a/comp/metadata/inventoryagent/inventoryagentimpl/inventoryagent.go +++ b/comp/metadata/inventoryagent/inventoryagentimpl/inventoryagent.go @@ -317,7 +317,7 @@ func (ia *inventoryagent) fetchSystemProbeMetadata() { ia.data["system_probe_core_enabled"] = sysProbeConf.GetBool("system_probe_config.enable_co_re") ia.data["system_probe_runtime_compilation_enabled"] = sysProbeConf.GetBool("system_probe_config.enable_runtime_compiler") ia.data["system_probe_kernel_headers_download_enabled"] = sysProbeConf.GetBool("system_probe_config.enable_kernel_header_download") - ia.data["system_probe_prebuilt_fallback_enabled"] = sysProbeConf.GetBool("system_probe_config.allow_precompiled_fallback") + ia.data["system_probe_prebuilt_fallback_enabled"] = sysProbeConf.GetBool("system_probe_config.allow_prebuilt_fallback") ia.data["system_probe_telemetry_enabled"] = sysProbeConf.GetBool("system_probe_config.telemetry_enabled") ia.data["system_probe_max_connections_per_message"] = sysProbeConf.GetInt("system_probe_config.max_conns_per_message") ia.data["system_probe_track_tcp_4_connections"] = sysProbeConf.GetBool("network_config.collect_tcp_v4") diff --git a/comp/metadata/inventoryagent/inventoryagentimpl/inventoryagent_test.go b/comp/metadata/inventoryagent/inventoryagentimpl/inventoryagent_test.go index e57527e82cbaf..876dea30e8db8 100644 --- a/comp/metadata/inventoryagent/inventoryagentimpl/inventoryagent_test.go +++ b/comp/metadata/inventoryagent/inventoryagentimpl/inventoryagent_test.go @@ -13,11 +13,10 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "go.uber.org/fx" "golang.org/x/exp/maps" - "github.com/stretchr/testify/assert" - authtokenimpl "github.com/DataDog/datadog-agent/comp/api/authtoken/fetchonlyimpl" "github.com/DataDog/datadog-agent/comp/core/config" log "github.com/DataDog/datadog-agent/comp/core/log/def" @@ -28,6 +27,7 @@ import ( sysprobeConfigFetcher "github.com/DataDog/datadog-agent/pkg/config/fetcher/sysprobe" pkgconfigmodel "github.com/DataDog/datadog-agent/pkg/config/model" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" "github.com/DataDog/datadog-agent/pkg/serializer" serializermock "github.com/DataDog/datadog-agent/pkg/serializer/mocks" "github.com/DataDog/datadog-agent/pkg/util/flavor" @@ -132,7 +132,7 @@ func TestInitData(t *testing.T) { "system_probe_config.enable_co_re": true, "system_probe_config.enable_runtime_compiler": true, "system_probe_config.enable_kernel_header_download": true, - "system_probe_config.allow_precompiled_fallback": true, + "system_probe_config.allow_prebuilt_fallback": true, "system_probe_config.telemetry_enabled": true, "system_probe_config.max_conns_per_message": 10, "system_probe_config.disable_ipv6": false, @@ -472,6 +472,8 @@ func TestFetchSystemProbeAgent(t *testing.T) { return "", fmt.Errorf("some error") } + isPrebuiltDeprecated := prebuilt.IsDeprecated() + ia := getTestInventoryPayload(t, nil, nil) ia.fetchSystemProbeMetadata() @@ -497,7 +499,9 @@ func TestFetchSystemProbeAgent(t *testing.T) { assert.True(t, ia.data["system_probe_core_enabled"].(bool)) assert.False(t, ia.data["system_probe_runtime_compilation_enabled"].(bool)) assert.False(t, ia.data["system_probe_kernel_headers_download_enabled"].(bool)) - assert.True(t, ia.data["system_probe_prebuilt_fallback_enabled"].(bool)) + if runtime.GOOS == "linux" { + assert.Equal(t, !isPrebuiltDeprecated, ia.data["system_probe_prebuilt_fallback_enabled"].(bool)) + } assert.False(t, ia.data["system_probe_telemetry_enabled"].(bool)) assert.Equal(t, 600, ia.data["system_probe_max_connections_per_message"].(int)) assert.True(t, ia.data["system_probe_track_tcp_4_connections"].(bool)) @@ -614,7 +618,7 @@ system_probe_config: enable_co_re: true enable_runtime_compiler: true enable_kernel_header_download: true - allow_precompiled_fallback: true + allow_prebuilt_fallback: true telemetry_enabled: true max_conns_per_message: 123 diff --git a/comp/metadata/inventorychecks/inventorychecksimpl/inventorychecks_test.go b/comp/metadata/inventorychecks/inventorychecksimpl/inventorychecks_test.go index 8f0dd83c49cec..253e84d8e8eb7 100644 --- a/comp/metadata/inventorychecks/inventorychecksimpl/inventorychecks_test.go +++ b/comp/metadata/inventorychecks/inventorychecksimpl/inventorychecks_test.go @@ -153,7 +153,6 @@ func TestGetPayload(t *testing.T) { src.Status.Error(fmt.Errorf("No such file or directory")) logSources.AddSource(src) fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() mockLogAgent := fxutil.Test[optional.Option[logagent.Mock]]( t, diff --git a/comp/ndmtmp/bundle.go b/comp/ndmtmp/bundle.go index b4c75dff3c20f..22061d7015bd8 100644 --- a/comp/ndmtmp/bundle.go +++ b/comp/ndmtmp/bundle.go @@ -13,7 +13,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) -// team: network-device-monitoring +// team: ndm-core // TODO: (components) Delete this module when the sender and event platform forwarder are fully componentized. diff --git a/comp/ndmtmp/bundle_mock.go b/comp/ndmtmp/bundle_mock.go index a264655bb271c..df3f70f7cf2fc 100644 --- a/comp/ndmtmp/bundle_mock.go +++ b/comp/ndmtmp/bundle_mock.go @@ -16,7 +16,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) -// team: network-device-monitoring +// team: ndm-core // MockBundle defines the fx options for mock versions of everything in this bundle. func MockBundle() fxutil.BundleOptions { diff --git a/comp/ndmtmp/forwarder/component.go b/comp/ndmtmp/forwarder/component.go index eaf32733da342..e8f535198e85b 100644 --- a/comp/ndmtmp/forwarder/component.go +++ b/comp/ndmtmp/forwarder/component.go @@ -10,7 +10,7 @@ import ( "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" ) -// team: network-device-monitoring +// team: ndm-core // Component is the component type. type Component interface { diff --git a/comp/netflow/bundle.go b/comp/netflow/bundle.go index 88702e3e72705..af20705060270 100644 --- a/comp/netflow/bundle.go +++ b/comp/netflow/bundle.go @@ -13,7 +13,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) -// team: network-device-monitoring +// team: ndm-integrations // Bundle defines the fx options for this bundle. func Bundle() fxutil.BundleOptions { diff --git a/comp/netflow/config/component.go b/comp/netflow/config/component.go index 0718c59a30300..dd0d06c939c8f 100644 --- a/comp/netflow/config/component.go +++ b/comp/netflow/config/component.go @@ -12,7 +12,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) -// team: network-device-monitoring +// team: ndm-integrations // Component is the component type. type Component interface { diff --git a/comp/netflow/config/config_test.go b/comp/netflow/config/config_test.go index 4fd6a9331dbda..57eda590ac09b 100644 --- a/comp/netflow/config/config_test.go +++ b/comp/netflow/config/config_test.go @@ -6,7 +6,6 @@ package config import ( - "strings" "testing" "github.com/stretchr/testify/assert" @@ -14,6 +13,7 @@ import ( logmock "github.com/DataDog/datadog-agent/comp/core/log/mock" "github.com/DataDog/datadog-agent/comp/netflow/common" + configmock "github.com/DataDog/datadog-agent/pkg/config/mock" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" ) @@ -216,9 +216,7 @@ network_devices: } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(tt.configYaml)) - require.NoError(t, err) + configmock.NewFromYAML(t, tt.configYaml) readConfig, err := ReadConfig(pkgconfigsetup.Datadog(), logger) if tt.expectedError != "" { diff --git a/comp/netflow/flowaggregator/flowaccumulator.go b/comp/netflow/flowaggregator/flowaccumulator.go index 39329b91913b3..c2fca641401e4 100644 --- a/comp/netflow/flowaggregator/flowaccumulator.go +++ b/comp/netflow/flowaggregator/flowaccumulator.go @@ -194,7 +194,7 @@ func (f *flowAccumulator) setDstReverseDNSHostname(aggHash uint64, hostname stri } func (f *flowAccumulator) addRDNSEnrichment(aggHash uint64, srcAddr []byte, dstAddr []byte) { - err := f.rdnsQuerier.GetHostname( + err := f.rdnsQuerier.GetHostnameAsync( srcAddr, // Sync callback, lock is already held func(hostname string) { @@ -213,7 +213,7 @@ func (f *flowAccumulator) addRDNSEnrichment(aggHash uint64, srcAddr []byte, dstA f.logger.Debugf("Error requesting reverse DNS enrichment for source IP address: %v error: %v", srcAddr, err) } - err = f.rdnsQuerier.GetHostname( + err = f.rdnsQuerier.GetHostnameAsync( dstAddr, // Sync callback, lock is held func(hostname string) { diff --git a/comp/netflow/server/component.go b/comp/netflow/server/component.go index 47e17ece750fd..7544c3bd52ded 100644 --- a/comp/netflow/server/component.go +++ b/comp/netflow/server/component.go @@ -15,7 +15,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) -// team: network-device-monitoring +// team: ndm-integrations // Component is the component type. It has no exposed methods. type Component interface{} diff --git a/comp/networkpath/bundle_test.go b/comp/networkpath/bundle_test.go index 18a9b664c9b83..6eb6868e8acba 100644 --- a/comp/networkpath/bundle_test.go +++ b/comp/networkpath/bundle_test.go @@ -10,6 +10,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" + rdnsquerier "github.com/DataDog/datadog-agent/comp/rdnsquerier/fx-mock" "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) @@ -17,5 +18,6 @@ func TestBundleDependencies(t *testing.T) { fxutil.TestBundle(t, Bundle(), core.MockBundle(), eventplatformimpl.MockModule(), + rdnsquerier.MockModule(), ) } diff --git a/comp/networkpath/npcollector/npcollectorimpl/config.go b/comp/networkpath/npcollector/npcollectorimpl/config.go index 3a91df33ad08d..b408ceb488ef2 100644 --- a/comp/networkpath/npcollector/npcollectorimpl/config.go +++ b/comp/networkpath/npcollector/npcollectorimpl/config.go @@ -22,6 +22,8 @@ type collectorConfigs struct { pathtestTTL time.Duration pathtestInterval time.Duration flushInterval time.Duration + reverseDNSEnabled bool + reverseDNSTimeout time.Duration networkDevicesNamespace string } @@ -38,6 +40,8 @@ func newConfig(agentConfig config.Component) *collectorConfigs { pathtestTTL: agentConfig.GetDuration("network_path.collector.pathtest_ttl"), pathtestInterval: agentConfig.GetDuration("network_path.collector.pathtest_interval"), flushInterval: agentConfig.GetDuration("network_path.collector.flush_interval"), + reverseDNSEnabled: agentConfig.GetBool("network_path.collector.reverse_dns_enrichment.enabled"), + reverseDNSTimeout: agentConfig.GetDuration("network_path.collector.reverse_dns_enrichment.timeout") * time.Millisecond, networkDevicesNamespace: agentConfig.GetString("network_devices.namespace"), } } diff --git a/comp/networkpath/npcollector/npcollectorimpl/npcollector.go b/comp/networkpath/npcollector/npcollectorimpl/npcollector.go index b1f1e089ef8be..4e0382ca99b3f 100644 --- a/comp/networkpath/npcollector/npcollectorimpl/npcollector.go +++ b/comp/networkpath/npcollector/npcollectorimpl/npcollector.go @@ -22,6 +22,7 @@ import ( "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/comp/networkpath/npcollector/npcollectorimpl/common" "github.com/DataDog/datadog-agent/comp/networkpath/npcollector/npcollectorimpl/pathteststore" + rdnsquerier "github.com/DataDog/datadog-agent/comp/rdnsquerier/def" "github.com/DataDog/datadog-agent/pkg/logs/message" "github.com/DataDog/datadog-agent/pkg/networkpath/metricsender" "github.com/DataDog/datadog-agent/pkg/networkpath/payload" @@ -30,6 +31,13 @@ import ( "github.com/DataDog/datadog-agent/pkg/process/statsd" ) +const ( + networkPathCollectorMetricPrefix = "datadog.network_path.collector." + reverseDNSLookupMetricPrefix = networkPathCollectorMetricPrefix + "reverse_dns_lookup." + reverseDNSLookupFailuresMetricName = reverseDNSLookupMetricPrefix + "failures" + reverseDNSLookupSuccessesMetricName = reverseDNSLookupMetricPrefix + "successes" +) + type npCollectorImpl struct { collectorConfigs *collectorConfigs @@ -38,6 +46,7 @@ type npCollectorImpl struct { logger log.Component metricSender metricsender.MetricSender statsdClient ddgostatsd.ClientInterface + rdnsquerier rdnsquerier.Component // Counters receivedPathtestCount *atomic.Uint64 @@ -74,8 +83,8 @@ func newNoopNpCollectorImpl() *npCollectorImpl { } } -func newNpCollectorImpl(epForwarder eventplatform.Forwarder, collectorConfigs *collectorConfigs, logger log.Component, telemetrycomp telemetryComp.Component) *npCollectorImpl { - logger.Infof("New NpCollector (workers=%d timeout=%d max_ttl=%d input_chan_size=%d processing_chan_size=%d pathtest_contexts_limit=%d pathtest_ttl=%s pathtest_interval=%s flush_interval=%s)", +func newNpCollectorImpl(epForwarder eventplatform.Forwarder, collectorConfigs *collectorConfigs, logger log.Component, telemetrycomp telemetryComp.Component, rdnsquerier rdnsquerier.Component) *npCollectorImpl { + logger.Infof("New NpCollector (workers=%d timeout=%d max_ttl=%d input_chan_size=%d processing_chan_size=%d pathtest_contexts_limit=%d pathtest_ttl=%s pathtest_interval=%s flush_interval=%s reverse_dns_enabled=%t reverse_dns_timeout=%d)", collectorConfigs.workers, collectorConfigs.timeout, collectorConfigs.maxTTL, @@ -84,11 +93,15 @@ func newNpCollectorImpl(epForwarder eventplatform.Forwarder, collectorConfigs *c collectorConfigs.pathtestContextsLimit, collectorConfigs.pathtestTTL, collectorConfigs.pathtestInterval, - collectorConfigs.flushInterval) + collectorConfigs.flushInterval, + collectorConfigs.reverseDNSEnabled, + collectorConfigs.reverseDNSTimeout, + ) return &npCollectorImpl{ epForwarder: epForwarder, collectorConfigs: collectorConfigs, + rdnsquerier: rdnsquerier, logger: logger, pathtestStore: pathteststore.NewPathtestStore(collectorConfigs.pathtestTTL, collectorConfigs.pathtestInterval, collectorConfigs.pathtestContextsLimit, logger), @@ -231,6 +244,9 @@ func (s *npCollectorImpl) runTracerouteForPath(ptest *pathteststore.PathtestCont path.Namespace = s.networkDevicesNamespace path.Origin = payload.PathOriginNetworkTraffic + // Perform reverse DNS lookup on destination and hop IPs + s.enrichPathWithRDNS(&path) + s.sendTelemetry(path, startTime, ptest) payloadBytes, err := json.Marshal(path) @@ -284,22 +300,22 @@ func (s *npCollectorImpl) flushWrapper(flushTime time.Time, lastFlushTime time.T s.logger.Debugf("Flush loop at %s", flushTime) if !lastFlushTime.IsZero() { flushInterval := flushTime.Sub(lastFlushTime) - s.statsdClient.Gauge("datadog.network_path.collector.flush_interval", flushInterval.Seconds(), []string{}, 1) //nolint:errcheck + s.statsdClient.Gauge(networkPathCollectorMetricPrefix+"flush_interval", flushInterval.Seconds(), []string{}, 1) //nolint:errcheck } s.flush() - s.statsdClient.Gauge("datadog.network_path.collector.flush_duration", s.TimeNowFn().Sub(flushTime).Seconds(), []string{}, 1) //nolint:errcheck + s.statsdClient.Gauge(networkPathCollectorMetricPrefix+"flush_duration", s.TimeNowFn().Sub(flushTime).Seconds(), []string{}, 1) //nolint:errcheck } func (s *npCollectorImpl) flush() { - s.statsdClient.Gauge("datadog.network_path.collector.workers", float64(s.workers), []string{}, 1) //nolint:errcheck + s.statsdClient.Gauge(networkPathCollectorMetricPrefix+"workers", float64(s.workers), []string{}, 1) //nolint:errcheck flowsContexts := s.pathtestStore.GetContextsCount() - s.statsdClient.Gauge("datadog.network_path.collector.pathtest_store_size", float64(flowsContexts), []string{}, 1) //nolint:errcheck + s.statsdClient.Gauge(networkPathCollectorMetricPrefix+"pathtest_store_size", float64(flowsContexts), []string{}, 1) //nolint:errcheck flushTime := s.TimeNowFn() flowsToFlush := s.pathtestStore.Flush() - s.statsdClient.Gauge("datadog.network_path.collector.pathtest_flushed_count", float64(len(flowsToFlush)), []string{}, 1) //nolint:errcheck + s.statsdClient.Gauge(networkPathCollectorMetricPrefix+"pathtest_flushed_count", float64(len(flowsToFlush)), []string{}, 1) //nolint:errcheck s.logger.Debugf("Flushing %d flows to the forwarder (flush_duration=%d, flow_contexts_before_flush=%d)", len(flowsToFlush), time.Since(flushTime).Milliseconds(), flowsContexts) @@ -309,6 +325,76 @@ func (s *npCollectorImpl) flush() { } } +func (s *npCollectorImpl) enrichPathWithRDNS(path *payload.NetworkPath) { + if !s.collectorConfigs.reverseDNSEnabled { + return + } + + // collect unique IP addresses from destination and hops + ipSet := make(map[string]struct{}, len(path.Hops)+1) // +1 for destination + ipSet[path.Destination.IPAddress] = struct{}{} + for _, hop := range path.Hops { + if !hop.Reachable { + continue + } + ipSet[hop.IPAddress] = struct{}{} + } + ipAddrs := make([]string, 0, len(ipSet)) + for ip := range ipSet { + ipAddrs = append(ipAddrs, ip) + } + + ctx, cancel := context.WithTimeout(context.Background(), s.collectorConfigs.reverseDNSTimeout) + defer cancel() + + // perform reverse DNS lookup on destination and hops + results := s.rdnsquerier.GetHostnames(ctx, ipAddrs) + if len(results) != len(ipAddrs) { + s.statsdClient.Incr(reverseDNSLookupMetricPrefix+"results_length_mismatch", []string{}, 1) //nolint:errcheck + s.logger.Debugf("Reverse lookup failed for all hops in path from %s to %s", path.Source.Hostname, path.Destination.Hostname) + } + + // assign resolved hostnames to destination and hops + hostname := s.getReverseDNSResult(path.Destination.IPAddress, results) + // if hostname is blank, use what's given by traceroute + // TODO: would it be better to move the logic up from the traceroute command? + // benefit to the current approach is having consistent behavior for all paths + // both static and dynamic + if hostname != "" { + path.Destination.ReverseDNSHostname = hostname + } + + for i, hop := range path.Hops { + if !hop.Reachable { + continue + } + hostname := s.getReverseDNSResult(hop.IPAddress, results) + if hostname != "" { + path.Hops[i].Hostname = hostname + } + } +} + +func (s *npCollectorImpl) getReverseDNSResult(ipAddr string, results map[string]rdnsquerier.ReverseDNSResult) string { + result, ok := results[ipAddr] + if !ok { + s.statsdClient.Incr(reverseDNSLookupFailuresMetricName, []string{"reason:absent"}, 1) //nolint:errcheck + s.logger.Tracef("Reverse DNS lookup failed for IP %s", ipAddr) + return "" + } + if result.Err != nil { + s.statsdClient.Incr(reverseDNSLookupFailuresMetricName, []string{"reason:error"}, 1) //nolint:errcheck + s.logger.Tracef("Reverse lookup failed for hop IP %s: %s", ipAddr, result.Err) + return "" + } + if result.Hostname == "" { + s.statsdClient.Incr(reverseDNSLookupSuccessesMetricName, []string{"status:empty"}, 1) //nolint:errcheck + } else { + s.statsdClient.Incr(reverseDNSLookupSuccessesMetricName, []string{"status:found"}, 1) //nolint:errcheck + } + return result.Hostname +} + func (s *npCollectorImpl) sendTelemetry(path payload.NetworkPath, startTime time.Time, ptest *pathteststore.PathtestContext) { checkInterval := ptest.LastFlushInterval() checkDuration := s.TimeNowFn().Sub(startTime) diff --git a/comp/networkpath/npcollector/npcollectorimpl/npcollector_test.go b/comp/networkpath/npcollector/npcollectorimpl/npcollector_test.go index 54fef6f329523..c44b54e1b1db9 100644 --- a/comp/networkpath/npcollector/npcollectorimpl/npcollector_test.go +++ b/comp/networkpath/npcollector/npcollectorimpl/npcollector_test.go @@ -11,6 +11,7 @@ import ( "bufio" "bytes" "encoding/json" + "errors" "fmt" "os" "strings" @@ -27,6 +28,7 @@ import ( "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" "github.com/DataDog/datadog-agent/comp/networkpath/npcollector/npcollectorimpl/common" "github.com/DataDog/datadog-agent/comp/networkpath/npcollector/npcollectorimpl/pathteststore" + rdnsquerier "github.com/DataDog/datadog-agent/comp/rdnsquerier/def" "github.com/DataDog/datadog-agent/pkg/logs/message" "github.com/DataDog/datadog-agent/pkg/networkpath/metricsender" "github.com/DataDog/datadog-agent/pkg/networkpath/payload" @@ -145,7 +147,8 @@ func Test_NpCollector_runningAndProcessing(t *testing.T) { "destination": { "hostname": "abc", "ip_address": "10.0.0.2", - "port": 80 + "port": 80, + "reverse_dns_hostname": "hostname-10.0.0.2" }, "hops": [ { @@ -179,7 +182,8 @@ func Test_NpCollector_runningAndProcessing(t *testing.T) { "destination": { "hostname": "abc", "ip_address": "10.0.0.4", - "port": 80 + "port": 80, + "reverse_dns_hostname": "hostname-10.0.0.4" }, "hops": [ { @@ -763,3 +767,154 @@ func Benchmark_npCollectorImpl_ScheduleConns(b *testing.B) { app.RequireStop() assert.False(b, npCollector.running) } + +func Test_npCollectorImpl_enrichPathWithRDNS(t *testing.T) { + // GIVEN + agentConfigs := map[string]any{ + "network_path.connections_monitoring.enabled": true, + } + _, npCollector := newTestNpCollector(t, agentConfigs) + + stats := &teststatsd.Client{} + npCollector.statsdClient = stats + npCollector.metricSender = metricsender.NewMetricSenderStatsd(stats) + + // WHEN + // Destination, hop 1, hop 3, hop 4 are private IPs, hop 2 is a public IP + path := payload.NetworkPath{ + Destination: payload.NetworkPathDestination{IPAddress: "10.0.0.41", Hostname: "dest-hostname"}, + Hops: []payload.NetworkPathHop{ + {IPAddress: "10.0.0.1", Reachable: true, Hostname: "hop1"}, + {IPAddress: "1.1.1.1", Reachable: true, Hostname: "hop2"}, + {IPAddress: "10.0.0.100", Reachable: true, Hostname: "hop3"}, + {IPAddress: "10.0.0.41", Reachable: true, Hostname: "dest-hostname"}, + }, + } + + npCollector.enrichPathWithRDNS(&path) + + // THEN + assert.Equal(t, "hostname-10.0.0.41", path.Destination.ReverseDNSHostname) // private IP should be resolved + assert.Equal(t, "hostname-10.0.0.1", path.Hops[0].Hostname) + assert.Equal(t, "hop2", path.Hops[1].Hostname) // public IP should fall back to hostname from traceroute + assert.Equal(t, "hostname-10.0.0.100", path.Hops[2].Hostname) + assert.Equal(t, "hostname-10.0.0.41", path.Hops[3].Hostname) + + // WHEN + // hop 3 is a private IP, others are public IPs or unknown hops which should not be resolved + path = payload.NetworkPath{ + Destination: payload.NetworkPathDestination{IPAddress: "8.8.8.8", Hostname: "google.com"}, + Hops: []payload.NetworkPathHop{ + {IPAddress: "unknown-hop-1", Reachable: false, Hostname: "hop1"}, + {IPAddress: "1.1.1.1", Reachable: true, Hostname: "hop2"}, + {IPAddress: "10.0.0.100", Reachable: true, Hostname: "hop3"}, + {IPAddress: "unknown-hop-4", Reachable: false, Hostname: "hop4"}, + }, + } + + npCollector.enrichPathWithRDNS(&path) + + // THEN + assert.Equal(t, "", path.Destination.ReverseDNSHostname) + assert.Equal(t, "hop1", path.Hops[0].Hostname) + assert.Equal(t, "hop2", path.Hops[1].Hostname) // public IP should fall back to hostname from traceroute + assert.Equal(t, "hostname-10.0.0.100", path.Hops[2].Hostname) + assert.Equal(t, "hop4", path.Hops[3].Hostname) + + // GIVEN - no reverse DNS resolution + agentConfigs = map[string]any{ + "network_path.connections_monitoring.enabled": true, + "network_path.collector.reverse_dns_enrichment.enabled": false, + } + _, npCollector = newTestNpCollector(t, agentConfigs) + + npCollector.statsdClient = stats + npCollector.metricSender = metricsender.NewMetricSenderStatsd(stats) + + // WHEN + // Destination, hop 1, hop 3, hop 4 are private IPs, hop 2 is a public IP + path = payload.NetworkPath{ + Destination: payload.NetworkPathDestination{IPAddress: "10.0.0.41", Hostname: "dest-hostname"}, + Hops: []payload.NetworkPathHop{ + {IPAddress: "10.0.0.1", Reachable: true, Hostname: "hop1"}, + {IPAddress: "1.1.1.1", Reachable: true, Hostname: "hop2"}, + {IPAddress: "10.0.0.100", Reachable: true, Hostname: "hop3"}, + {IPAddress: "10.0.0.41", Reachable: true, Hostname: "dest-hostname"}, + }, + } + + npCollector.enrichPathWithRDNS(&path) + + // THEN - no resolution should happen + assert.Equal(t, "", path.Destination.ReverseDNSHostname) + assert.Equal(t, "hop1", path.Hops[0].Hostname) + assert.Equal(t, "hop2", path.Hops[1].Hostname) + assert.Equal(t, "hop3", path.Hops[2].Hostname) + assert.Equal(t, "dest-hostname", path.Hops[3].Hostname) +} + +func Test_npCollectorImpl_getReverseDNSResult(t *testing.T) { + // GIVEN + agentConfigs := map[string]any{ + "network_path.connections_monitoring.enabled": true, + } + _, npCollector := newTestNpCollector(t, agentConfigs) + + stats := &teststatsd.Client{} + npCollector.statsdClient = stats + npCollector.metricSender = metricsender.NewMetricSenderStatsd(stats) + + tts := []struct { + description string + ipAddr string + results map[string]rdnsquerier.ReverseDNSResult + expected string + }{ + { + description: "result not in map", + ipAddr: "10.0.0.1", + results: map[string]rdnsquerier.ReverseDNSResult{}, + expected: "", + }, + { + description: "map is nil", + ipAddr: "10.0.0.1", + results: nil, + expected: "", + }, + { + description: "result is an error", + ipAddr: "10.0.0.1", + results: map[string]rdnsquerier.ReverseDNSResult{ + "10.0.0.1": {IP: "10.0.0.1", Hostname: "should-not-be-used", Err: errors.New("error")}, + }, + expected: "", + }, + { + description: "result is blank", + ipAddr: "10.0.0.1", + results: map[string]rdnsquerier.ReverseDNSResult{ + "10.0.0.1": {IP: "10.0.0.1", Hostname: ""}, + }, + expected: "", + }, + { + description: "result is valid", + ipAddr: "10.0.0.1", + results: map[string]rdnsquerier.ReverseDNSResult{ + "10.0.0.1": {IP: "10.0.0.1", Hostname: "valid-hostname"}, + }, + expected: "valid-hostname", + }, + } + + for _, tt := range tts { + t.Run(tt.description, func(t *testing.T) { + // WHEN + result := npCollector.getReverseDNSResult(tt.ipAddr, tt.results) + + // THEN + assert.Equal(t, tt.expected, result) + }) + } +} diff --git a/comp/networkpath/npcollector/npcollectorimpl/npcollector_testutils.go b/comp/networkpath/npcollector/npcollectorimpl/npcollector_testutils.go index 43a30b974a328..16d777c11fd79 100644 --- a/comp/networkpath/npcollector/npcollectorimpl/npcollector_testutils.go +++ b/comp/networkpath/npcollector/npcollectorimpl/npcollector_testutils.go @@ -22,6 +22,7 @@ import ( "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" "github.com/DataDog/datadog-agent/comp/ndmtmp/forwarder/forwarderimpl" "github.com/DataDog/datadog-agent/comp/networkpath/npcollector" + rdnsqueriermock "github.com/DataDog/datadog-agent/comp/rdnsquerier/fx-mock" "github.com/stretchr/testify/require" "go.uber.org/fx" "go.uber.org/fx/fxtest" @@ -43,6 +44,7 @@ var testOptions = fx.Options( defaultforwarder.MockModule(), core.MockBundle(), eventplatformimpl.MockModule(), + rdnsqueriermock.MockModule(), ) func newTestNpCollector(t fxtest.TB, agentConfigs map[string]any) (*fxtest.App, *npCollectorImpl) { diff --git a/comp/networkpath/npcollector/npcollectorimpl/npcollectorcomp.go b/comp/networkpath/npcollector/npcollectorimpl/npcollectorcomp.go index 9102604bf3e43..01c0a42691ed9 100644 --- a/comp/networkpath/npcollector/npcollectorimpl/npcollectorcomp.go +++ b/comp/networkpath/npcollector/npcollectorimpl/npcollectorcomp.go @@ -15,6 +15,8 @@ import ( "github.com/DataDog/datadog-agent/comp/core/telemetry" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/comp/networkpath/npcollector" + rdnsquerier "github.com/DataDog/datadog-agent/comp/rdnsquerier/def" + nooprdnsquerier "github.com/DataDog/datadog-agent/comp/rdnsquerier/impl-none" "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) @@ -25,6 +27,7 @@ type dependencies struct { Logger log.Component AgentConfig config.Component Telemetry telemetry.Component + RDNSQuerier rdnsquerier.Component } type provides struct { @@ -46,12 +49,24 @@ func newNpCollector(deps dependencies) provides { configs := newConfig(deps.AgentConfig) if configs.networkPathCollectorEnabled() { deps.Logger.Debugf("Network Path Collector enabled") + + // Note that multiple components can share the same rdnsQuerier instance. If any of them have + // reverse DNS enrichment enabled then the deps.RDNSQuerier component passed here will be an + // active instance. However, we also need to check here whether the network path component has + // reverse DNS enrichment enabled to decide whether to use the passed instance or to override + // it with a noop implementation. + rdnsQuerier := deps.RDNSQuerier + if !configs.reverseDNSEnabled { + deps.Logger.Infof("Reverse DNS enrichment is disabled for Network Path Collector") + rdnsQuerier = nooprdnsquerier.NewNone().Comp + } + epForwarder, ok := deps.EpForwarder.Get() if !ok { deps.Logger.Errorf("Error getting EpForwarder") collector = newNoopNpCollectorImpl() } else { - collector = newNpCollectorImpl(epForwarder, configs, deps.Logger, deps.Telemetry) + collector = newNpCollectorImpl(epForwarder, configs, deps.Logger, deps.Telemetry, rdnsQuerier) deps.Lc.Append(fx.Hook{ // No need for OnStart hook since NpCollector.Init() will be called by clients when needed. OnStart: func(context.Context) error { diff --git a/comp/otelcol/ddflareextension/impl/go.mod b/comp/otelcol/ddflareextension/impl/go.mod index 5e9e19c869297..73a4c13ecac27 100644 --- a/comp/otelcol/ddflareextension/impl/go.mod +++ b/comp/otelcol/ddflareextension/impl/go.mod @@ -108,9 +108,9 @@ require ( github.com/DataDog/datadog-agent/comp/otelcol/ddflareextension/def v0.0.0-00010101000000-000000000000 github.com/DataDog/datadog-agent/comp/otelcol/otlp/components/exporter/datadogexporter v0.0.0-00010101000000-000000000000 github.com/DataDog/datadog-agent/comp/otelcol/otlp/components/processor/infraattributesprocessor v0.0.0-00010101000000-000000000000 - github.com/DataDog/datadog-agent/pkg/api v0.56.2 + github.com/DataDog/datadog-agent/pkg/api v0.57.1 github.com/DataDog/datadog-agent/pkg/config/mock v0.58.0-devel - github.com/DataDog/datadog-agent/pkg/version v0.57.0 + github.com/DataDog/datadog-agent/pkg/version v0.57.1 github.com/gorilla/mux v1.8.1 github.com/open-telemetry/opentelemetry-collector-contrib/connector/datadogconnector v0.104.0 github.com/open-telemetry/opentelemetry-collector-contrib/connector/spanmetricsconnector v0.104.0 @@ -158,9 +158,9 @@ require ( github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/Code-Hex/go-generics-cache v1.3.1 // indirect github.com/DataDog/agent-payload/v5 v5.0.123 // indirect - github.com/DataDog/datadog-agent/comp/core/config v0.56.2 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/builder v0.56.2 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/types v0.56.2 // indirect + github.com/DataDog/datadog-agent/comp/core/config v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/builder v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/types v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/hostname/hostnameinterface v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/comp/core/log/def v0.58.0-devel // indirect github.com/DataDog/datadog-agent/comp/core/log/mock v0.58.0-devel // indirect @@ -191,7 +191,7 @@ require ( github.com/DataDog/datadog-agent/pkg/config/setup v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/structure v0.0.0-00010101000000-000000000000 // indirect github.com/DataDog/datadog-agent/pkg/config/teeconfig v0.60.0-devel // indirect - github.com/DataDog/datadog-agent/pkg/config/utils v0.56.2 // indirect + github.com/DataDog/datadog-agent/pkg/config/utils v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/logs/auditor v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/logs/client v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/logs/diagnostic v0.56.0-rc.3 // indirect diff --git a/comp/otelcol/otlp/collector.go b/comp/otelcol/otlp/collector.go index 3fc7b89a11c65..ce7e98d44c7c0 100644 --- a/comp/otelcol/otlp/collector.go +++ b/comp/otelcol/otlp/collector.go @@ -53,6 +53,7 @@ var pipelineError = atomic.NewError(nil) type tagEnricher struct { cardinality types.TagCardinality + tagger tagger.Component } func (t *tagEnricher) SetCardinality(cardinality string) (err error) { @@ -73,7 +74,7 @@ func (t *tagEnricher) Enrich(_ context.Context, extraTags []string, dimensions * prefix, id, err := common.ExtractPrefixAndID(dimensions.OriginID()) if err != nil { entityID := types.NewEntityID(prefix, id) - entityTags, err := tagger.Tag(entityID, t.cardinality) + entityTags, err := t.tagger.Tag(entityID, t.cardinality) if err != nil { log.Tracef("Cannot get tags for entity %s: %s", dimensions.OriginID(), err) } else { @@ -83,7 +84,7 @@ func (t *tagEnricher) Enrich(_ context.Context, extraTags []string, dimensions * log.Tracef("Cannot get tags for entity %s: %s", dimensions.OriginID(), err) } - globalTags, err := tagger.GlobalTags(t.cardinality) + globalTags, err := t.tagger.GlobalTags(t.cardinality) if err != nil { log.Trace(err.Error()) } else { @@ -118,7 +119,7 @@ func getComponents(s serializer.MetricSerializer, logsAgentChannel chan *message exporterFactories := []exporter.Factory{ otlpexporter.NewFactory(), - serializerexporter.NewFactory(s, &tagEnricher{cardinality: types.LowCardinality}, hostname.Get, nil, nil), + serializerexporter.NewFactory(s, &tagEnricher{cardinality: types.LowCardinality, tagger: tagger}, hostname.Get, nil, nil), debugexporter.NewFactory(), } diff --git a/comp/otelcol/otlp/collector_test.go b/comp/otelcol/otlp/collector_test.go index 4368afb1bb218..1e44b6e1f79c6 100644 --- a/comp/otelcol/otlp/collector_test.go +++ b/comp/otelcol/otlp/collector_test.go @@ -25,7 +25,7 @@ import ( func TestGetComponents(t *testing.T) { fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + _, err := getComponents(serializermock.NewMetricSerializer(t), make(chan *message.Message), fakeTagger) // No duplicate component require.NoError(t, err) @@ -33,7 +33,7 @@ func TestGetComponents(t *testing.T) { func AssertSucessfulRun(t *testing.T, pcfg PipelineConfig) { fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + p, err := NewPipeline(pcfg, serializermock.NewMetricSerializer(t), make(chan *message.Message), fakeTagger) require.NoError(t, err) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) @@ -60,7 +60,7 @@ func AssertSucessfulRun(t *testing.T, pcfg PipelineConfig) { func AssertFailedRun(t *testing.T, pcfg PipelineConfig, expected string) { fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + p, err := NewPipeline(pcfg, serializermock.NewMetricSerializer(t), make(chan *message.Message), fakeTagger) require.NoError(t, err) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) diff --git a/comp/otelcol/otlp/components/exporter/datadogexporter/go.mod b/comp/otelcol/otlp/components/exporter/datadogexporter/go.mod index 344dedb5abddc..f87aeb3dab582 100644 --- a/comp/otelcol/otlp/components/exporter/datadogexporter/go.mod +++ b/comp/otelcol/otlp/components/exporter/datadogexporter/go.mod @@ -28,6 +28,7 @@ replace ( github.com/DataDog/datadog-agent/comp/trace/compression/impl-gzip => ../../../../../../comp/trace/compression/impl-gzip github.com/DataDog/datadog-agent/comp/trace/compression/impl-zstd => ../../../../../../comp/trace/compression/impl-zstd github.com/DataDog/datadog-agent/pkg/aggregator/ckey => ../../../../../../pkg/aggregator/ckey + github.com/DataDog/datadog-agent/pkg/api => ../../../../../../pkg/api github.com/DataDog/datadog-agent/pkg/collector/check/defaults => ../../../../../../pkg/collector/check/defaults github.com/DataDog/datadog-agent/pkg/config/env => ../../../../../../pkg/config/env github.com/DataDog/datadog-agent/pkg/config/mock => ../../../../../../pkg/config/mock @@ -125,9 +126,9 @@ require ( require ( github.com/DataDog/agent-payload/v5 v5.0.119 // indirect - github.com/DataDog/datadog-agent/comp/core/config v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/builder v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/types v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/comp/core/config v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/builder v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/types v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/hostname/hostnameinterface v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/comp/core/log/def v0.0.0-00010101000000-000000000000 // indirect github.com/DataDog/datadog-agent/comp/core/secrets v0.57.1 // indirect @@ -140,6 +141,7 @@ require ( github.com/DataDog/datadog-agent/comp/serializer/compression v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/comp/trace/compression/def v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/aggregator/ckey v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/api v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/collector/check/defaults v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/env v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/mock v0.58.0-devel // indirect @@ -148,7 +150,7 @@ require ( github.com/DataDog/datadog-agent/pkg/config/setup v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/structure v0.0.0-00010101000000-000000000000 // indirect github.com/DataDog/datadog-agent/pkg/config/teeconfig v0.60.0-devel // indirect - github.com/DataDog/datadog-agent/pkg/config/utils v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/config/utils v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/logs/auditor v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/logs/client v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/logs/diagnostic v0.56.0-rc.3 // indirect @@ -188,7 +190,7 @@ require ( github.com/DataDog/datadog-agent/pkg/util/system v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/system/socket v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/winutil v0.57.1 // indirect - github.com/DataDog/datadog-agent/pkg/version v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/version v0.57.1 // indirect github.com/DataDog/datadog-api-client-go/v2 v2.26.0 // indirect github.com/DataDog/dd-sensitive-data-scanner/sds-go/go v0.0.0-20240816154533-f7f9beb53a42 // indirect github.com/DataDog/go-sqllexer v0.0.16 // indirect diff --git a/comp/otelcol/otlp/components/exporter/serializerexporter/go.mod b/comp/otelcol/otlp/components/exporter/serializerexporter/go.mod index 8de00dc5f4ef9..848a5aa8915cd 100644 --- a/comp/otelcol/otlp/components/exporter/serializerexporter/go.mod +++ b/comp/otelcol/otlp/components/exporter/serializerexporter/go.mod @@ -17,6 +17,7 @@ replace ( github.com/DataDog/datadog-agent/comp/forwarder/orchestrator/orchestratorinterface => ../../../../../forwarder/orchestrator/orchestratorinterface github.com/DataDog/datadog-agent/comp/serializer/compression => ../../../../../serializer/compression/ github.com/DataDog/datadog-agent/pkg/aggregator/ckey => ../../../../../../pkg/aggregator/ckey + github.com/DataDog/datadog-agent/pkg/api => ../../../../../../pkg/api github.com/DataDog/datadog-agent/pkg/collector/check/defaults => ../../../../../../pkg/collector/check/defaults github.com/DataDog/datadog-agent/pkg/config/env => ../../../../../../pkg/config/env github.com/DataDog/datadog-agent/pkg/config/mock => ../../../../../../pkg/config/mock @@ -91,9 +92,9 @@ require ( require ( github.com/DataDog/agent-payload/v5 v5.0.114 // indirect - github.com/DataDog/datadog-agent/comp/core/config v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/builder v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/types v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/comp/core/config v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/builder v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/types v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/log/def v0.0.0-00010101000000-000000000000 // indirect github.com/DataDog/datadog-agent/comp/core/secrets v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/status v0.56.0-rc.3 // indirect @@ -103,6 +104,7 @@ require ( github.com/DataDog/datadog-agent/comp/forwarder/orchestrator/orchestratorinterface v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/comp/serializer/compression v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/aggregator/ckey v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/api v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/collector/check/defaults v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/env v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/mock v0.58.0-devel // indirect @@ -111,7 +113,7 @@ require ( github.com/DataDog/datadog-agent/pkg/config/setup v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/structure v0.0.0-00010101000000-000000000000 // indirect github.com/DataDog/datadog-agent/pkg/config/teeconfig v0.60.0-devel // indirect - github.com/DataDog/datadog-agent/pkg/config/utils v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/config/utils v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/orchestrator/model v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/process/util/api v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/status/health v0.56.0-rc.3 // indirect @@ -133,7 +135,7 @@ require ( github.com/DataDog/datadog-agent/pkg/util/system v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/system/socket v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/winutil v0.57.1 // indirect - github.com/DataDog/datadog-agent/pkg/version v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/version v0.57.1 // indirect github.com/DataDog/mmh3 v0.0.0-20210722141835-012dc69a9e49 // indirect github.com/DataDog/sketches-go v1.4.4 // indirect github.com/DataDog/viper v1.13.5 // indirect diff --git a/comp/otelcol/otlp/integrationtest/integration_test.go b/comp/otelcol/otlp/integrationtest/integration_test.go index 659025608087a..47b9fe0eeaff9 100644 --- a/comp/otelcol/otlp/integrationtest/integration_test.go +++ b/comp/otelcol/otlp/integrationtest/integration_test.go @@ -32,6 +32,8 @@ import ( "go.uber.org/fx" "google.golang.org/protobuf/proto" + ddgostatsd "github.com/DataDog/datadog-go/v5/statsd" + agentConfig "github.com/DataDog/datadog-agent/cmd/otel-agent/config" "github.com/DataDog/datadog-agent/cmd/otel-agent/subcommands" "github.com/DataDog/datadog-agent/comp/api/authtoken/fetchonlyimpl" @@ -74,7 +76,6 @@ import ( "github.com/DataDog/datadog-agent/pkg/trace/telemetry" "github.com/DataDog/datadog-agent/pkg/util/fxutil" "github.com/DataDog/datadog-agent/pkg/util/optional" - ddgostatsd "github.com/DataDog/datadog-go/v5/statsd" ) func runTestOTelAgent(ctx context.Context, params *subcommands.GlobalParams) error { diff --git a/comp/otelcol/otlp/map_provider_not_serverless_test.go b/comp/otelcol/otlp/map_provider_not_serverless_test.go index 4ee1a08a38efe..cb71a49c1bfec 100644 --- a/comp/otelcol/otlp/map_provider_not_serverless_test.go +++ b/comp/otelcol/otlp/map_provider_not_serverless_test.go @@ -1128,7 +1128,7 @@ func TestUnmarshal(t *testing.T) { provider, err := otelcol.NewConfigProvider(mapSettings) require.NoError(t, err) fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + components, err := getComponents(serializermock.NewMetricSerializer(t), make(chan *message.Message), fakeTagger) require.NoError(t, err) diff --git a/comp/process/apiserver/apiserver_test.go b/comp/process/apiserver/apiserver_test.go index 8719f3d8db91d..68b2eb22dbbc4 100644 --- a/comp/process/apiserver/apiserver_test.go +++ b/comp/process/apiserver/apiserver_test.go @@ -17,6 +17,8 @@ import ( "github.com/DataDog/datadog-agent/comp/core/settings/settingsimpl" "github.com/DataDog/datadog-agent/comp/core/status" "github.com/DataDog/datadog-agent/comp/core/status/statusimpl" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafx "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx" "github.com/DataDog/datadog-agent/pkg/util/fxutil" @@ -32,6 +34,8 @@ func TestLifecycle(t *testing.T) { PythonVersionGetFunc: func() string { return "n/a" }, }, ), + fx.Supply(tagger.NewFakeTaggerParams()), + taggerimpl.Module(), statusimpl.Module(), settingsimpl.MockModule(), )) diff --git a/comp/process/bundle_test.go b/comp/process/bundle_test.go index 1c95f526f423a..03fb70a4fc91e 100644 --- a/comp/process/bundle_test.go +++ b/comp/process/bundle_test.go @@ -19,6 +19,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/status" coreStatusImpl "github.com/DataDog/datadog-agent/comp/core/status/statusimpl" "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafx "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx" "github.com/DataDog/datadog-agent/comp/dogstatsd/statsd" @@ -28,6 +29,7 @@ import ( "github.com/DataDog/datadog-agent/comp/process/runner" "github.com/DataDog/datadog-agent/comp/process/status/statusimpl" "github.com/DataDog/datadog-agent/comp/process/types" + rdnsquerier "github.com/DataDog/datadog-agent/comp/rdnsquerier/fx-mock" "github.com/DataDog/datadog-agent/pkg/collector/python" "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) @@ -47,12 +49,14 @@ func TestBundleDependencies(t *testing.T) { settingsimpl.MockModule(), statusimpl.Module(), fx.Supply(tagger.NewFakeTaggerParams()), + taggerimpl.Module(), fx.Supply( status.Params{ PythonVersionGetFunc: python.GetPythonVersion, }, ), fx.Provide(func() context.Context { return context.TODO() }), + rdnsquerier.MockModule(), npcollectorimpl.MockModule(), statsd.MockModule(), ) @@ -92,6 +96,7 @@ func TestBundleOneShot(t *testing.T) { workloadmetafx.Module(workloadmeta.NewParams()), eventplatformreceiverimpl.Module(), eventplatformimpl.Module(eventplatformimpl.NewDefaultParams()), + rdnsquerier.MockModule(), npcollectorimpl.Module(), statsd.MockModule(), Bundle(), diff --git a/comp/process/profiler/profilerimpl/profiler.go b/comp/process/profiler/profilerimpl/profiler.go index bdcaa28f2bf71..2174b12d911c7 100644 --- a/comp/process/profiler/profilerimpl/profiler.go +++ b/comp/process/profiler/profilerimpl/profiler.go @@ -76,10 +76,8 @@ func getProfilingSettings(cfg config.Component) profiling.Settings { site = fmt.Sprintf(profiling.ProfilingURLTemplate, s) } - v, _ := version.Agent() - tags := cfg.GetStringSlice("internal_profiling.extra_tags") - tags = append(tags, fmt.Sprintf("version:%v", v)) + tags = append(tags, fmt.Sprintf("version:%v", version.AgentVersion)) return profiling.Settings{ ProfilingURL: site, diff --git a/comp/rdnsquerier/def/component.go b/comp/rdnsquerier/def/component.go index 88a64bcfa718f..2a780fd763569 100644 --- a/comp/rdnsquerier/def/component.go +++ b/comp/rdnsquerier/def/component.go @@ -6,9 +6,22 @@ // Package rdnsquerier provides the reverse DNS querier component. package rdnsquerier -// team: network-device-monitoring +import ( + "context" +) + +// team: ndm-integrations + +// ReverseDNSResult is the result of a reverse DNS lookup +type ReverseDNSResult struct { + IP string + Hostname string + Err error +} // Component is the component type. type Component interface { - GetHostname([]byte, func(string), func(string, error)) error + GetHostnameAsync([]byte, func(string), func(string, error)) error + GetHostname(context.Context, string) (string, error) + GetHostnames(context.Context, []string) map[string]ReverseDNSResult } diff --git a/comp/rdnsquerier/impl-none/none.go b/comp/rdnsquerier/impl-none/none.go index 8f3d7cb3100b0..0b7f1022f1eb9 100644 --- a/comp/rdnsquerier/impl-none/none.go +++ b/comp/rdnsquerier/impl-none/none.go @@ -7,6 +7,8 @@ package rdnsquerierimpl import ( + "context" + rdnsquerier "github.com/DataDog/datadog-agent/comp/rdnsquerier/def" ) @@ -25,7 +27,19 @@ func NewNone() Provides { } // GetHostnameAsync does nothing for the noop rdnsquerier implementation -func (q *rdnsQuerierImplNone) GetHostname(_ []byte, _ func(string), _ func(string, error)) error { +func (q *rdnsQuerierImplNone) GetHostnameAsync(_ []byte, _ func(string), _ func(string, error)) error { + // noop + return nil +} + +// GetHostname does nothing for the noop rdnsquerier implementation +func (q *rdnsQuerierImplNone) GetHostname(_ context.Context, _ string) (string, error) { + // noop + return "", nil +} + +// GetHostnames does nothing for the noop rdnsquerier implementation +func (q *rdnsQuerierImplNone) GetHostnames(_ context.Context, _ []string) map[string]rdnsquerier.ReverseDNSResult { // noop return nil } diff --git a/comp/rdnsquerier/impl/config.go b/comp/rdnsquerier/impl/config.go index 0ca9417c2be98..3cf7d906ebad1 100644 --- a/comp/rdnsquerier/impl/config.go +++ b/comp/rdnsquerier/impl/config.go @@ -57,9 +57,10 @@ const ( func newConfig(agentConfig config.Component) *rdnsQuerierConfig { netflowRDNSEnrichmentEnabled := agentConfig.GetBool("network_devices.netflow.reverse_dns_enrichment_enabled") + networkPathRDNSEnrichmentEnabled := agentConfig.GetBool("network_path.collector.reverse_dns_enrichment.enabled") && agentConfig.GetBool("network_path.connections_monitoring.enabled") c := &rdnsQuerierConfig{ - enabled: netflowRDNSEnrichmentEnabled, + enabled: netflowRDNSEnrichmentEnabled || networkPathRDNSEnrichmentEnabled, workers: agentConfig.GetInt("reverse_dns_enrichment.workers"), chanSize: agentConfig.GetInt("reverse_dns_enrichment.chan_size"), diff --git a/comp/rdnsquerier/impl/config_test.go b/comp/rdnsquerier/impl/config_test.go index 71ec7b73c8084..6a80363508616 100644 --- a/comp/rdnsquerier/impl/config_test.go +++ b/comp/rdnsquerier/impl/config_test.go @@ -45,11 +45,72 @@ func TestConfig(t *testing.T) { }, }, { - name: "default config when enabled", + name: "disabled when Network Path Collector is enabled, reverse DNS enrichment is disabled", + configYaml: ` +network_path: + connections_monitoring: + enabled: true + collector: + reverse_dns_enrichment: + enabled: false +`, + expectedConfig: rdnsQuerierConfig{ + enabled: false, + workers: 0, + chanSize: 0, + cache: cacheConfig{ + enabled: true, + entryTTL: 0, + cleanInterval: 0, + persistInterval: 0, + maxRetries: -1, + maxSize: 0, + }, + rateLimiter: rateLimiterConfig{ + enabled: true, + limitPerSec: 0, + limitThrottledPerSec: 0, + throttleErrorThreshold: 0, + recoveryIntervals: 0, + recoveryInterval: 0, + }, + }, + }, + { + name: "default config when enabled through netflow", configYaml: ` network_devices: netflow: reverse_dns_enrichment_enabled: true +`, + expectedConfig: rdnsQuerierConfig{ + enabled: true, + workers: defaultWorkers, + chanSize: defaultChanSize, + cache: cacheConfig{ + enabled: true, + entryTTL: defaultCacheEntryTTL, + cleanInterval: defaultCacheCleanInterval, + persistInterval: defaultCachePersistInterval, + maxRetries: defaultCacheMaxRetries, + maxSize: defaultCacheMaxSize, + }, + rateLimiter: rateLimiterConfig{ + enabled: true, + limitPerSec: defaultRateLimitPerSec, + limitThrottledPerSec: defaultRateLimitThrottledPerSec, + throttleErrorThreshold: defaultRateLimitThrottleErrorThreshold, + recoveryIntervals: defaultRateLimitRecoveryIntervals, + recoveryInterval: defaultRateLimitRecoveryInterval, + }, + }, + }, + { + name: "default config when Network Path Collector is enabled", + configYaml: ` +network_path: + connections_monitoring: + enabled: true `, expectedConfig: rdnsQuerierConfig{ enabled: true, diff --git a/comp/rdnsquerier/impl/rdnsquerier.go b/comp/rdnsquerier/impl/rdnsquerier.go index c943d795cc23c..86b4d40e91ac8 100644 --- a/comp/rdnsquerier/impl/rdnsquerier.go +++ b/comp/rdnsquerier/impl/rdnsquerier.go @@ -10,6 +10,7 @@ import ( "context" "fmt" "net/netip" + "sync" "github.com/DataDog/datadog-agent/comp/core/config" log "github.com/DataDog/datadog-agent/comp/core/log/def" @@ -17,6 +18,7 @@ import ( compdef "github.com/DataDog/datadog-agent/comp/def" rdnsquerier "github.com/DataDog/datadog-agent/comp/rdnsquerier/def" rdnsquerierimplnone "github.com/DataDog/datadog-agent/comp/rdnsquerier/impl-none" + "go.uber.org/multierr" ) // Requires defines the dependencies for the rdnsquerier component @@ -157,7 +159,7 @@ func NewComponent(reqs Requires) (Provides, error) { // If the hostname for the IP address is immediately available (i.e. cache is enabled and entry is cached) then the updateHostnameSync callback // will be invoked synchronously, otherwise a query is sent to a channel to be processed asynchronously. If the channel is full then an error // is returned. When the request completes the updateHostnameAsync callback will be invoked asynchronously. -func (q *rdnsQuerierImpl) GetHostname(ipAddr []byte, updateHostnameSync func(string), updateHostnameAsync func(string, error)) error { +func (q *rdnsQuerierImpl) GetHostnameAsync(ipAddr []byte, updateHostnameSync func(string), updateHostnameAsync func(string, error)) error { q.internalTelemetry.total.Inc() netipAddr, ok := netip.AddrFromSlice(ipAddr) @@ -167,7 +169,7 @@ func (q *rdnsQuerierImpl) GetHostname(ipAddr []byte, updateHostnameSync func(str } if !netipAddr.IsPrivate() { - q.logger.Tracef("Reverse DNS Enrichment IP address %s is not in the private address space", netipAddr) + q.logger.Tracef("Reverse DNS Enrichment IP address %s is not in the private address space", ipAddr) return nil } q.internalTelemetry.private.Inc() @@ -175,10 +177,85 @@ func (q *rdnsQuerierImpl) GetHostname(ipAddr []byte, updateHostnameSync func(str err := q.cache.getHostname(netipAddr.String(), updateHostnameSync, updateHostnameAsync) if err != nil { q.logger.Debugf("Reverse DNS Enrichment cache.getHostname() for addr %s returned error: %v", netipAddr.String(), err) - return err } - return nil + return err +} + +// GetHostname attempts to resolve the hostname for the given IP address synchronously. +// If the IP address is invalid then an error is returned. +// If the IP address is not in the private address space then it is ignored - no lookup is performed and nil error is returned. +// If the IP address is in the private address space then the IP address will be resolved to a hostname. +// The function accepts a timeout via context and will return an error if the timeout is reached. +func (q *rdnsQuerierImpl) GetHostname(ctx context.Context, ipAddr string) (string, error) { + q.internalTelemetry.total.Inc() + + netipAddr, err := netip.ParseAddr(ipAddr) + if err != nil { + q.internalTelemetry.invalidIPAddress.Inc() + return "", fmt.Errorf("invalid IP address %s: %v", ipAddr, err) + } + + if !netipAddr.IsPrivate() { + q.logger.Tracef("Reverse DNS Enrichment IP address %s is not in the private address space", ipAddr) + return "", nil + } + q.internalTelemetry.private.Inc() + + resultsChan := make(chan rdnsquerier.ReverseDNSResult, 1) + + err = q.cache.getHostname( + netipAddr.String(), + func(h string) { + resultsChan <- rdnsquerier.ReverseDNSResult{Hostname: h} + }, + func(h string, e error) { + resultsChan <- rdnsquerier.ReverseDNSResult{Hostname: h, Err: e} + }, + ) + if err != nil { + q.logger.Debugf("Reverse DNS Enrichment cache.getHostname() for addr %s returned error: %v", netipAddr.String(), err) + return "", err + } + + select { + case result := <-resultsChan: + err = multierr.Append(err, result.Err) + return result.Hostname, err + case <-ctx.Done(): + return "", fmt.Errorf("timeout reached while resolving hostname for IP address %v", ipAddr) + } +} + +// GetHostnames attempts to resolve the hostname for the given IP addresses. +// If the IP address is invalid then an error is returned. +// If the IP address is not in the private address space then it is ignored - no lookup is performed and nil error is returned. +// If the IP address is in the private address space then the IP address will be resolved to a hostname. +// The function accepts a timeout via context and will return an error if the timeout is reached. +func (q *rdnsQuerierImpl) GetHostnames(ctx context.Context, ipAddrs []string) map[string]rdnsquerier.ReverseDNSResult { + var wg sync.WaitGroup + resultsChan := make(chan rdnsquerier.ReverseDNSResult, len(ipAddrs)) + + for _, ipAddr := range ipAddrs { + wg.Add(1) + go func(ctx context.Context, ipAddr string) { + defer wg.Done() + hostname, err := q.GetHostname(ctx, ipAddr) + resultsChan <- rdnsquerier.ReverseDNSResult{IP: ipAddr, Hostname: hostname, Err: err} + }(ctx, ipAddr) + } + + go func() { + wg.Wait() + close(resultsChan) + }() + + results := make(map[string]rdnsquerier.ReverseDNSResult, len(ipAddrs)) + for result := range resultsChan { + results[result.IP] = result + } + + return results } func (q *rdnsQuerierImpl) start(_ context.Context) error { diff --git a/comp/rdnsquerier/impl/rdnsquerier_test.go b/comp/rdnsquerier/impl/rdnsquerier_test.go index fb5102e511815..81d80b8ea2f7c 100644 --- a/comp/rdnsquerier/impl/rdnsquerier_test.go +++ b/comp/rdnsquerier/impl/rdnsquerier_test.go @@ -3,16 +3,23 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2024-present Datadog, Inc. +//go:build test + package rdnsquerierimpl import ( + "context" "fmt" "net" "sync" + "sync/atomic" "testing" "time" + rdnsquerierdef "github.com/DataDog/datadog-agent/comp/rdnsquerier/def" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // Test that the rdnsQuerier starts and stops as expected. @@ -20,7 +27,7 @@ func TestStartStop(t *testing.T) { overrides := map[string]interface{}{ "network_devices.netflow.reverse_dns_enrichment_enabled": true, } - ts := testSetup(t, overrides, false, nil) + ts := testSetup(t, overrides, false, nil, 0) internalRDNSQuerier := ts.rdnsQuerier.(*rdnsQuerierImpl) assert.NotNil(t, internalRDNSQuerier) @@ -38,10 +45,10 @@ func TestNotStarted(t *testing.T) { overrides := map[string]interface{}{ "network_devices.netflow.reverse_dns_enrichment_enabled": true, } - ts := testSetup(t, overrides, false, nil) + ts := testSetup(t, overrides, false, nil, 0) // IP address in private range - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(_ string) { assert.FailNow(t, "Sync callback should not be called when rdnsquerier is not started") @@ -66,12 +73,12 @@ func TestNormalOperationsDefaultConfig(t *testing.T) { overrides := map[string]interface{}{ "network_devices.netflow.reverse_dns_enrichment_enabled": true, } - ts := testSetup(t, overrides, true, nil) + ts := testSetup(t, overrides, true, nil, 0) var wg sync.WaitGroup // Invalid IP address - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{1, 2, 3}, func(_ string) { assert.FailNow(t, "Sync callback should not be called for invalid IP address") @@ -83,7 +90,7 @@ func TestNormalOperationsDefaultConfig(t *testing.T) { assert.ErrorContains(t, err, "invalid IP address") // IP address not in private range - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{8, 8, 8, 8}, func(_ string) { assert.FailNow(t, "Sync callback should not be called for IP address not in private range") @@ -96,7 +103,7 @@ func TestNormalOperationsDefaultConfig(t *testing.T) { // IP address in private range - async callback should be called the first time an IP address is queried wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -112,7 +119,7 @@ func TestNormalOperationsDefaultConfig(t *testing.T) { // IP address in private range - cache hit should result in sync callback being called the second time an IP address is queried wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(hostname string) { assert.Equal(t, "fakehostname-192.168.1.100", hostname) @@ -143,12 +150,12 @@ func TestNormalOperationsCacheDisabled(t *testing.T) { "network_devices.netflow.reverse_dns_enrichment_enabled": true, "reverse_dns_enrichment.cache.enabled": false, } - ts := testSetup(t, overrides, true, nil) + ts := testSetup(t, overrides, true, nil, 0) var wg sync.WaitGroup // Invalid IP address - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{1, 2, 3}, func(_ string) { assert.FailNow(t, "Sync callback should not be called for invalid IP address") @@ -160,7 +167,7 @@ func TestNormalOperationsCacheDisabled(t *testing.T) { assert.ErrorContains(t, err, "invalid IP address") // IP address not in private range - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{8, 8, 8, 8}, func(_ string) { assert.FailNow(t, "Sync callback should not be called for IP address not in private range") @@ -173,7 +180,7 @@ func TestNormalOperationsCacheDisabled(t *testing.T) { // IP address in private range - with cache disabled the async callback should be called every time wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -188,7 +195,7 @@ func TestNormalOperationsCacheDisabled(t *testing.T) { wg.Wait() wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -221,11 +228,11 @@ func TestRateLimiter(t *testing.T) { "network_devices.netflow.reverse_dns_enrichment_enabled": true, "reverse_dns_enrichment.rate_limiter.limit_per_sec": 1, } - ts := testSetup(t, overrides, true, nil) + ts := testSetup(t, overrides, true, nil, 0) // IP addresses in private range for i := range 20 { - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, byte(i)}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -279,6 +286,7 @@ func TestRateLimiterThrottled(t *testing.T) { &net.DNSError{Err: "test timeout error", IsTimeout: true}, }}, }, + 0, ) var wg sync.WaitGroup @@ -287,7 +295,7 @@ func TestRateLimiterThrottled(t *testing.T) { wg.Add(20) start := time.Now() for i := range 20 { - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, byte(i)}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -317,7 +325,7 @@ func TestRateLimiterThrottled(t *testing.T) { // These queries will get errors, exceeding throttle_error_threshold, which will cause the rate limiter to throttle down wg.Add(2) for i := 30; i < 32; i++ { - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, byte(i)}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -349,7 +357,7 @@ func TestRateLimiterThrottled(t *testing.T) { wg.Add(20) start = time.Now() for i := range 20 { - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, byte(i)}, func(hostname string) { assert.Equal(t, fmt.Sprintf("fakehostname-192.168.1.%d", i), hostname) @@ -382,7 +390,7 @@ func TestRateLimiterThrottled(t *testing.T) { wg.Add(6) start = time.Now() for i := 40; i < 46; i++ { - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, byte(i)}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -416,7 +424,7 @@ func TestRateLimiterThrottled(t *testing.T) { wg.Add(10) start = time.Now() for i := 50; i < 60; i++ { - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, byte(i)}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -457,7 +465,7 @@ func TestChannelFullRequestsDroppedWhenRateLimited(t *testing.T) { "reverse_dns_enrichment.rate_limiter.enabled": true, "reverse_dns_enrichment.rate_limiter.limit_per_sec": 1, } - ts := testSetup(t, overrides, true, nil) + ts := testSetup(t, overrides, true, nil, 0) var wg sync.WaitGroup @@ -466,7 +474,7 @@ func TestChannelFullRequestsDroppedWhenRateLimited(t *testing.T) { wg.Add(1) // only wait for one callback, most or all of the other requests will be dropped var once sync.Once for i := range 20 { - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, byte(i)}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -509,13 +517,13 @@ func TestCacheHitInProgress(t *testing.T) { "network_devices.netflow.reverse_dns_enrichment_enabled": true, "reverse_dns_enrichment.rate_limiter.limit_per_sec": 1, } - ts := testSetup(t, overrides, true, nil) + ts := testSetup(t, overrides, true, nil, 0) var wg sync.WaitGroup for range 10 { wg.Add(1) - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(hostname string) { assert.Equal(t, "fakehostname-192.168.1.100", hostname) @@ -530,7 +538,7 @@ func TestCacheHitInProgress(t *testing.T) { assert.NoError(t, err) wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 101}, func(hostname string) { assert.Equal(t, "fakehostname-192.168.1.101", hostname) @@ -581,12 +589,13 @@ func TestRetries(t *testing.T) { fmt.Errorf("test error")}, }, }, + 0, ) var wg sync.WaitGroup wg.Add(2) - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -599,7 +608,7 @@ func TestRetries(t *testing.T) { ) assert.NoError(t, err) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 101}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -615,7 +624,7 @@ func TestRetries(t *testing.T) { // both were within retry limits so should be cached wg.Add(2) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(hostname string) { assert.Equal(t, "fakehostname-192.168.1.100", hostname) @@ -626,7 +635,7 @@ func TestRetries(t *testing.T) { }, ) assert.NoError(t, err) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 101}, func(hostname string) { assert.Equal(t, "fakehostname-192.168.1.101", hostname) @@ -668,12 +677,13 @@ func TestRetriesExceeded(t *testing.T) { fmt.Errorf("test error3")}, }, }, + 0, ) var wg sync.WaitGroup wg.Add(1) - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -688,7 +698,7 @@ func TestRetriesExceeded(t *testing.T) { // Because an error was returned for all available retries this IP address should now have hostname "" cached wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(hostname string) { assert.Equal(t, "", hostname) @@ -725,12 +735,13 @@ func TestIsNotFound(t *testing.T) { &net.DNSError{Err: "no such host", IsNotFound: true}}, }, }, + 0, ) var wg sync.WaitGroup wg.Add(1) - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -745,7 +756,7 @@ func TestIsNotFound(t *testing.T) { wg.Wait() wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(hostname string) { assert.Equal(t, "", hostname) @@ -775,7 +786,7 @@ func TestCacheMaxSize(t *testing.T) { "network_devices.netflow.reverse_dns_enrichment_enabled": true, "reverse_dns_enrichment.cache.max_size": 5, } - ts := testSetup(t, overrides, true, nil) + ts := testSetup(t, overrides, true, nil, 0) var wg sync.WaitGroup @@ -783,7 +794,7 @@ func TestCacheMaxSize(t *testing.T) { num := 20 wg.Add(num) for i := range num { - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, byte(i)}, func(hostname string) { assert.Equal(t, fmt.Sprintf("fakehostname-192.168.1.%d", i), hostname) @@ -823,7 +834,7 @@ func TestCacheExpiration(t *testing.T) { "reverse_dns_enrichment.cache.entry_ttl": time.Duration(100) * time.Millisecond, "reverse_dns_enrichment.cache.clean_interval": time.Duration(1) * time.Second, } - ts := testSetup(t, overrides, true, nil) + ts := testSetup(t, overrides, true, nil, 0) var wg sync.WaitGroup @@ -831,7 +842,7 @@ func TestCacheExpiration(t *testing.T) { num := 100 wg.Add(num) for i := range num { - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, byte(i)}, func(hostname string) { assert.Equal(t, fmt.Sprintf("fakehostname-192.168.1.%d", i), hostname) @@ -874,13 +885,13 @@ func TestCachePersist(t *testing.T) { "run_path": t.TempDir(), } - ts := testSetup(t, overrides, true, nil) + ts := testSetup(t, overrides, true, nil, 0) var wg sync.WaitGroup // async callback should be called the first time an IP address is queried wg.Add(1) - err := ts.rdnsQuerier.GetHostname( + err := ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -896,7 +907,7 @@ func TestCachePersist(t *testing.T) { // cache hit should result in sync callback being called the second time an IP address is queried wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(hostname string) { assert.Equal(t, "fakehostname-192.168.1.100", hostname) @@ -923,13 +934,13 @@ func TestCachePersist(t *testing.T) { assert.NoError(t, ts.lc.Stop(ts.ctx)) // create new testsetup, validate that the IP address previously queried and cached is still cached - ts = testSetup(t, overrides, true, nil) + ts = testSetup(t, overrides, true, nil, 0) ts.validateExpectedGauge(t, "cache_size", 1.0) // cache hit should result in sync callback being called the first time the IP address is queried after // restart because persistent cache should have been loaded wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(hostname string) { assert.Equal(t, "fakehostname-192.168.1.100", hostname) @@ -955,14 +966,14 @@ func TestCachePersist(t *testing.T) { // create new testsetup with shorter entryTTL, validate that the IP address previously // cached has new shorter expiration time overrides["reverse_dns_enrichment.cache.entry_ttl"] = time.Duration(100) * time.Millisecond - ts = testSetup(t, overrides, true, nil) + ts = testSetup(t, overrides, true, nil, 0) ts.validateExpectedGauge(t, "cache_size", 1.0) time.Sleep(200 * time.Millisecond) // cache_hit_expired should result in async callback being called wg.Add(1) - err = ts.rdnsQuerier.GetHostname( + err = ts.rdnsQuerier.GetHostnameAsync( []byte{192, 168, 1, 100}, func(_ string) { assert.FailNow(t, "Sync callback should not be called") @@ -986,3 +997,214 @@ func TestCachePersist(t *testing.T) { }) ts.validateExpected(t, expectedTelemetry) } + +func TestGetHostname(t *testing.T) { + overrides := map[string]interface{}{ + "network_devices.netflow.reverse_dns_enrichment_enabled": true, + } + + ts := testSetup(t, overrides, true, nil, 0) + internalRDNSQuerier := ts.rdnsQuerier.(*rdnsQuerierImpl) + + tts := map[string]struct { + ip string + timeout time.Duration + expected string + errMsg string + }{ + "invalid_ip should error": { + ip: "invalid_ip", + timeout: 1 * time.Second, + expected: "", + errMsg: "invalid IP address", + }, + "public IPv4 should return empty no error": { + ip: "8.8.8.8", + timeout: 1 * time.Second, + expected: "", + errMsg: "", + }, + "private IPv4 not in cache should return hostname": { + ip: "192.168.1.100", + timeout: 1 * time.Second, + expected: "fakehostname-192.168.1.100", + errMsg: "", + }, + "private IPv4 in cache should return hostname": { + ip: "192.168.1.100", + timeout: 1 * time.Second, + expected: "fakehostname-192.168.1.100", + errMsg: "", + }, + "public IPv6 should return empty no error": { + ip: "2001:4860:4860::8888", + timeout: 1 * time.Second, + expected: "", + errMsg: "", + }, + "private IPv6 not in cache should return hostname": { + ip: "fd00::1", + timeout: 1 * time.Second, + expected: "fakehostname-fd00::1", + errMsg: "", + }, + "private IPv6 in cache should return hostname": { + ip: "fd00::1", + timeout: 1 * time.Second, + expected: "fakehostname-fd00::1", + errMsg: "", + }, + } + + for name, tt := range tts { + t.Run(name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(ts.ctx, tt.timeout) + defer cancel() + hostname, err := internalRDNSQuerier.GetHostname(ctx, tt.ip) + if tt.errMsg != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.errMsg) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tt.expected, hostname) + }) + } +} + +func TestGetHostnameTimeout(t *testing.T) { + overrides := map[string]interface{}{ + "network_devices.netflow.reverse_dns_enrichment_enabled": true, + } + // Set up with a delay to simulate timeout + ts := testSetup(t, overrides, true, nil, 3*time.Second) + internalRDNSQuerier := ts.rdnsQuerier.(*rdnsQuerierImpl) + ctx, cancel := context.WithTimeout(ts.ctx, 1*time.Millisecond) + + // Test with a timeout exceeding the specified timeout limit + hostname, err := internalRDNSQuerier.GetHostname(ctx, "192.168.1.100") + assert.Equal(t, "", hostname) + assert.Error(t, err) + assert.Contains(t, err.Error(), "timeout reached while resolving hostname for IP address 192.168.1.100") + + cancel() +} + +// Test that when the rate limit is exceeded and the channel fills requests are dropped. +func TestGetHostnameChannelFullRequestsDroppedWhenRateLimited(t *testing.T) { + overrides := map[string]interface{}{ + "network_devices.netflow.reverse_dns_enrichment_enabled": true, + "reverse_dns_enrichment.workers": 1, + "reverse_dns_enrichment.chan_size": 1, + "reverse_dns_enrichment.rate_limiter.enabled": true, + "reverse_dns_enrichment.rate_limiter.limit_per_sec": 1, + } + ts := testSetup(t, overrides, true, nil, 1*time.Second) + + // IP addresses in private range + var errCount atomic.Int32 + var wg sync.WaitGroup + for i := range 20 { + wg.Add(1) + go func(i int) { + defer wg.Done() + hostname, err := ts.rdnsQuerier.GetHostname(ts.ctx, fmt.Sprintf("192.168.1.%d", i)) + if err != nil { + assert.ErrorContains(t, err, "channel is full, dropping query for IP address") + errCount.Add(1) + } else { + assert.Equal(t, fmt.Sprintf("fakehostname-192.168.1.%d", i), hostname) + } + }(i) + } + wg.Wait() + + assert.GreaterOrEqual(t, errCount.Load(), int32(1)) + expectedTelemetry := ts.makeExpectedTelemetry(map[string]float64{ + "total": 20.0, + "private": 20.0, + "chan_added": float64(20 - errCount.Load()), + "dropped_chan_full": float64(errCount.Load()), + "cache_miss": 20.0, + }) + delete(expectedTelemetry, "successful") + ts.validateExpected(t, expectedTelemetry) + + minimumTelemetry := map[string]float64{ + "successful": 1.0, + } + ts.validateMinimum(t, minimumTelemetry) +} + +func TestGetHostnames(t *testing.T) { + overrides := map[string]interface{}{ + "network_devices.netflow.reverse_dns_enrichment_enabled": true, + } + + defaultTs := testSetup(t, overrides, true, nil, 100*time.Millisecond) + + tests := []struct { + name string + ts *testState + ipAddrs []string + timeout time.Duration + expected map[string]rdnsquerierdef.ReverseDNSResult + }{ + { + name: "valid IPs", + ts: defaultTs, + ipAddrs: []string{"192.168.1.100", "192.168.1.101"}, + timeout: 1 * time.Second, + expected: map[string]rdnsquerierdef.ReverseDNSResult{ + "192.168.1.100": {IP: "192.168.1.100", Hostname: "fakehostname-192.168.1.100"}, + "192.168.1.101": {IP: "192.168.1.101", Hostname: "fakehostname-192.168.1.101"}, + }, + }, + { + name: "invalid IP, private IPs, and public IP", + ts: defaultTs, + ipAddrs: []string{"invalid_ip", "192.168.1.102", "8.8.8.8", "192.168.1.100"}, + timeout: 1 * time.Second, + expected: map[string]rdnsquerierdef.ReverseDNSResult{ + "invalid_ip": {IP: "invalid_ip", Err: fmt.Errorf("invalid IP address invalid_ip")}, + "192.168.1.102": {IP: "192.168.1.102", Hostname: "fakehostname-192.168.1.102"}, + "8.8.8.8": {IP: "8.8.8.8"}, + "192.168.1.100": {IP: "192.168.1.100", Hostname: "fakehostname-192.168.1.100"}, + }, + }, + { + name: "invalid IP, timeout for private and public IPs", + ts: testSetup(t, overrides, true, nil, 10*time.Second), + ipAddrs: []string{"192.168.1.105", "invalid", "8.8.8.8"}, + timeout: 1 * time.Second, + expected: map[string]rdnsquerierdef.ReverseDNSResult{ + "192.168.1.105": {IP: "192.168.1.105", Err: fmt.Errorf("timeout reached while resolving hostname for IP address 192.168.1.105")}, + "invalid": {IP: "invalid", Err: fmt.Errorf("invalid IP address invalid")}, + "8.8.8.8": {IP: "8.8.8.8"}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(tt.ts.ctx, tt.timeout) + defer cancel() + + internalRDNSQuerier := tt.ts.rdnsQuerier.(*rdnsQuerierImpl) + results := internalRDNSQuerier.GetHostnames(ctx, tt.ipAddrs) + + for ip, expectedResult := range tt.expected { + result, ok := results[ip] + require.True(t, ok, "result for IP %s not found", ip) + assert.Equal(t, expectedResult.IP, result.IP) + assert.Equal(t, expectedResult.Hostname, result.Hostname) + if expectedResult.Err != nil { + require.Error(t, result.Err) + assert.Contains(t, result.Err.Error(), expectedResult.Err.Error()) + } else { + assert.NoError(t, result.Err) + } + } + }) + } +} diff --git a/comp/rdnsquerier/impl/rdnsquerier_testutils.go b/comp/rdnsquerier/impl/rdnsquerier_testutils.go index a7adbf3217bfc..d1b43364ac224 100644 --- a/comp/rdnsquerier/impl/rdnsquerier_testutils.go +++ b/comp/rdnsquerier/impl/rdnsquerier_testutils.go @@ -10,6 +10,7 @@ package rdnsquerierimpl import ( "context" "testing" + "time" "github.com/DataDog/datadog-agent/pkg/util/fxutil" "go.uber.org/fx" @@ -35,9 +36,18 @@ type fakeResults struct { type fakeResolver struct { config *rdnsQuerierConfig fakeIPResults map[string]*fakeResults + delay time.Duration + logger log.Component } func (r *fakeResolver) lookup(addr string) (string, error) { + + r.logger.Infof("fakeResolver.lookup(%s) with timeout %d", addr, r.delay) + + if r.delay > 0 { + time.Sleep(r.delay) + } + fr, ok := r.fakeIPResults[addr] if ok && len(fr.errors) > 0 { err := fr.errors[0] @@ -60,7 +70,7 @@ type testState struct { logComp log.Component } -func testSetup(t *testing.T, overrides map[string]interface{}, start bool, fakeIPResults map[string]*fakeResults) *testState { +func testSetup(t *testing.T, overrides map[string]interface{}, start bool, fakeIPResults map[string]*fakeResults, delay time.Duration) *testState { lc := compdef.NewTestLifecycle(t) config := fxutil.Test[config.Component](t, fx.Options( @@ -95,13 +105,13 @@ func testSetup(t *testing.T, overrides map[string]interface{}, start bool, fakeI assert.NotNil(t, internalCache) internalQuerier := internalCache.querier.(*querierImpl) assert.NotNil(t, internalQuerier) - internalQuerier.resolver = &fakeResolver{internalRDNSQuerier.config, fakeIPResults} + internalQuerier.resolver = &fakeResolver{internalRDNSQuerier.config, fakeIPResults, delay, logComp} } else { internalCache := internalRDNSQuerier.cache.(*cacheNone) assert.NotNil(t, internalCache) internalQuerier := internalCache.querier.(*querierImpl) assert.NotNil(t, internalQuerier) - internalQuerier.resolver = &fakeResolver{internalRDNSQuerier.config, fakeIPResults} + internalQuerier.resolver = &fakeResolver{internalRDNSQuerier.config, fakeIPResults, delay, logComp} } if start { @@ -149,7 +159,7 @@ func (ts *testState) validateExpected(t *testing.T, expectedTelemetry map[string } else { assert.NoError(t, err) assert.Len(t, metrics, 1) - assert.Equal(t, expected, metrics[0].Value()) + assert.Equal(t, expected, metrics[0].Value(), name) } } } diff --git a/comp/rdnsquerier/mock/mock.go b/comp/rdnsquerier/mock/mock.go index 9a1d678f60ae0..8bda6cb2eedf7 100644 --- a/comp/rdnsquerier/mock/mock.go +++ b/comp/rdnsquerier/mock/mock.go @@ -9,6 +9,7 @@ package mock import ( + "context" "fmt" "net/netip" @@ -27,10 +28,10 @@ func NewMock() rdnsquerier.Component { return &rdnsQuerierMock{} } -// GetHostname simulates resolving the hostname for the given IP address. If the IP address is in the private address +// GetHostnameAsync simulates resolving the hostname for the given IP address. If the IP address is in the private address // space then, depending on the IP address, either the updateHostnameSync callback will be invoked synchronously as if // there was a cache hit, or the updateHostnameAsync callback will be invoked asynchronously with the simulated resolved hostname. -func (q *rdnsQuerierMock) GetHostname(ipAddr []byte, updateHostnameSync func(string), updateHostnameAsync func(string, error)) error { +func (q *rdnsQuerierMock) GetHostnameAsync(ipAddr []byte, updateHostnameSync func(string), updateHostnameAsync func(string, error)) error { ipaddr, ok := netip.AddrFromSlice(ipAddr) if !ok { return fmt.Errorf("invalid IP address %v", ipAddr) @@ -51,3 +52,40 @@ func (q *rdnsQuerierMock) GetHostname(ipAddr []byte, updateHostnameSync func(str return nil } + +// GetHostname simulates resolving the hostname for the given IP address synchronously. If the IP address is in the private address +// space then the resolved hostname is returned. +func (q *rdnsQuerierMock) GetHostname(_ context.Context, ipAddr string) (string, error) { + netipAddr, err := netip.ParseAddr(ipAddr) + if err != nil { + return "", fmt.Errorf("invalid IP address %v", ipAddr) + } + + if !netipAddr.IsPrivate() { + return "", nil + } + + return "hostname-" + netipAddr.String(), nil +} + +// GetHostnames simulates resolving the hostnames for the given IP addresses synchronously. If the IP address is in the private address +// space then the resolved hostname is returned. +func (q *rdnsQuerierMock) GetHostnames(_ context.Context, ipAddrs []string) map[string]rdnsquerier.ReverseDNSResult { + results := make(map[string]rdnsquerier.ReverseDNSResult, len(ipAddrs)) + for _, ipAddr := range ipAddrs { + netipAddr, err := netip.ParseAddr(ipAddr) + if err != nil { + results[ipAddr] = rdnsquerier.ReverseDNSResult{IP: ipAddr, Err: fmt.Errorf("invalid IP address %v", ipAddr)} + continue + } + + if !netipAddr.IsPrivate() { + results[ipAddr] = rdnsquerier.ReverseDNSResult{IP: ipAddr} + continue + } + + results[ipAddr] = rdnsquerier.ReverseDNSResult{IP: ipAddr, Hostname: "hostname-" + netipAddr.String()} + } + + return results +} diff --git a/comp/remote-config/rcclient/component.go b/comp/remote-config/rcclient/component.go index fdbfcfe227f34..7e6a5088421fd 100644 --- a/comp/remote-config/rcclient/component.go +++ b/comp/remote-config/rcclient/component.go @@ -29,8 +29,9 @@ type Component interface { // Params is the input parameter struct for the RC client Component. type Params struct { - AgentName string - AgentVersion string + AgentName string + AgentVersion string + IsSystemProbe bool } // NoneModule return a None optional type for rcclient.Component. diff --git a/comp/remote-config/rcclient/rcclientimpl/rcclient.go b/comp/remote-config/rcclient/rcclientimpl/rcclient.go index 2dc7ffc5700f5..4e43c1d99b1aa 100644 --- a/comp/remote-config/rcclient/rcclientimpl/rcclient.go +++ b/comp/remote-config/rcclient/rcclientimpl/rcclient.go @@ -16,8 +16,10 @@ import ( "github.com/pkg/errors" "go.uber.org/fx" + configcomp "github.com/DataDog/datadog-agent/comp/core/config" log "github.com/DataDog/datadog-agent/comp/core/log/def" "github.com/DataDog/datadog-agent/comp/core/settings" + "github.com/DataDog/datadog-agent/comp/core/sysprobeconfig" "github.com/DataDog/datadog-agent/comp/remote-config/rcclient" "github.com/DataDog/datadog-agent/comp/remote-config/rcclient/types" "github.com/DataDog/datadog-agent/pkg/api/security" @@ -28,6 +30,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/remoteconfig/state" "github.com/DataDog/datadog-agent/pkg/util/fxutil" pkglog "github.com/DataDog/datadog-agent/pkg/util/log" + "github.com/DataDog/datadog-agent/pkg/util/optional" ) // Module defines the fx options for this component. @@ -52,6 +55,9 @@ type rcClient struct { // Tasks are separated from the other products, because they must be executed once taskListeners []types.RCAgentTaskListener settingsComponent settings.Component + config configcomp.Component + sysprobeConfig optional.Option[sysprobeconfig.Component] + isSystemProbe bool } type dependencies struct { @@ -64,6 +70,8 @@ type dependencies struct { Listeners []types.RCListener `group:"rCListener"` // <-- Fill automatically by Fx TaskListeners []types.RCAgentTaskListener `group:"rCAgentTaskListener"` // <-- Fill automatically by Fx SettingsComponent settings.Component + Config configcomp.Component + SysprobeConfig optional.Option[sysprobeconfig.Component] } // newRemoteConfigClient must not populate any Fx groups or return any types that would be consumed as dependencies by @@ -117,6 +125,9 @@ func newRemoteConfigClient(deps dependencies) (rcclient.Component, error) { client: c, clientMRF: clientMRF, settingsComponent: deps.SettingsComponent, + config: deps.Config, + sysprobeConfig: deps.SysprobeConfig, + isSystemProbe: deps.Params.IsSystemProbe, } if pkgconfigsetup.IsRemoteConfigEnabled(pkgconfigsetup.Datadog()) { @@ -260,8 +271,16 @@ func (rc rcClient) agentConfigUpdateCallback(updates map[string]state.RawConfig, return } + targetCmp := rc.config + localSysProbeConf, isSet := rc.sysprobeConfig.Get() + if isSet && rc.isSystemProbe { + pkglog.Infof("Using system probe config for remote config") + targetCmp = localSysProbeConf + } // Checks who (the source) is responsible for the last logLevel change - source := pkgconfigsetup.Datadog().GetSource("log_level") + source := targetCmp.GetSource("log_level") + + pkglog.Infof("A new log level configuration has been received through remote config, (source: %s, log_level '%s')", source, mergedConfig.LogLevel) switch source { case model.SourceRC: @@ -269,8 +288,8 @@ func (rc rcClient) agentConfigUpdateCallback(updates map[string]state.RawConfig, // - we want to change (once again) the log level through RC // - we want to fall back to the log level we had saved as fallback (in that case mergedConfig.LogLevel == "") if len(mergedConfig.LogLevel) == 0 { - pkgconfigsetup.Datadog().UnsetForSource("log_level", model.SourceRC) - pkglog.Infof("Removing remote-config log level override, falling back to '%s'", pkgconfigsetup.Datadog().Get("log_level")) + targetCmp.UnsetForSource("log_level", model.SourceRC) + pkglog.Infof("Removing remote-config log level override, falling back to '%s'", targetCmp.Get("log_level")) } else { newLevel := mergedConfig.LogLevel pkglog.Infof("Changing log level to '%s' through remote config", newLevel) @@ -291,6 +310,7 @@ func (rc rcClient) agentConfigUpdateCallback(updates map[string]state.RawConfig, // Need to update the log level even if the level stays the same because we need to update the source // Might be possible to add a check in deeper functions to avoid unnecessary work + pkglog.Infof("Changing log level to '%s' through remote config (new source)", mergedConfig.LogLevel) err = rc.settingsComponent.SetRuntimeSetting("log_level", mergedConfig.LogLevel, model.SourceRC) } diff --git a/comp/remote-config/rcclient/rcclientimpl/rcclient_test.go b/comp/remote-config/rcclient/rcclientimpl/rcclient_test.go index d31decbceb748..cf5a3cb093139 100644 --- a/comp/remote-config/rcclient/rcclientimpl/rcclient_test.go +++ b/comp/remote-config/rcclient/rcclientimpl/rcclient_test.go @@ -14,6 +14,7 @@ import ( logmock "github.com/DataDog/datadog-agent/comp/core/log/mock" "github.com/DataDog/datadog-agent/comp/core/settings" "github.com/DataDog/datadog-agent/comp/core/settings/settingsimpl" + "github.com/DataDog/datadog-agent/comp/core/sysprobeconfig" "github.com/DataDog/datadog-agent/comp/remote-config/rcclient" "github.com/DataDog/datadog-agent/pkg/api/security" configmock "github.com/DataDog/datadog-agent/pkg/config/mock" @@ -66,7 +67,9 @@ func TestRCClientCreate(t *testing.T) { fxutil.Test[dependencies]( t, fx.Provide(func() log.Component { return logmock.New(t) }), + fx.Provide(func() config.Component { return configmock.New(t) }), settingsimpl.MockModule(), + sysprobeconfig.NoneModule(), ), ) // Missing params @@ -76,6 +79,8 @@ func TestRCClientCreate(t *testing.T) { fxutil.Test[dependencies]( t, fx.Provide(func() log.Component { return logmock.New(t) }), + fx.Provide(func() config.Component { return configmock.New(t) }), + sysprobeconfig.NoneModule(), fx.Supply( rcclient.Params{ AgentName: "test-agent", @@ -92,12 +97,14 @@ func TestRCClientCreate(t *testing.T) { func TestAgentConfigCallback(t *testing.T) { pkglog.SetupLogger(seelog.Default, "info") - config := configmock.New(t) + cfg := configmock.New(t) rc := fxutil.Test[rcclient.Component](t, fx.Options( Module(), fx.Provide(func() log.Component { return logmock.New(t) }), + fx.Provide(func() config.Component { return cfg }), + sysprobeconfig.NoneModule(), fx.Supply( rcclient.Params{ AgentName: "test-agent", @@ -109,7 +116,7 @@ func TestAgentConfigCallback(t *testing.T) { Settings: map[string]settings.RuntimeSetting{ "log_level": &mockLogLevelRuntimeSettings{logLevel: "info"}, }, - Config: config, + Config: cfg, }, ), settingsimpl.Module(), @@ -122,11 +129,11 @@ func TestAgentConfigCallback(t *testing.T) { structRC := rc.(rcClient) - ipcAddress, err := pkgconfigsetup.GetIPCAddress(pkgconfigsetup.Datadog()) + ipcAddress, err := pkgconfigsetup.GetIPCAddress(cfg) assert.NoError(t, err) structRC.client, _ = client.NewUnverifiedGRPCClient( - ipcAddress, pkgconfigsetup.GetIPCPort(), func() (string, error) { return security.FetchAuthToken(pkgconfigsetup.Datadog()) }, + ipcAddress, pkgconfigsetup.GetIPCPort(), func() (string, error) { return security.FetchAuthToken(cfg) }, client.WithAgent("test-agent", "9.99.9"), client.WithProducts(state.ProductAgentConfig), client.WithPollInterval(time.Hour), @@ -134,15 +141,15 @@ func TestAgentConfigCallback(t *testing.T) { // ----------------- // Test scenario #1: Agent Flare request by RC and the log level hadn't been changed by the user before - assert.Equal(t, model.SourceDefault, pkgconfigsetup.Datadog().GetSource("log_level")) + assert.Equal(t, model.SourceDefault, cfg.GetSource("log_level")) // Set log level to debug structRC.agentConfigUpdateCallback(map[string]state.RawConfig{ "datadog/2/AGENT_CONFIG/layer1/configname": layerStartFlare, "datadog/2/AGENT_CONFIG/configuration_order/configname": configOrder, }, applyEmpty) - assert.Equal(t, "debug", pkgconfigsetup.Datadog().Get("log_level")) - assert.Equal(t, model.SourceRC, pkgconfigsetup.Datadog().GetSource("log_level")) + assert.Equal(t, "debug", cfg.Get("log_level")) + assert.Equal(t, model.SourceRC, cfg.GetSource("log_level")) // Send an empty log level request, as RC would at the end of the Agent Flare request // Should fallback to the default level @@ -150,36 +157,36 @@ func TestAgentConfigCallback(t *testing.T) { "datadog/2/AGENT_CONFIG/layer1/configname": layerEndFlare, "datadog/2/AGENT_CONFIG/configuration_order/configname": configOrder, }, applyEmpty) - assert.Equal(t, "info", pkgconfigsetup.Datadog().Get("log_level")) - assert.Equal(t, model.SourceDefault, pkgconfigsetup.Datadog().GetSource("log_level")) + assert.Equal(t, "info", cfg.Get("log_level")) + assert.Equal(t, model.SourceDefault, cfg.GetSource("log_level")) // ----------------- // Test scenario #2: log level was changed by the user BEFORE Agent Flare request - pkgconfigsetup.Datadog().Set("log_level", "info", model.SourceCLI) + cfg.Set("log_level", "info", model.SourceCLI) structRC.agentConfigUpdateCallback(map[string]state.RawConfig{ "datadog/2/AGENT_CONFIG/layer1/configname": layerStartFlare, "datadog/2/AGENT_CONFIG/configuration_order/configname": configOrder, }, applyEmpty) // Log level should still be "info" because it was enforced by the user - assert.Equal(t, "info", pkgconfigsetup.Datadog().Get("log_level")) + assert.Equal(t, "info", cfg.Get("log_level")) // Source should still be CLI as it has priority over RC - assert.Equal(t, model.SourceCLI, pkgconfigsetup.Datadog().GetSource("log_level")) + assert.Equal(t, model.SourceCLI, cfg.GetSource("log_level")) // ----------------- // Test scenario #3: log level is changed by the user DURING the Agent Flare request - pkgconfigsetup.Datadog().UnsetForSource("log_level", model.SourceCLI) + cfg.UnsetForSource("log_level", model.SourceCLI) structRC.agentConfigUpdateCallback(map[string]state.RawConfig{ "datadog/2/AGENT_CONFIG/layer1/configname": layerStartFlare, "datadog/2/AGENT_CONFIG/configuration_order/configname": configOrder, }, applyEmpty) - assert.Equal(t, "debug", pkgconfigsetup.Datadog().Get("log_level")) - assert.Equal(t, model.SourceRC, pkgconfigsetup.Datadog().GetSource("log_level")) + assert.Equal(t, "debug", cfg.Get("log_level")) + assert.Equal(t, model.SourceRC, cfg.GetSource("log_level")) - pkgconfigsetup.Datadog().Set("log_level", "debug", model.SourceCLI) + cfg.Set("log_level", "debug", model.SourceCLI) structRC.agentConfigUpdateCallback(map[string]state.RawConfig{ "datadog/2/AGENT_CONFIG/layer1/configname": layerEndFlare, "datadog/2/AGENT_CONFIG/configuration_order/configname": configOrder, }, applyEmpty) - assert.Equal(t, "debug", pkgconfigsetup.Datadog().Get("log_level")) - assert.Equal(t, model.SourceCLI, pkgconfigsetup.Datadog().GetSource("log_level")) + assert.Equal(t, "debug", cfg.Get("log_level")) + assert.Equal(t, model.SourceCLI, cfg.GetSource("log_level")) } diff --git a/comp/snmpscan/def/component.go b/comp/snmpscan/def/component.go index b81d86b2ea28f..1acd1b6cdb768 100644 --- a/comp/snmpscan/def/component.go +++ b/comp/snmpscan/def/component.go @@ -10,7 +10,7 @@ import ( "github.com/gosnmp/gosnmp" ) -// team: network-device-monitoring +// team: ndm-core // Component is the component type. type Component interface { diff --git a/comp/snmptraps/bundle.go b/comp/snmptraps/bundle.go index 1ea1023c6df00..a097561b8f5b8 100644 --- a/comp/snmptraps/bundle.go +++ b/comp/snmptraps/bundle.go @@ -12,7 +12,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) -// team: network-device-monitoring +// team: ndm-core // Bundle defines the fx options for this bundle. func Bundle() fxutil.BundleOptions { diff --git a/comp/snmptraps/config/component.go b/comp/snmptraps/config/component.go index 1fa60dee43b7e..4a21cca79a30a 100644 --- a/comp/snmptraps/config/component.go +++ b/comp/snmptraps/config/component.go @@ -7,7 +7,7 @@ // a component that provides it. package config -// team: network-device-monitoring +// team: ndm-core // Component is the component type. type Component interface { diff --git a/comp/snmptraps/formatter/component.go b/comp/snmptraps/formatter/component.go index cf792e0ad566f..8750e87177bec 100644 --- a/comp/snmptraps/formatter/component.go +++ b/comp/snmptraps/formatter/component.go @@ -10,7 +10,7 @@ import ( "github.com/DataDog/datadog-agent/comp/snmptraps/packet" ) -// team: network-device-monitoring +// team: ndm-core // Component is the component type. type Component interface { diff --git a/comp/snmptraps/forwarder/component.go b/comp/snmptraps/forwarder/component.go index f8675a8c5d3b4..74a7106c47cf0 100644 --- a/comp/snmptraps/forwarder/component.go +++ b/comp/snmptraps/forwarder/component.go @@ -7,7 +7,7 @@ // listener component, formats it properly, and sends it to the backend. package forwarder -// team: network-device-monitoring +// team: ndm-core // Component is the component type. type Component interface{} diff --git a/comp/snmptraps/listener/component.go b/comp/snmptraps/listener/component.go index e97b4fe25b473..db0114a7c498c 100644 --- a/comp/snmptraps/listener/component.go +++ b/comp/snmptraps/listener/component.go @@ -11,7 +11,7 @@ import ( "github.com/DataDog/datadog-agent/comp/snmptraps/packet" ) -// team: network-device-monitoring +// team: ndm-core // Component is the component type. type Component interface { diff --git a/comp/snmptraps/oidresolver/component.go b/comp/snmptraps/oidresolver/component.go index 7ed352f8ed8be..15573a5cbe816 100644 --- a/comp/snmptraps/oidresolver/component.go +++ b/comp/snmptraps/oidresolver/component.go @@ -6,7 +6,7 @@ // Package oidresolver resolves OIDs package oidresolver -// team: network-device-monitoring +// team: ndm-core // Component is a interface to get Trap and Variable metadata from OIDs type Component interface { diff --git a/comp/snmptraps/server/component.go b/comp/snmptraps/server/component.go index c7c14abf96821..596b49dedcecb 100644 --- a/comp/snmptraps/server/component.go +++ b/comp/snmptraps/server/component.go @@ -8,7 +8,7 @@ // reformats them, and sends the resulting data to the backend. package server -// team: network-device-monitoring +// team: ndm-core // Component is the SNMP traps server. It listens for SNMP traps messages and // sends traps data to the DD backend. diff --git a/comp/snmptraps/status/component.go b/comp/snmptraps/status/component.go index ac223c59edb7a..9586e9b6fdcaa 100644 --- a/comp/snmptraps/status/component.go +++ b/comp/snmptraps/status/component.go @@ -7,7 +7,7 @@ // component system. package status -// team: network-device-monitoring +// team: ndm-core // Component is the component type. type Component interface { diff --git a/comp/trace/config/config.go b/comp/trace/config/config.go index a686c1b0fd572..2d2e75f2c4110 100644 --- a/comp/trace/config/config.go +++ b/comp/trace/config/config.go @@ -16,6 +16,7 @@ import ( "gopkg.in/yaml.v2" coreconfig "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" apiutil "github.com/DataDog/datadog-agent/pkg/api/util" "github.com/DataDog/datadog-agent/pkg/config/env" "github.com/DataDog/datadog-agent/pkg/config/model" @@ -39,6 +40,7 @@ type Dependencies struct { fx.In Params Params Config coreconfig.Component + Tagger tagger.Component } // cfg implements the Component. diff --git a/comp/trace/config/config_otlp_test.go b/comp/trace/config/config_otlp_test.go index a15b74ee3bd1b..c7429b3588547 100644 --- a/comp/trace/config/config_otlp_test.go +++ b/comp/trace/config/config_otlp_test.go @@ -17,18 +17,12 @@ import ( "go.uber.org/fx" corecomp "github.com/DataDog/datadog-agent/comp/core/config" - "github.com/DataDog/datadog-agent/pkg/util/fxutil" ) func TestFullYamlConfigWithOTLP(t *testing.T) { - - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() require.NotNil(t, cfg) diff --git a/comp/trace/config/config_test.go b/comp/trace/config/config_test.go index f9b469ef2fe42..f83200f9a5fce 100644 --- a/comp/trace/config/config_test.go +++ b/comp/trace/config/config_test.go @@ -30,6 +30,8 @@ import ( "gopkg.in/yaml.v2" corecomp "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" apiutil "github.com/DataDog/datadog-agent/pkg/api/util" "github.com/DataDog/datadog-agent/pkg/config/env" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -146,10 +148,7 @@ func TestSplitTagRegex(t *testing.T) { func TestTelemetryEndpointsConfig(t *testing.T) { t.Run("default", func(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) cfg := config.Object() require.NotNil(t, cfg) @@ -163,11 +162,7 @@ func TestTelemetryEndpointsConfig(t *testing.T) { "apm_config.telemetry.dd_url": "http://example.com/", } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) @@ -181,11 +176,7 @@ func TestTelemetryEndpointsConfig(t *testing.T) { "apm_config.telemetry.dd_url": "111://abc.com", } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) @@ -200,11 +191,7 @@ func TestTelemetryEndpointsConfig(t *testing.T) { "site": "new_site.example.com", } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) @@ -222,11 +209,7 @@ func TestTelemetryEndpointsConfig(t *testing.T) { "apm_config.telemetry.additional_endpoints": additionalEndpoints, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) @@ -249,11 +232,7 @@ func TestTelemetryEndpointsConfig(t *testing.T) { "apm_config.telemetry.additional_endpoints": additionalEndpoints, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) @@ -282,26 +261,32 @@ func TestConfigHostname(t *testing.T) { fallbackHostnameFunc = os.Hostname }() + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + fxutil.TestStart(t, fx.Options( corecomp.MockModule(), fx.Replace(corecomp.MockParams{ Params: corecomp.Params{ConfFilePath: "./testdata/site_override.yaml"}, Overrides: overrides, }), + fx.Provide(func() tagger.Component { + return taggerComponent + }), MockModule(), - ), func(t testing.TB, app *fx.App) { - require.NotNil(t, app) + ), + func(t testing.TB, app *fx.App) { + require.NotNil(t, app) - ctx := context.Background() - err := app.Start(ctx) - defer app.Stop(ctx) + ctx := context.Background() + err := app.Start(ctx) + defer app.Stop(ctx) - require.NotNil(t, err) - assert.Contains(t, err.Error(), "nor from OS") + require.NotNil(t, err) + assert.Contains(t, err.Error(), "nor from OS") - }, func(_ Component) { - // nothing - }) + }, func(_ Component) { + // nothing + }) }) t.Run("fallback", func(t *testing.T) { @@ -315,14 +300,11 @@ func TestConfigHostname(t *testing.T) { t.Skip() } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/site_override.yaml"}, - Overrides: overrides, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/site_override.yaml"}, + Overrides: overrides, + })) + cfg := config.Object() require.NotNil(t, cfg) @@ -330,13 +312,9 @@ func TestConfigHostname(t *testing.T) { }) t.Run("file", func(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() @@ -347,13 +325,9 @@ func TestConfigHostname(t *testing.T) { t.Run("env", func(t *testing.T) { t.Setenv("DD_HOSTNAME", "onlyenv") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/site_override.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/site_override.yaml"}, + })) cfg := config.Object() require.NotNil(t, cfg) @@ -363,13 +337,9 @@ func TestConfigHostname(t *testing.T) { t.Run("file+env", func(t *testing.T) { t.Setenv("DD_HOSTNAME", "envoverride") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() require.NotNil(t, cfg) @@ -381,14 +351,10 @@ func TestConfigHostname(t *testing.T) { "serverless.enabled": true, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/site_default.yaml"}, - Overrides: overrides, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/site_default.yaml"}, + Overrides: overrides, + })) cfg := config.Object() require.NotNil(t, cfg) @@ -438,10 +404,7 @@ func TestConfigHostname(t *testing.T) { bin := makeProgram("host.name", 0) defer os.Remove(bin) - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) cfg := config.Object() require.NotNil(t, cfg) @@ -455,10 +418,7 @@ func TestConfigHostname(t *testing.T) { bin := makeProgram("", 0) defer os.Remove(bin) - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) cfg := config.Object() require.NotNil(t, cfg) @@ -471,10 +431,7 @@ func TestConfigHostname(t *testing.T) { bin := makeProgram("", 0) defer os.Remove(bin) - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) cfg := config.Object() require.NotNil(t, cfg) @@ -489,10 +446,7 @@ func TestConfigHostname(t *testing.T) { bin := makeProgram("", 1) defer os.Remove(bin) - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) cfg := config.Object() require.NotNil(t, cfg) @@ -505,10 +459,7 @@ func TestConfigHostname(t *testing.T) { bin := makeProgram("some text", 1) defer os.Remove(bin) - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) cfg := config.Object() require.NotNil(t, cfg) @@ -531,13 +482,9 @@ func TestSite(t *testing.T) { "vector": {"./testdata/observability_pipelines_worker_override.yaml", "https://observability_pipelines_worker.domain.tld:8443"}, } { t.Run(name, func(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: tt.file}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: tt.file}, + })) cfg := config.Object() require.NotNil(t, cfg) @@ -547,10 +494,7 @@ func TestSite(t *testing.T) { } func TestDefaultConfig(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) cfg := config.Object() require.NotNil(t, cfg) @@ -571,13 +515,9 @@ func TestDefaultConfig(t *testing.T) { } func TestNoAPMConfig(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/no_apm_config.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/no_apm_config.yaml"}, + })) cfg := config.Object() require.NotNil(t, cfg) @@ -589,13 +529,9 @@ func TestNoAPMConfig(t *testing.T) { } func TestDisableLoggingConfig(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/disable_file_logging.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/disable_file_logging.yaml"}, + })) cfg := config.Object() require.NotNil(t, cfg) @@ -604,13 +540,9 @@ func TestDisableLoggingConfig(t *testing.T) { } func TestFullYamlConfig(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() require.NotNil(t, cfg) @@ -709,13 +641,10 @@ func TestFullYamlConfig(t *testing.T) { } func TestFileLoggingDisabled(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/disable_file_logging.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/disable_file_logging.yaml"}, + })) + cfg := config.Object() require.NotNil(t, cfg) @@ -723,13 +652,9 @@ func TestFileLoggingDisabled(t *testing.T) { } func TestUndocumentedYamlConfig(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/undocumented.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/undocumented.yaml"}, + })) cfg := config.Object() require.NotNil(t, cfg) @@ -785,13 +710,9 @@ func TestNormalizeEnvFromDDEnv(t *testing.T) { t.Run("", func(t *testing.T) { t.Setenv("DD_ENV", in) - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/no_apm_config.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/no_apm_config.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -811,13 +732,9 @@ func TestNormalizeEnvFromDDTags(t *testing.T) { t.Run("", func(t *testing.T) { t.Setenv("DD_TAGS", in) - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/no_apm_config.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/no_apm_config.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -837,13 +754,9 @@ func TestNormalizeEnvFromConfig(t *testing.T) { "./testdata/non-normalized_env_host_tag.yaml", } { t.Run("", func(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: cfgFile}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: cfgFile}, + })) cfg := config.Object() @@ -870,13 +783,9 @@ func TestLoadEnv(t *testing.T) { t.Setenv(tt.envOld, "1,2,3") t.Setenv(tt.envNew, "4,5,6") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() @@ -893,13 +802,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "123") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -909,14 +814,10 @@ func TestLoadEnv(t *testing.T) { env = "DD_SITE" t.Run(env, func(t *testing.T) { t.Setenv(env, "my-site.com") + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/site_default.yaml"}, + })) - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/site_default.yaml"}, - }), - MockModule(), - )) cfg := config.Object() assert.NotNil(t, cfg) @@ -926,13 +827,9 @@ func TestLoadEnv(t *testing.T) { env = "DD_APM_ENABLED" t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -942,13 +839,9 @@ func TestLoadEnv(t *testing.T) { env = "DD_APM_DD_URL" t.Run(env, func(t *testing.T) { t.Setenv(env, "my-site.com") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -958,13 +851,9 @@ func TestLoadEnv(t *testing.T) { env = "HTTPS_PROXY" t.Run(env, func(t *testing.T) { t.Setenv(env, "my-proxy.url") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -974,13 +863,9 @@ func TestLoadEnv(t *testing.T) { env = "DD_PROXY_HTTPS" t.Run(env, func(t *testing.T) { t.Setenv(env, "my-proxy.url") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -990,13 +875,9 @@ func TestLoadEnv(t *testing.T) { env = "DD_HOSTNAME" t.Run(env, func(t *testing.T) { t.Setenv(env, "local.host") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -1006,13 +887,9 @@ func TestLoadEnv(t *testing.T) { env = "DD_BIND_HOST" t.Run(env, func(t *testing.T) { t.Setenv(env, "bindhost.com") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -1026,13 +903,9 @@ func TestLoadEnv(t *testing.T) { t.Run(envKey, func(t *testing.T) { t.Setenv(envKey, "1234") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -1044,13 +917,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "4321") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -1061,13 +930,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/undocumented.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/undocumented.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -1078,13 +943,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "12.3") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/undocumented.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/undocumented.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -1098,13 +959,9 @@ func TestLoadEnv(t *testing.T) { t.Run(envKey, func(t *testing.T) { t.Setenv(envKey, "1,2,3") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() assert.NotNil(t, cfg) @@ -1116,13 +973,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "web|http.request=1,db|sql.query=0.5") - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := config.Object() @@ -1137,13 +990,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `[{"name":"name1", "pattern":"pattern1"}, {"name":"name2","pattern":"pattern2","repl":"replace2"}]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() @@ -1168,13 +1017,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `important1 important2:value1`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() @@ -1186,13 +1031,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["important1:value with a space"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1204,13 +1045,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `important1 important2:^value1$`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() @@ -1222,13 +1059,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["important1:^value with a space$"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() @@ -1241,13 +1074,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `bad1:value1`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1258,13 +1087,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["bad1:value with a space"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1275,13 +1100,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["bad1:value with a space","bad2:value with spaces"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1295,13 +1116,9 @@ func TestLoadEnv(t *testing.T) { env = "DD_APM_FILTER_TAGS_REGEX_REJECT" t.Run(env, func(t *testing.T) { t.Setenv(env, `bad1:^value1$`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1311,13 +1128,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["bad1:value with a space"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1332,13 +1145,9 @@ func TestLoadEnv(t *testing.T) { t.Run(envKey, func(t *testing.T) { t.Setenv(envKey, "50") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1355,13 +1164,10 @@ func TestLoadEnv(t *testing.T) { t.Run(envKey, func(t *testing.T) { t.Setenv(envKey, "6") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/deprecated-max-tps-apm.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/deprecated-max-tps-apm.yaml"}, + })) + cfg := c.Object() assert.NotNil(t, cfg) @@ -1373,13 +1179,9 @@ func TestLoadEnv(t *testing.T) { t.Run(envKey, func(t *testing.T) { t.Setenv(envKey, "6") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1398,13 +1200,9 @@ func TestLoadEnv(t *testing.T) { t.Run(envKey, func(t *testing.T) { t.Setenv(envKey, "12") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1418,13 +1216,9 @@ func TestLoadEnv(t *testing.T) { t.Run(envKey, func(t *testing.T) { t.Setenv(envKey, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1438,13 +1232,9 @@ func TestLoadEnv(t *testing.T) { } { t.Run(envKey, func(t *testing.T) { t.Setenv(envKey, "7") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1456,13 +1246,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "337.41") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1473,13 +1259,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `{"url1": ["key1", "key2"], "url2": ["key3"]}`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1493,13 +1275,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "my-site.com") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1511,13 +1289,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "my-site.com") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1529,13 +1303,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "my-key") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1547,13 +1317,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `{"url1": ["key1", "key2"], "url2": ["key3"]}`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1572,13 +1338,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "my-diagnostics-site.com") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1590,13 +1352,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "my-diagnostics-key") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1608,13 +1366,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `{"diagnostics-url1": ["diagnostics-key1", "diagnostics-key2"], "diagnostics-url2": ["diagnostics-key3"]}`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1633,13 +1387,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "my-site.com") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1650,13 +1400,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "my-key") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1667,13 +1413,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `{"url1": ["key1", "key2"], "url2": ["key3"]}`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1692,13 +1434,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "false") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1711,13 +1449,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "false") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1728,13 +1462,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1746,13 +1476,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["client_id", "product_id"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1767,13 +1493,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["key1", "key2"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1788,13 +1510,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1806,13 +1524,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1824,13 +1538,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1842,13 +1552,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1862,13 +1568,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1880,13 +1582,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["document_id", "template_id"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1901,13 +1599,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["key1", "key2"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1922,13 +1616,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1940,13 +1630,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1958,13 +1644,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1976,13 +1658,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -1994,13 +1672,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["id1", "id2"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -2015,13 +1689,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["key1", "key2"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -2036,13 +1706,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, "true") - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -2054,13 +1720,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["id1", "id2"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -2075,13 +1737,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `["key1", "key2"]`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -2096,13 +1754,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `{"url1": ["key1", "key2"], "url2": ["key3"]}`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -2121,13 +1775,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { assert := func(in string, _ []string) { t.Setenv(env, in) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -2151,13 +1801,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `install_id_foo_bar`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) assert.Equal(t, "install_id_foo_bar", pkgconfigsetup.Datadog().GetString("apm_config.install_id")) @@ -2169,13 +1815,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `host_injection`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) assert.Equal(t, "host_injection", pkgconfigsetup.Datadog().GetString("apm_config.install_type")) @@ -2187,13 +1829,9 @@ func TestLoadEnv(t *testing.T) { t.Run(env, func(t *testing.T) { t.Setenv(env, `1699621675`) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/full.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) assert.Equal(t, int64(1699621675), pkgconfigsetup.Datadog().GetInt64("apm_config.install_time")) @@ -2223,13 +1861,9 @@ func TestFargateConfig(t *testing.T) { } { t.Run("", func(t *testing.T) { env.SetFeatures(t, data.features...) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/no_apm_config.yaml"}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/no_apm_config.yaml"}, + })) cfg := c.Object() assert.NotNil(t, cfg) @@ -2241,10 +1875,7 @@ func TestFargateConfig(t *testing.T) { func TestSetMaxMemCPU(t *testing.T) { t.Run("default, non-containerized", func(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) cfg := config.Object() require.NotNil(t, cfg) @@ -2255,10 +1886,7 @@ func TestSetMaxMemCPU(t *testing.T) { }) t.Run("default, containerized", func(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) cfg := config.Object() require.NotNil(t, cfg) @@ -2274,11 +1902,7 @@ func TestSetMaxMemCPU(t *testing.T) { "apm_config.max_memory": "200", } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) @@ -2293,11 +1917,7 @@ func TestSetMaxMemCPU(t *testing.T) { "apm_config.max_memory": "300", } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) @@ -2308,15 +1928,31 @@ func TestSetMaxMemCPU(t *testing.T) { } func TestPeerTagsAggregation(t *testing.T) { + + t.Run("default-enabled", func(t *testing.T) { + config := buildConfigComponent(t) + cfg := config.Object() + assert.True(t, cfg.PeerTagsAggregation) + assert.Nil(t, cfg.PeerTags) + + assert.Contains(t, cfg.ConfiguredPeerTags(), "_dd.base_service") // global base peer tag precursor + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.system") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.service") // known peer tag precursors that should be loaded from peer_tags.ini + }) + t.Run("disabled", func(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + overrides := map[string]interface{}{ + "apm_config.peer_service_aggregation": true, + "apm_config.peer_tags_aggregation": false, + } + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) assert.False(t, cfg.PeerTagsAggregation) assert.Nil(t, cfg.PeerTags) + assert.Nil(t, cfg.ConfiguredPeerTags()) }) t.Run("deprecated-enabled", func(t *testing.T) { @@ -2324,75 +1960,93 @@ func TestPeerTagsAggregation(t *testing.T) { "apm_config.peer_service_aggregation": true, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) assert.True(t, cfg.PeerTagsAggregation) assert.Nil(t, cfg.PeerTags) + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.system") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.service") // known peer tag precursors that should be loaded from peer_tags.ini }) - t.Run("enabled", func(t *testing.T) { + + t.Run("deprecated-disabled", func(t *testing.T) { overrides := map[string]interface{}{ - "apm_config.peer_tags_aggregation": true, + // Setting peer_service_aggregation to false has no effect. Nobody should be using this flag, though some previous beta customers might still need to migrate to peer_tags_aggregation. + "apm_config.peer_service_aggregation": false, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() + require.NotNil(t, cfg) assert.True(t, cfg.PeerTagsAggregation) assert.Nil(t, cfg.PeerTags) + assert.NotNil(t, cfg.ConfiguredPeerTags()) + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.system") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.service") // known peer tag precursors that should be loaded from peer_tags.ini }) + t.Run("both-enabled", func(t *testing.T) { overrides := map[string]interface{}{ "apm_config.peer_service_aggregation": true, "apm_config.peer_tags_aggregation": true, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) assert.True(t, cfg.PeerTagsAggregation) assert.Nil(t, cfg.PeerTags) + assert.NotNil(t, cfg.ConfiguredPeerTags()) + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.system") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.service") // known peer tag precursors that should be loaded from peer_tags.ini + }) + + t.Run("both-disabled", func(t *testing.T) { + overrides := map[string]interface{}{ + "apm_config.peer_service_aggregation": false, + "apm_config.peer_tags_aggregation": false, + } + + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) + cfg := config.Object() + require.NotNil(t, cfg) + assert.False(t, cfg.PeerTagsAggregation) + assert.Nil(t, cfg.PeerTags) + assert.Nil(t, cfg.ConfiguredPeerTags()) }) t.Run("disabled-user-tags", func(t *testing.T) { overrides := map[string]interface{}{ - "apm_config.peer_tags": []string{"user_peer_tag"}, + "apm_config.peer_tags_aggregation": false, + "apm_config.peer_tags": []string{"user_peer_tag"}, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) assert.False(t, cfg.PeerTagsAggregation) assert.Equal(t, []string{"user_peer_tag"}, cfg.PeerTags) + assert.Nil(t, cfg.ConfiguredPeerTags()) }) - t.Run("deprecated-enabled-user-tags", func(t *testing.T) { + t.Run("default-enabled-user-tags", func(t *testing.T) { overrides := map[string]interface{}{ - "apm_config.peer_tags": []string{"user_peer_tag"}, - "apm_config.peer_service_aggregation": true, + "apm_config.peer_tags": []string{"user_peer_tag"}, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() assert.True(t, cfg.PeerTagsAggregation) assert.Equal(t, []string{"user_peer_tag"}, cfg.PeerTags) + assert.Contains(t, cfg.ConfiguredPeerTags(), "user_peer_tag") + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.system") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.service") // known peer tag precursors that should be loaded from peer_tags.ini }) t.Run("enabled-user-tags", func(t *testing.T) { overrides := map[string]interface{}{ @@ -2400,11 +2054,7 @@ func TestPeerTagsAggregation(t *testing.T) { "apm_config.peer_tags_aggregation": true, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) assert.True(t, cfg.PeerTagsAggregation) @@ -2417,24 +2067,35 @@ func TestPeerTagsAggregation(t *testing.T) { "apm_config.peer_service_aggregation": true, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) assert.True(t, cfg.PeerTagsAggregation) assert.Equal(t, []string{"user_peer_tag"}, cfg.PeerTags) + assert.Contains(t, cfg.ConfiguredPeerTags(), "user_peer_tag") + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "db.system") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.hostname") // known peer tag precursors that should be loaded from peer_tags.ini + assert.Contains(t, cfg.ConfiguredPeerTags(), "peer.service") // known peer tag precursors that should be loaded from peer_tags.ini }) } func TestComputeStatsBySpanKind(t *testing.T) { + + t.Run("default-enabled", func(t *testing.T) { + config := buildConfigComponent(t) + + cfg := config.Object() + + require.NotNil(t, cfg) + assert.True(t, cfg.ComputeStatsBySpanKind) + }) + t.Run("disabled", func(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + overrides := map[string]interface{}{ + "apm_config.compute_stats_by_span_kind": false, + } + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) @@ -2446,11 +2107,7 @@ func TestComputeStatsBySpanKind(t *testing.T) { "apm_config.compute_stats_by_span_kind": true, } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{Overrides: overrides}), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{Overrides: overrides})) cfg := config.Object() require.NotNil(t, cfg) @@ -2466,13 +2123,10 @@ func TestGenerateInstallSignature(t *testing.T) { err = os.WriteFile(cfgFile, cfgContent, 0644) assert.NoError(t, err) - c := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: cfgFile}, - }), - MockModule(), - )) + c := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: cfgFile}, + })) + cfg := c.Object() assert.NotNil(t, cfg) @@ -2498,11 +2152,7 @@ func TestGenerateInstallSignature(t *testing.T) { func TestMockConfig(t *testing.T) { t.Setenv("DD_SITE", "datadoghq.eu") - config := fxutil.Test[Component](t, fx.Options( - fx.Supply(corecomp.Params{}), - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t, fx.Supply(corecomp.Params{})) cfg := config.Object() require.NotNil(t, cfg) @@ -2511,11 +2161,7 @@ func TestMockConfig(t *testing.T) { } func TestMockDefaultConfig(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - fx.Supply(corecomp.Params{}), - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t, fx.Supply(corecomp.Params{})) cfg := config.Object() require.NotNil(t, cfg) @@ -2524,11 +2170,7 @@ func TestMockDefaultConfig(t *testing.T) { } func TestGetCoreConfigHandler(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - fx.Supply(corecomp.Params{}), - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t, fx.Supply(corecomp.Params{})) handler := config.GetConfigHandler().(http.HandlerFunc) @@ -2565,13 +2207,9 @@ func TestGetCoreConfigHandler(t *testing.T) { } func TestDisableReceiverConfig(t *testing.T) { - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - fx.Replace(corecomp.MockParams{ - Params: corecomp.Params{ConfFilePath: "./testdata/disable_receiver.yaml"}, - }), - MockModule(), - )) + config := buildConfigComponent(t, fx.Replace(corecomp.MockParams{ + Params: corecomp.Params{ConfFilePath: "./testdata/disable_receiver.yaml"}, + })) cfg := config.Object() require.NotNil(t, cfg) @@ -2585,13 +2223,36 @@ func TestOnUpdateAPIKeyCallback(t *testing.T) { n++ } - config := fxutil.Test[Component](t, fx.Options( - corecomp.MockModule(), - MockModule(), - )) + config := buildConfigComponent(t) + config.OnUpdateAPIKey(callback) configC := config.(*cfg) configC.updateAPIKey("foo", "bar") assert.Equal(t, 1, n) } + +func buildConfigComponent(t *testing.T, coreConfigOptions ...fx.Option) Component { + t.Helper() + + coreConfig := fxutil.Test[corecomp.Component](t, + corecomp.MockModule(), + fx.Options(coreConfigOptions...), + ) + + taggerComponent := fxutil.Test[tagger.Mock](t, + fx.Replace(coreConfig), + taggerimpl.MockModule(), + ) + + c := fxutil.Test[Component](t, fx.Options( + fx.Provide(func() tagger.Component { + return taggerComponent + }), + fx.Provide(func() corecomp.Component { + return coreConfig + }), + MockModule(), + )) + return c +} diff --git a/comp/trace/config/setup.go b/comp/trace/config/setup.go index 6bd3be6278696..77b7c5ccbde0b 100644 --- a/comp/trace/config/setup.go +++ b/comp/trace/config/setup.go @@ -56,14 +56,14 @@ const ( func setupConfigCommon(deps Dependencies, _ string) (*config.AgentConfig, error) { confFilePath := deps.Config.ConfigFileUsed() - return LoadConfigFile(confFilePath, deps.Config) + return LoadConfigFile(confFilePath, deps.Config, deps.Tagger) } // LoadConfigFile returns a new configuration based on the given path. The path must not necessarily exist // and a valid configuration can be returned based on defaults and environment variables. If a // valid configuration can not be obtained, an error is returned. -func LoadConfigFile(path string, c corecompcfg.Component) (*config.AgentConfig, error) { - cfg, err := prepareConfig(c) +func LoadConfigFile(path string, c corecompcfg.Component, tagger tagger.Component) (*config.AgentConfig, error) { + cfg, err := prepareConfig(c, tagger) if err != nil { if !os.IsNotExist(err) { return nil, err @@ -80,7 +80,7 @@ func LoadConfigFile(path string, c corecompcfg.Component) (*config.AgentConfig, return cfg, validate(cfg, c) } -func prepareConfig(c corecompcfg.Component) (*config.AgentConfig, error) { +func prepareConfig(c corecompcfg.Component, tagger tagger.Component) (*config.AgentConfig, error) { cfg := config.New() cfg.DDAgentBin = defaultDDAgentBin cfg.AgentVersion = version.AgentVersion @@ -117,15 +117,13 @@ func prepareConfig(c corecompcfg.Component) (*config.AgentConfig, error) { cfg.RemoteConfigClient = client } } - cfg.ContainerTags = containerTagsFunc + cfg.ContainerTags = func(cid string) ([]string, error) { + return tagger.Tag(types.NewEntityID(types.ContainerID, cid), types.HighCardinality) + } cfg.ContainerProcRoot = coreConfigObject.GetString("container_proc_root") return cfg, nil } -func containerTagsFunc(cid string) ([]string, error) { - return tagger.Tag(types.NewEntityID(types.ContainerID, cid), types.HighCardinality) -} - // appendEndpoints appends any endpoint configuration found at the given cfgKey. // The format for cfgKey should be a map which has the URL as a key and one or // more API keys as an array value. @@ -224,13 +222,19 @@ func applyDatadogConfig(c *config.AgentConfig, core corecompcfg.Component) error c.ConnectionLimit = core.GetInt("apm_config.connection_limit") } - // NOTE: maintain backwards-compatibility with old peer service flag that will eventually be deprecated. - c.PeerTagsAggregation = core.GetBool("apm_config.peer_service_aggregation") - if c.PeerTagsAggregation { - log.Warn("`apm_config.peer_service_aggregation` is deprecated, please use `apm_config.peer_tags_aggregation` instead") + /** + * NOTE: PeerTagsAggregation is on by default as of Q4 2024. To get the default experience, + * customers DO NOT NEED to set "apm_config.peer_service_aggregation" (deprecated) or "apm_config.peer_tags_aggregation" (previously defaulted to false, now true). + * However, customers may opt out by explicitly setting "apm_config.peer_tags_aggregation" to "false". + */ + c.PeerTagsAggregation = core.GetBool("apm_config.peer_tags_aggregation") + + if !c.PeerTagsAggregation { + log.Info("peer tags aggregation is explicitly disabled. To enable it, remove `apm_config.peer_tags_aggregation: false` from your configuration") } - c.PeerTagsAggregation = c.PeerTagsAggregation || core.GetBool("apm_config.peer_tags_aggregation") + c.ComputeStatsBySpanKind = core.GetBool("apm_config.compute_stats_by_span_kind") + if core.IsSet("apm_config.peer_tags") { c.PeerTags = core.GetStringSlice("apm_config.peer_tags") } diff --git a/docs/cloud-workload-security/backend_linux.md b/docs/cloud-workload-security/backend_linux.md index a311d001bcbec..837f6fa1ef566 100644 --- a/docs/cloud-workload-security/backend_linux.md +++ b/docs/cloud-workload-security/backend_linux.md @@ -198,6 +198,19 @@ CSM Threats event for Linux systems have the following JSON schema: "type": "object", "description": "CGroupContextSerializer serializes a cgroup context to JSON" }, + "ConnectEvent": { + "properties": { + "addr": { + "$ref": "#/$defs/IPPortFamily" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "addr" + ], + "description": "ConnectEventSerializer serializes a connect event to JSON" + }, "ContainerContext": { "properties": { "id": { @@ -1742,6 +1755,9 @@ CSM Threats event for Linux systems have the following JSON schema: "bind": { "$ref": "#/$defs/BindEvent" }, + "connect": { + "$ref": "#/$defs/ConnectEvent" + }, "mount": { "$ref": "#/$defs/MountEvent" }, @@ -1793,6 +1809,7 @@ CSM Threats event for Linux systems have the following JSON schema: | `dns` | $ref | Please see [DNSEvent](#dnsevent) | | `imds` | $ref | Please see [IMDSEvent](#imdsevent) | | `bind` | $ref | Please see [BindEvent](#bindevent) | +| `connect` | $ref | Please see [ConnectEvent](#connectevent) | | `mount` | $ref | Please see [MountEvent](#mountevent) | | `syscalls` | $ref | Please see [SyscallsEvent](#syscallsevent) | | `usr` | $ref | Please see [UserContext](#usercontext) | @@ -2100,6 +2117,31 @@ CSM Threats event for Linux systems have the following JSON schema: | `manager` | CGroup manager | +## `ConnectEvent` + + +{{< code-block lang="json" collapsible="true" >}} +{ + "properties": { + "addr": { + "$ref": "#/$defs/IPPortFamily" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "addr" + ], + "description": "ConnectEventSerializer serializes a connect event to JSON" +} + +{{< /code-block >}} + + +| References | +| ---------- | +| [IPPortFamily](#ipportfamily) | + ## `ContainerContext` diff --git a/docs/cloud-workload-security/backend_linux.schema.json b/docs/cloud-workload-security/backend_linux.schema.json index ef0b9ecb5f6d7..8e87269948c8a 100644 --- a/docs/cloud-workload-security/backend_linux.schema.json +++ b/docs/cloud-workload-security/backend_linux.schema.json @@ -187,6 +187,19 @@ "type": "object", "description": "CGroupContextSerializer serializes a cgroup context to JSON" }, + "ConnectEvent": { + "properties": { + "addr": { + "$ref": "#/$defs/IPPortFamily" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "addr" + ], + "description": "ConnectEventSerializer serializes a connect event to JSON" + }, "ContainerContext": { "properties": { "id": { @@ -1731,6 +1744,9 @@ "bind": { "$ref": "#/$defs/BindEvent" }, + "connect": { + "$ref": "#/$defs/ConnectEvent" + }, "mount": { "$ref": "#/$defs/MountEvent" }, diff --git a/docs/cloud-workload-security/linux_expressions.md b/docs/cloud-workload-security/linux_expressions.md index 51fa104e4c68a..437198fc2aaf0 100644 --- a/docs/cloud-workload-security/linux_expressions.md +++ b/docs/cloud-workload-security/linux_expressions.md @@ -35,6 +35,7 @@ Triggers are events that correspond to types of activity seen by the system. The | `chdir` | File | [Experimental] A process changed the current directory | 7.52 | | `chmod` | File | A file’s permissions were changed | 7.27 | | `chown` | File | A file’s owner was changed | 7.27 | +| `connect` | Network | A connect was executed | 7.60 | | `dns` | Network | A DNS request was sent | 7.36 | | `exec` | Process | A process was executed or forked | 7.27 | | `exit` | Process | A process was terminated | 7.38 | @@ -201,6 +202,7 @@ The *file.rights* attribute can now be used in addition to *file.mode*. *file.mo | [`process.ancestors.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`process.ancestors.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`process.ancestors.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`process.ancestors.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`process.ancestors.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`process.ancestors.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`process.ancestors.length`](#common-string-length-doc) | Length of the corresponding element | @@ -282,6 +284,7 @@ The *file.rights* attribute can now be used in addition to *file.mode*. *file.mo | [`process.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`process.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`process.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`process.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`process.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`process.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`process.parent.args`](#common-process-args-doc) | Arguments of the process (as a string, excluding argv0) | @@ -353,6 +356,7 @@ The *file.rights* attribute can now be used in addition to *file.mode*. *file.mo | [`process.parent.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`process.parent.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`process.parent.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`process.parent.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`process.parent.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`process.parent.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`process.parent.pid`](#common-pidcontext-pid-doc) | Process ID of the process (also called thread group ID) | @@ -508,6 +512,20 @@ A file’s owner was changed | [`chown.syscall.path`](#chown-syscall-path-doc) | Path argument of the syscall | | [`chown.syscall.uid`](#chown-syscall-uid-doc) | UID argument of the syscall | +### Event `connect` + +A connect was executed + +| Property | Definition | +| -------- | ------------- | +| [`connect.addr.family`](#connect-addr-family-doc) | Address family | +| [`connect.addr.ip`](#common-ipportcontext-ip-doc) | IP address | +| [`connect.addr.port`](#common-ipportcontext-port-doc) | Port number | +| [`connect.retval`](#common-syscallevent-retval-doc) | Return value of the syscall | +| [`connect.server.addr.family`](#connect-server-addr-family-doc) | Server address family | +| [`connect.server.addr.ip`](#common-ipportcontext-ip-doc) | IP address | +| [`connect.server.addr.port`](#common-ipportcontext-port-doc) | Port number | + ### Event `dns` A DNS request was sent @@ -605,6 +623,7 @@ A process was executed or forked | [`exec.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`exec.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`exec.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`exec.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`exec.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`exec.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`exec.pid`](#common-pidcontext-pid-doc) | Process ID of the process (also called thread group ID) | @@ -695,6 +714,7 @@ A process was terminated | [`exit.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`exit.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`exit.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`exit.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`exit.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`exit.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`exit.pid`](#common-pidcontext-pid-doc) | Process ID of the process (also called thread group ID) | @@ -942,6 +962,7 @@ A raw network packet captured | [`packet.destination.ip`](#common-ipportcontext-ip-doc) | IP address | | [`packet.destination.port`](#common-ipportcontext-port-doc) | Port number | | [`packet.device.ifname`](#common-networkdevicecontext-ifname-doc) | Interface ifname | +| [`packet.filter`](#packet-filter-doc) | pcap filter expression | | [`packet.l3_protocol`](#common-networkcontext-l3_protocol-doc) | L3 protocol of the network packet | | [`packet.l4_protocol`](#common-networkcontext-l4_protocol-doc) | L4 protocol of the network packet | | [`packet.size`](#common-networkcontext-size-doc) | Size in bytes of the network packet | @@ -1026,6 +1047,7 @@ A ptrace command was executed | [`ptrace.tracee.ancestors.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`ptrace.tracee.ancestors.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`ptrace.tracee.ancestors.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`ptrace.tracee.ancestors.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`ptrace.tracee.ancestors.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`ptrace.tracee.ancestors.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`ptrace.tracee.ancestors.length`](#common-string-length-doc) | Length of the corresponding element | @@ -1107,6 +1129,7 @@ A ptrace command was executed | [`ptrace.tracee.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`ptrace.tracee.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`ptrace.tracee.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`ptrace.tracee.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`ptrace.tracee.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`ptrace.tracee.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`ptrace.tracee.parent.args`](#common-process-args-doc) | Arguments of the process (as a string, excluding argv0) | @@ -1178,6 +1201,7 @@ A ptrace command was executed | [`ptrace.tracee.parent.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`ptrace.tracee.parent.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`ptrace.tracee.parent.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`ptrace.tracee.parent.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`ptrace.tracee.parent.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`ptrace.tracee.parent.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`ptrace.tracee.parent.pid`](#common-pidcontext-pid-doc) | Process ID of the process (also called thread group ID) | @@ -1451,6 +1475,7 @@ A signal was sent | [`signal.target.ancestors.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`signal.target.ancestors.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`signal.target.ancestors.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`signal.target.ancestors.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`signal.target.ancestors.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`signal.target.ancestors.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`signal.target.ancestors.length`](#common-string-length-doc) | Length of the corresponding element | @@ -1532,6 +1557,7 @@ A signal was sent | [`signal.target.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`signal.target.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`signal.target.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`signal.target.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`signal.target.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`signal.target.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`signal.target.parent.args`](#common-process-args-doc) | Arguments of the process (as a string, excluding argv0) | @@ -1603,6 +1629,7 @@ A signal was sent | [`signal.target.parent.interpreter.file.rights`](#common-filefields-rights-doc) | Rights of the file | | [`signal.target.parent.interpreter.file.uid`](#common-filefields-uid-doc) | UID of the file's owner | | [`signal.target.parent.interpreter.file.user`](#common-filefields-user-doc) | User of the file's owner | +| [`signal.target.parent.is_exec`](#common-process-is_exec-doc) | Indicates whether the process entry is from a new binary execution | | [`signal.target.parent.is_kworker`](#common-pidcontext-is_kworker-doc) | Indicates whether the process is a kworker | | [`signal.target.parent.is_thread`](#common-process-is_thread-doc) | Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program) | | [`signal.target.parent.pid`](#common-pidcontext-pid-doc) | Process ID of the process (also called thread group ID) | @@ -2108,8 +2135,17 @@ Type: IP/CIDR Definition: IP address -`*.ip` has 5 possible prefixes: -`bind.addr` `network.destination` `network.source` `packet.destination` `packet.source` +`*.ip` has 7 possible prefixes: +`bind.addr` `connect.addr` `connect.server.addr` `network.destination` `network.source` `packet.destination` `packet.source` + + +### `*.is_exec` {#common-process-is_exec-doc} +Type: bool + +Definition: Indicates whether the process entry is from a new binary execution + +`*.is_exec` has 11 possible prefixes: +`exec` `exit` `process` `process.ancestors` `process.parent` `ptrace.tracee` `ptrace.tracee.ancestors` `ptrace.tracee.parent` `signal.target` `signal.target.ancestors` `signal.target.parent` ### `*.is_kworker` {#common-pidcontext-is_kworker-doc} @@ -2314,8 +2350,8 @@ Type: int Definition: Port number -`*.port` has 5 possible prefixes: -`bind.addr` `network.destination` `network.source` `packet.destination` `packet.source` +`*.port` has 7 possible prefixes: +`bind.addr` `connect.addr` `connect.server.addr` `network.destination` `network.source` `packet.destination` `packet.source` ### `*.ppid` {#common-process-ppid-doc} @@ -2332,8 +2368,8 @@ Type: int Definition: Return value of the syscall -`*.retval` has 22 possible prefixes: -`bind` `bpf` `chdir` `chmod` `chown` `link` `load_module` `mkdir` `mmap` `mount` `mprotect` `open` `ptrace` `removexattr` `rename` `rmdir` `setxattr` `signal` `splice` `unlink` `unload_module` `utimes` +`*.retval` has 23 possible prefixes: +`bind` `bpf` `chdir` `chmod` `chown` `connect` `link` `load_module` `mkdir` `mmap` `mount` `mprotect` `open` `ptrace` `removexattr` `rename` `rmdir` `setxattr` `signal` `splice` `unlink` `unload_module` `utimes` Constants: [Error constants](#error-constants) @@ -2611,6 +2647,20 @@ Definition: UID argument of the syscall +### `connect.addr.family` {#connect-addr-family-doc} +Type: int + +Definition: Address family + + + +### `connect.server.addr.family` {#connect-server-addr-family-doc} +Type: int + +Definition: Server address family + + + ### `container.created_at` {#container-created_at-doc} Type: int @@ -3005,6 +3055,13 @@ Definition: Path argument of the syscall +### `packet.filter` {#packet-filter-doc} +Type: string + +Definition: pcap filter expression + + + ### `packet.tls.version` {#packet-tls-version-doc} Type: int diff --git a/docs/cloud-workload-security/secl_linux.json b/docs/cloud-workload-security/secl_linux.json index 8e98f4ff09763..034d1b5c4f8ec 100644 --- a/docs/cloud-workload-security/secl_linux.json +++ b/docs/cloud-workload-security/secl_linux.json @@ -422,6 +422,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "process.ancestors.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "process.ancestors.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -827,6 +832,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "process.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "process.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -1182,6 +1192,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "process.parent.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "process.parent.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -1788,6 +1803,50 @@ } ] }, + { + "name": "connect", + "definition": "A connect was executed", + "type": "Network", + "from_agent_version": "7.60", + "experimental": false, + "properties": [ + { + "name": "connect.addr.family", + "definition": "Address family", + "property_doc_link": "connect-addr-family-doc" + }, + { + "name": "connect.addr.ip", + "definition": "IP address", + "property_doc_link": "common-ipportcontext-ip-doc" + }, + { + "name": "connect.addr.port", + "definition": "Port number", + "property_doc_link": "common-ipportcontext-port-doc" + }, + { + "name": "connect.retval", + "definition": "Return value of the syscall", + "property_doc_link": "common-syscallevent-retval-doc" + }, + { + "name": "connect.server.addr.family", + "definition": "Server address family", + "property_doc_link": "connect-server-addr-family-doc" + }, + { + "name": "connect.server.addr.ip", + "definition": "IP address", + "property_doc_link": "common-ipportcontext-ip-doc" + }, + { + "name": "connect.server.addr.port", + "definition": "Port number", + "property_doc_link": "common-ipportcontext-port-doc" + } + ] + }, { "name": "dns", "definition": "A DNS request was sent", @@ -2224,6 +2283,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "exec.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "exec.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -2648,6 +2712,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "exit.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "exit.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -3639,6 +3708,11 @@ "definition": "Interface ifname", "property_doc_link": "common-networkdevicecontext-ifname-doc" }, + { + "name": "packet.filter", + "definition": "pcap filter expression", + "property_doc_link": "packet-filter-doc" + }, { "name": "packet.l3_protocol", "definition": "L3 protocol of the network packet", @@ -4033,6 +4107,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "ptrace.tracee.ancestors.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "ptrace.tracee.ancestors.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -4438,6 +4517,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "ptrace.tracee.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "ptrace.tracee.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -4793,6 +4877,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "ptrace.tracee.parent.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "ptrace.tracee.parent.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -5950,6 +6039,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "signal.target.ancestors.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "signal.target.ancestors.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -6355,6 +6449,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "signal.target.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "signal.target.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -6710,6 +6809,11 @@ "definition": "User of the file's owner", "property_doc_link": "common-filefields-user-doc" }, + { + "name": "signal.target.parent.is_exec", + "definition": "Indicates whether the process entry is from a new binary execution", + "property_doc_link": "common-process-is_exec-doc" + }, { "name": "signal.target.parent.is_kworker", "definition": "Indicates whether the process is a kworker", @@ -8220,6 +8324,8 @@ "definition": "IP address", "prefixes": [ "bind.addr", + "connect.addr", + "connect.server.addr", "network.destination", "network.source", "packet.destination", @@ -8229,6 +8335,28 @@ "constants_link": "", "examples": [] }, + { + "name": "*.is_exec", + "link": "common-process-is_exec-doc", + "type": "bool", + "definition": "Indicates whether the process entry is from a new binary execution", + "prefixes": [ + "exec", + "exit", + "process", + "process.ancestors", + "process.parent", + "ptrace.tracee", + "ptrace.tracee.ancestors", + "ptrace.tracee.parent", + "signal.target", + "signal.target.ancestors", + "signal.target.parent" + ], + "constants": "", + "constants_link": "", + "examples": [] + }, { "name": "*.is_kworker", "link": "common-pidcontext-is_kworker-doc", @@ -8936,6 +9064,8 @@ "definition": "Port number", "prefixes": [ "bind.addr", + "connect.addr", + "connect.server.addr", "network.destination", "network.source", "packet.destination", @@ -8978,6 +9108,7 @@ "chdir", "chmod", "chown", + "connect", "link", "load_module", "mkdir", @@ -9532,6 +9663,30 @@ "constants_link": "", "examples": [] }, + { + "name": "connect.addr.family", + "link": "connect-addr-family-doc", + "type": "int", + "definition": "Address family", + "prefixes": [ + "connect" + ], + "constants": "", + "constants_link": "", + "examples": [] + }, + { + "name": "connect.server.addr.family", + "link": "connect-server-addr-family-doc", + "type": "int", + "definition": "Server address family", + "prefixes": [ + "connect" + ], + "constants": "", + "constants_link": "", + "examples": [] + }, { "name": "container.created_at", "link": "container-created_at-doc", @@ -10156,6 +10311,18 @@ "constants_link": "", "examples": [] }, + { + "name": "packet.filter", + "link": "packet-filter-doc", + "type": "string", + "definition": "pcap filter expression", + "prefixes": [ + "packet" + ], + "constants": "", + "constants_link": "", + "examples": [] + }, { "name": "packet.tls.version", "link": "packet-tls-version-doc", diff --git a/docs/dev/agent_omnibus.md b/docs/dev/agent_omnibus.md index ff7c87bb642f5..68ff17b6e3724 100644 --- a/docs/dev/agent_omnibus.md +++ b/docs/dev/agent_omnibus.md @@ -90,7 +90,7 @@ Start a Powershell prompt and navigate to your local clone of the `datadog-agent Run the following command: ```powershell -docker run -v "$(Get-Location):c:\mnt" -e OMNIBUS_TARGET=main -e RELEASE_VERSION=nightly -e MAJOR_VERSION=7 -e PY_RUNTIMES=3 -e TARGET_ARCH=x64 datadog/agent-buildimages-windows_x64:1809 c:\mnt\tasks\winbuildscripts\buildwin.bat +docker run -v "$(Get-Location):c:\mnt" -e OMNIBUS_TARGET=main -e RELEASE_VERSION=nightly -e MAJOR_VERSION=7 -e TARGET_ARCH=x64 datadog/agent-buildimages-windows_x64:1809 c:\mnt\tasks\winbuildscripts\buildwin.bat ``` Downloading the Docker image may take some time in the first run. @@ -105,16 +105,11 @@ param ( [bool]$DEBUG=$false ) -if ($MAJOR_VERSION -eq 7) { - $PY_RUNTIMES="3" -} else { - $PY_RUNTIMES="2,3" -} $cmd = "docker run" if ($RM_CONTAINER) { $cmd += " --rm " } -$opts = "-e OMNIBUS_TARGET=main -e RELEASE_VERSION=$RELEASE_VERSION -e MAJOR_VERSION=$MAJOR_VERSION -e PY_RUNTIMES=$PY_RUNTIMES -e TARGET_ARCH=$TARGET_ARCH" +$opts = "-e OMNIBUS_TARGET=main -e RELEASE_VERSION=$RELEASE_VERSION -e MAJOR_VERSION=$MAJOR_VERSION -e TARGET_ARCH=$TARGET_ARCH" if ($DEBUG) { $opts += " -e DEBUG_CUSTOMACTION=yes " } diff --git a/go.mod b/go.mod index a991242b0fb09..2539da884c15b 100644 --- a/go.mod +++ b/go.mod @@ -144,7 +144,7 @@ require ( code.cloudfoundry.org/garden v0.0.0-20210208153517-580cadd489d2 code.cloudfoundry.org/lager v2.0.0+incompatible github.com/CycloneDX/cyclonedx-go v0.9.1 - github.com/DataDog/appsec-internal-go v1.8.0 + github.com/DataDog/appsec-internal-go v1.9.0 github.com/DataDog/datadog-agent/pkg/gohai v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/obfuscate v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.57.0 @@ -271,11 +271,11 @@ require ( github.com/streadway/amqp v1.1.0 github.com/stretchr/testify v1.9.0 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 - github.com/tinylib/msgp v1.2.2 + github.com/tinylib/msgp v1.2.3 github.com/twmb/murmur3 v1.1.8 - github.com/uptrace/bun v1.2.1 - github.com/uptrace/bun/dialect/pgdialect v1.2.1 - github.com/uptrace/bun/driver/pgdriver v1.2.1 + github.com/uptrace/bun v1.2.5 + github.com/uptrace/bun/dialect/pgdialect v1.2.5 + github.com/uptrace/bun/driver/pgdriver v1.2.5 github.com/urfave/negroni v1.0.0 github.com/vishvananda/netlink v1.3.0 github.com/vishvananda/netns v0.0.4 @@ -299,7 +299,7 @@ require ( go.uber.org/atomic v1.11.0 go.uber.org/automaxprocs v1.6.0 go.uber.org/dig v1.18.0 - go.uber.org/fx v1.22.2 + go.uber.org/fx v1.23.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d @@ -373,19 +373,19 @@ require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect - github.com/aws/aws-sdk-go-v2 v1.32.2 - github.com/aws/aws-sdk-go-v2/config v1.28.0 - github.com/aws/aws-sdk-go-v2/credentials v1.17.41 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect + github.com/aws/aws-sdk-go-v2 v1.32.3 + github.com/aws/aws-sdk-go-v2/config v1.28.1 + github.com/aws/aws-sdk-go-v2/credentials v1.17.42 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect github.com/aws/aws-sdk-go-v2/service/ebs v1.27.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ec2 v1.186.0 - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ec2 v1.186.1 + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 // indirect github.com/aws/smithy-go v1.22.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 // indirect @@ -579,7 +579,7 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect k8s.io/component-base v0.29.3 - mellium.im/sasl v0.3.1 // indirect + mellium.im/sasl v0.3.2 // indirect modernc.org/cc/v3 v3.41.0 // indirect modernc.org/ccgo/v3 v3.16.15 // indirect modernc.org/libc v1.41.0 // indirect @@ -615,8 +615,8 @@ require ( github.com/DATA-DOG/go-sqlmock v1.5.2 github.com/DataDog/agent-payload/v5 v5.0.134 github.com/DataDog/datadog-agent/comp/api/api/def v0.56.0-rc.3 - github.com/DataDog/datadog-agent/comp/core/config v0.56.2 - github.com/DataDog/datadog-agent/comp/core/flare/types v0.56.2 + github.com/DataDog/datadog-agent/comp/core/config v0.57.1 + github.com/DataDog/datadog-agent/comp/core/flare/types v0.57.1 github.com/DataDog/datadog-agent/comp/core/hostname/hostnameinterface v0.56.0-rc.3 github.com/DataDog/datadog-agent/comp/core/log/def v0.58.0-devel github.com/DataDog/datadog-agent/comp/core/log/impl v0.0.0-00010101000000-000000000000 @@ -650,14 +650,14 @@ require ( github.com/DataDog/datadog-agent/comp/trace/compression/impl-gzip v0.56.0-rc.3 github.com/DataDog/datadog-agent/comp/trace/compression/impl-zstd v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/aggregator/ckey v0.56.0-rc.3 - github.com/DataDog/datadog-agent/pkg/api v0.56.2 + github.com/DataDog/datadog-agent/pkg/api v0.57.1 github.com/DataDog/datadog-agent/pkg/collector/check/defaults v0.57.1 github.com/DataDog/datadog-agent/pkg/config/env v0.57.1 github.com/DataDog/datadog-agent/pkg/config/mock v0.58.0-devel github.com/DataDog/datadog-agent/pkg/config/model v0.57.1 github.com/DataDog/datadog-agent/pkg/config/remote v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/config/setup v0.57.1 - github.com/DataDog/datadog-agent/pkg/config/utils v0.56.2 + github.com/DataDog/datadog-agent/pkg/config/utils v0.57.1 github.com/DataDog/datadog-agent/pkg/errors v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/logs/auditor v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/logs/client v0.56.0-rc.3 @@ -702,14 +702,14 @@ require ( github.com/DataDog/datadog-agent/pkg/util/testutil v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/util/uuid v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/util/winutil v0.57.1 - github.com/DataDog/datadog-agent/pkg/version v0.57.0 + github.com/DataDog/datadog-agent/pkg/version v0.57.1 github.com/DataDog/go-libddwaf/v3 v3.4.0 github.com/DataDog/go-sqllexer v0.0.16 github.com/Datadog/dublin-traceroute v0.0.2 github.com/aquasecurity/trivy v0.49.2-0.20240227072422-e1ea02c7b80d - github.com/aws/aws-sdk-go-v2/service/kms v1.37.2 - github.com/aws/aws-sdk-go-v2/service/rds v1.88.0 - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 + github.com/aws/aws-sdk-go-v2/service/kms v1.37.3 + github.com/aws/aws-sdk-go-v2/service/rds v1.89.0 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.3 github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240409155312-26d1ea377073 github.com/cloudfoundry-community/go-cfclient/v2 v2.0.1-0.20230503155151-3d15366c5820 github.com/containerd/cgroups/v3 v3.0.3 @@ -766,7 +766,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/Code-Hex/go-generics-cache v1.3.1 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/builder v0.56.2 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/builder v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/otelcol/otlp/components/statsprocessor v0.0.0-20240525065430-d0b647bcb646 // indirect github.com/DataDog/datadog-agent/pkg/config/nodetreemodel v0.60.0-devel // indirect github.com/DataDog/datadog-agent/pkg/config/teeconfig v0.60.0-devel // indirect @@ -930,8 +930,9 @@ require ( github.com/prometheus-community/windows_exporter v0.25.1 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect github.com/prometheus/prometheus v2.5.0+incompatible // indirect + github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/rs/zerolog v1.32.0 // indirect + github.com/rs/zerolog v1.33.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect diff --git a/go.sum b/go.sum index 9c06b8dcccbec..31f6b165fd244 100644 --- a/go.sum +++ b/go.sum @@ -680,8 +680,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7Oputl github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/DataDog/agent-payload/v5 v5.0.134 h1:h0oP3vDTOsjW1uKIZxKsCjOV/40jkY2Y+42GKAVH9ig= github.com/DataDog/agent-payload/v5 v5.0.134/go.mod h1:FgVQKmVdqdmZTbxIptqJC/l+xEzdiXsaAOs/vGAvWzs= -github.com/DataDog/appsec-internal-go v1.8.0 h1:1Tfn3LEogntRqZtf88twSApOCAAO3V+NILYhuQIo4J4= -github.com/DataDog/appsec-internal-go v1.8.0/go.mod h1:wW0cRfWBo4C044jHGwYiyh5moQV2x0AhnwqMuiX7O/g= +github.com/DataDog/appsec-internal-go v1.9.0 h1:cGOneFsg0JTRzWl5U2+og5dbtyW3N8XaYwc5nXe39Vw= +github.com/DataDog/appsec-internal-go v1.9.0/go.mod h1:wW0cRfWBo4C044jHGwYiyh5moQV2x0AhnwqMuiX7O/g= github.com/DataDog/aptly v1.5.3 h1:oLsRvjuXSVM4ia0N83dU3KiQeiJ6BaszYbTZOkSfDlw= github.com/DataDog/aptly v1.5.3/go.mod h1:ZL5TfCso+z4enH03N+s3z8tYUJHhL6DlxIvnnP2TbY4= github.com/DataDog/cast v1.3.1-0.20190301154711-1ee8c8bd14a3 h1:SobA9WYm4K/MUtWlbKaomWTmnuYp1KhIm8Wlx3vmpsg= @@ -885,27 +885,27 @@ github.com/aws/aws-sdk-go v1.53.11 h1:KcmduYvX15rRqt4ZU/7jKkmDxU/G87LJ9MUI0yQJh0 github.com/aws/aws-sdk-go v1.53.11/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= -github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI= -github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= +github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk= +github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14/go.mod h1:9NCTOURS8OpxvoAVHq79LK81/zC78hfRWFn+aL0SPcY= github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw= github.com/aws/aws-sdk-go-v2/config v1.19.0/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE= -github.com/aws/aws-sdk-go-v2/config v1.28.0 h1:FosVYWcqEtWNxHn8gB/Vs6jOlNwSoyOCA/g/sxyySOQ= -github.com/aws/aws-sdk-go-v2/config v1.28.0/go.mod h1:pYhbtvg1siOOg8h5an77rXle9tVG8T+BWLWAo7cOukc= +github.com/aws/aws-sdk-go-v2/config v1.28.1 h1:oxIvOUXy8x0U3fR//0eq+RdCKimWI900+SV+10xsCBw= +github.com/aws/aws-sdk-go-v2/config v1.28.1/go.mod h1:bRQcttQJiARbd5JZxw6wG0yIK3eLeSCPdg6uqmmlIiI= github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ= github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg= -github.com/aws/aws-sdk-go-v2/credentials v1.17.41 h1:7gXo+Axmp+R4Z+AK8YFQO0ZV3L0gizGINCOWxSLY9W8= -github.com/aws/aws-sdk-go-v2/credentials v1.17.41/go.mod h1:u4Eb8d3394YLubphT4jLEwN1rLNq2wFOlT6OuxFwPzU= +github.com/aws/aws-sdk-go-v2/credentials v1.17.42 h1:sBP0RPjBU4neGpIYyx8mkU2QqLPl5u9cmdTWVzIpHkM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.42/go.mod h1:FwZBfU530dJ26rv9saAbxa9Ej3eF/AK0OAY86k13n4M= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 h1:TMH3f/SCAWdNtXXVPPu5D6wrr4G5hI1rAxbcocKfC7Q= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17/go.mod h1:1ZRXLdTpzdJb9fwTMXiLipENRxkGMTn1sfKexGllQCw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 h1:68jFVtt3NulEzojFesM/WVarlFpCaXLKaBxDpzkQ9OQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18/go.mod h1:Fjnn5jQVIo6VyedMc0/EhPpfNlPl7dHV916O6B+49aE= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 h1:UAsR3xA31QGf79WzpG/ixT9FZvQlh5HY1NRqSHBNOCk= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21/go.mod h1:JNr43NFf5L9YaG3eKTm7HQzls9J+A9YYcGI5Quh1r2Y= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 h1:Jw50LwEkVjuVzE1NzkhNKkBf9cRN7MtE1F/b2cOKTUM= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22/go.mod h1:Y/SmAyPcOTmpeVaWSzSKiILfXTVJwrGmYZhcRbhWuEY= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 h1:6jZVETqmYCadGFvrYEQfC5fAQmlo80CeL5psbno6r0s= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21/go.mod h1:1SR0GbLlnN3QUmYaflZNiH1ql+1qrSiB2vwcJ+4UM60= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 h1:981MHwBaRZM7+9QSR6XamDzF/o7ouUGxFzr+nVSIhrs= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22/go.mod h1:1RA1+aBEfn+CAB/Mh0MB6LsdCYCnjZm7tKXtnk499ZQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= @@ -914,8 +914,8 @@ github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.6/go.mod h1:Q0Hq2X/NuL7z8b1Dww8rm github.com/aws/aws-sdk-go-v2/service/appconfig v1.4.2/go.mod h1:FZ3HkCe+b10uFZZkFdvf98LHW21k49W8o8J366lqVKY= github.com/aws/aws-sdk-go-v2/service/ebs v1.27.0 h1:4zuGQITyy9O+GlSGcs+aUz3+SmlvnYFc1/o4lRBs5Bw= github.com/aws/aws-sdk-go-v2/service/ebs v1.27.0/go.mod h1:T0t6q7wBD2P11xwVcc6GvwmuDT3i6ZJgZ+13ziQUUnA= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.186.0 h1:n2l2WeV+lEABrGwG/4MsE0WFEbd3j7yKsmZzbnEm5CY= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.186.0/go.mod h1:kYXaB4FzyhEJjvrJ84oPnMElLiEAjGxxUunVW2tBSng= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.186.1 h1:s3en74URaTjlhpJqOUCHlmombBFo88jxZqs3qjRmXrI= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.186.1/go.mod h1:ossaD9Z1ugYb6sq9QIqQLEOorCGcqUoxlhud9M9yE70= github.com/aws/aws-sdk-go-v2/service/ecr v1.36.0 h1:OVg61nfvhkvneY2btZ50sdYHsvhJs46dqtuBiURZo2A= github.com/aws/aws-sdk-go-v2/service/ecr v1.36.0/go.mod h1:kdKXMMVpJd/N59EYI8aneYNsQNqCd99iSg2bEmQHaUI= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.27.0 h1:k4ykVLeoO2JohTC7BIfIqWYvmf8HcirbWHf8Zn0SPpI= @@ -926,27 +926,27 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1: github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.38/go.mod h1:epIZoRSSbRIwLPJU5F+OldHhwZPBdpDeQkRdCeY3+00= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 h1:qcxX0JYlgWH3hpPUnd6U0ikcl6LLA9sLkXE2w1fpMvY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3/go.mod h1:cLSNEmI45soc+Ef8K/L+8sEA3A3pYFEYf5B5UI+6bH4= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.6/go.mod h1:lnc2taBsR9nTlz9meD+lhFZZ9EWY712QHrRflWpTcOA= -github.com/aws/aws-sdk-go-v2/service/kms v1.37.2 h1:tfBABi5R6aSZlhgTWHxL+opYUDOnIGoNcJLwVYv0jLM= -github.com/aws/aws-sdk-go-v2/service/kms v1.37.2/go.mod h1:dZYFcQwuoh+cLOlFnZItijZptmyDhRIkOKWFO1CfzV8= -github.com/aws/aws-sdk-go-v2/service/rds v1.88.0 h1:QdpwmIB0ZZN/devOnw+dJSF2VFnmn3LM5kuEKQ0kpj0= -github.com/aws/aws-sdk-go-v2/service/rds v1.88.0/go.mod h1:KziDa/w2AVz3dfANxwuBV0XqoQjxTKbVQyLNH5BRvO4= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.3 h1:VpyBA6KP6JgzwokQps8ArQPGy9rFej8adwuuQGcduH8= +github.com/aws/aws-sdk-go-v2/service/kms v1.37.3/go.mod h1:TT/9V4PcmSPpd8LPUNJ8hBHJmpqcfhx6MrbWTkvyR+4= +github.com/aws/aws-sdk-go-v2/service/rds v1.89.0 h1:4x0WbBa+i/AS0AFlj7yvx3n+GuK3XR58J6t61pW6h8U= +github.com/aws/aws-sdk-go-v2/service/rds v1.89.0/go.mod h1:WB+SVZKu1IBpsy3GrpR2EBnqB6A05Bd0r4RDLRqMbdk= github.com/aws/aws-sdk-go-v2/service/s3 v1.40.2/go.mod h1:Zjfqt7KhQK+PO1bbOsFNzKgaq7TcxzmEoDWN8lM0qzQ= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 h1:Rrqru2wYkKQCS2IM5/JrgKUQIoNTqA6y/iuxkjzxC6M= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2/go.mod h1:QuCURO98Sqee2AXmqDNxKXYFm2OEDAVAPApMqO0Vqnc= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.3 h1:CyA6J82ePPoh1Nj8ErOR2e/JRlzfFzWpGwGMFzFjwZg= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.3/go.mod h1:EliITPlGcBz0FRiVl7lRLtzI1cnDybFcfLYMZedOInE= github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 h1:bSYXVyUzoTHoKalBmwaZxs97HU9DWWI3ehHSAMa7xOk= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.2/go.mod h1:skMqY7JElusiOUjMJMOv1jJsP7YUg7DrhgqZZWuzu1U= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 h1:UTpsIf0loCIWEbrqdLb+0RxnTXfWh2vhw4nQmFi4nPc= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.3/go.mod h1:FZ9j3PFHHAR+w0BSEjK955w5YD2UwB/l/H0yAK3MJvI= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3/go.mod h1:a7bHA82fyUXOm+ZSWKU6PIoBxrjSprdLoM8xPYvzYVg= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 h1:AhmO1fHINP9vFYUE0LHzCWg/LfUWUF+zFPEcY9QXb7o= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2/go.mod h1:o8aQygT2+MVP0NaV6kbdE1YnnIM8RRVQzoeUH45GOdI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 h1:2YCmIXv3tmiItw0LlYf6v7gEHebLY45kBEnPezbUKyU= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3/go.mod h1:u19stRyNPxGhj6dRm+Cdgu6N75qnbW7+QN0q0dsAk58= github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 h1:CiS7i0+FUe+/YY1GvIBLLrR/XNGZ4CtM1Ll0XavNuVo= -github.com/aws/aws-sdk-go-v2/service/sts v1.32.2/go.mod h1:HtaiBI8CjYoNVde8arShXb94UbQQi9L4EMr6D+xGBwo= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 h1:wVnQ6tigGsRqSWDEEyH6lSAJ9OyFUsSnbaUWChuSGzs= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.3/go.mod h1:VZa9yTFyj4o10YGsmDO4gbQJUvvhY72fhumT8W4LqsE= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= @@ -2247,6 +2247,8 @@ github.com/prometheus/prometheus v0.51.2-0.20240405174432-b4a973753c6e h1:UmqAuY github.com/prometheus/prometheus v0.51.2-0.20240405174432-b4a973753c6e/go.mod h1:+0ld+ozir7zWFcHA2vVpWAKxXakIioEjPPNOqH+J3ZA= github.com/protocolbuffers/protoscope v0.0.0-20221109213918-8e7a6aafa2c9 h1:arwj11zP0yJIxIRiDn22E0H8PxfF7TsTrc2wIPFIsf4= github.com/protocolbuffers/protoscope v0.0.0-20221109213918-8e7a6aafa2c9/go.mod h1:SKZx6stCn03JN3BOWTwvVIO2ajMkb/zQdTceXYhKw/4= +github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4= +github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY= @@ -2278,8 +2280,8 @@ github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= -github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= -github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= @@ -2455,8 +2457,8 @@ github.com/tidwall/wal v1.1.7 h1:emc1TRjIVsdKKSnpwGBAcsAGg0767SvUk8+ygx7Bb+4= github.com/tidwall/wal v1.1.7/go.mod h1:r6lR1j27W9EPalgHiB7zLJDYu3mzW5BQP5KrzBpYY/E= github.com/tilinna/clock v1.1.0 h1:6IQQQCo6KoBxVudv6gwtY8o4eDfhHo8ojA5dP0MfhSs= github.com/tilinna/clock v1.1.0/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= -github.com/tinylib/msgp v1.2.2 h1:iHiBE1tJQwFI740SPEPkGE8cfhNfrqOYRlH450BnC/4= -github.com/tinylib/msgp v1.2.2/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0= +github.com/tinylib/msgp v1.2.3 h1:6ryR/GnmkqptS/HSe6JylgoKASyBKefBQnvIesnyiV4= +github.com/tinylib/msgp v1.2.3/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= @@ -2485,12 +2487,12 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/uptrace/bun v1.2.1 h1:2ENAcfeCfaY5+2e7z5pXrzFKy3vS8VXvkCag6N2Yzfk= -github.com/uptrace/bun v1.2.1/go.mod h1:cNg+pWBUMmJ8rHnETgf65CEvn3aIKErrwOD6IA8e+Ec= -github.com/uptrace/bun/dialect/pgdialect v1.2.1 h1:ceP99r03u+s8ylaDE/RzgcajwGiC76Jz3nS2ZgyPQ4M= -github.com/uptrace/bun/dialect/pgdialect v1.2.1/go.mod h1:mv6B12cisvSc6bwKm9q9wcrr26awkZK8QXM+nso9n2U= -github.com/uptrace/bun/driver/pgdriver v1.2.1 h1:Cp6c1tKzbTIyL8o0cGT6cOhTsmQZdsUNhgcV51dsmLU= -github.com/uptrace/bun/driver/pgdriver v1.2.1/go.mod h1:jEd3WGx74hWLat3/IkesOoWNjrFNUDADK3nkyOFOOJM= +github.com/uptrace/bun v1.2.5 h1:gSprL5xiBCp+tzcZHgENzJpXnmQwRM/A6s4HnBF85mc= +github.com/uptrace/bun v1.2.5/go.mod h1:vkQMS4NNs4VNZv92y53uBSHXRqYyJp4bGhMHgaNCQpY= +github.com/uptrace/bun/dialect/pgdialect v1.2.5 h1:dWLUxpjTdglzfBks2x+U2WIi+nRVjuh7Z3DLYVFswJk= +github.com/uptrace/bun/dialect/pgdialect v1.2.5/go.mod h1:stwnlE8/6x8cuQ2aXcZqwDK/d+6jxgO3iQewflJT6C4= +github.com/uptrace/bun/driver/pgdriver v1.2.5 h1:+0Ofdg/tW7DsIXdTizYWapSex6Csh9VdBg6/bbAZWJw= +github.com/uptrace/bun/driver/pgdriver v1.2.5/go.mod h1:RsYV08Z72glum3swBhag7IBl1D+eztjWmodfcOZFHJ0= github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= @@ -2748,8 +2750,8 @@ go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw= go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= -go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= -go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= +go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg= +go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -3705,8 +3707,8 @@ lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo= -mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw= +mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0= +mellium.im/sasl v0.3.2/go.mod h1:NKXDi1zkr+BlMHLQjY3ofYuU4KSPFxknb8mfEu6SveY= modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20= diff --git a/omnibus/config/software/datadog-agent-dependencies.rb b/omnibus/config/software/datadog-agent-dependencies.rb index 9b0ba32e5e80c..3cac114d0578e 100644 --- a/omnibus/config/software/datadog-agent-dependencies.rb +++ b/omnibus/config/software/datadog-agent-dependencies.rb @@ -8,3 +8,5 @@ dependency 'datadog-agent-integrations-py3-dependencies' dependency "systemd" if linux_target? + +dependency 'libpcap' if linux_target? and !heroku_target? # system-probe dependency \ No newline at end of file diff --git a/omnibus/config/software/libpcap.rb b/omnibus/config/software/libpcap.rb new file mode 100644 index 0000000000000..9ab7ffdd05f02 --- /dev/null +++ b/omnibus/config/software/libpcap.rb @@ -0,0 +1,42 @@ +# Unless explicitly stated otherwise all files in this repository are licensed +# under the Apache License Version 2.0. +# This product includes software developed at Datadog (https:#www.datadoghq.com/). +# Copyright 2016-present Datadog, Inc. + +name "libpcap" +default_version "1.10.5" +# system-probe doesn't depend on any particular version of libpcap so use the latest one (as of 2024-10-28) +# this version should be kept in sync with the one in tasks/system_probe.py +version "1.10.5" do + source sha256: "84fa89ac6d303028c1c5b754abff77224f45eca0a94eb1a34ff0aa9ceece3925" +end + +license "BSD-3-Clause" +license_file "LICENSE" + +relative_path "libpcap-#{version}" + +source url: "https://www.tcpdump.org/release/libpcap-#{version}.tar.xz" + +build do + env = with_standard_compiler_flags(with_embedded_path) + + configure_options = [ + "--disable-largefile", + "--disable-instrument-functions", + "--disable-remote", + "--disable-usb", + "--disable-netmap", + "--disable-bluetooth", + "--disable-dbus", + "--disable-rdma", + ] + configure(*configure_options, env: env) + + make "-j #{workers}", env: env + make "install", env: env + + delete "#{install_dir}/embedded/bin/pcap-config" + delete "#{install_dir}/embedded/lib/libpcap.a" + +end diff --git a/omnibus/config/templates/datadog-agent-mac-app/Info.plist.erb b/omnibus/config/templates/datadog-agent-mac-app/Info.plist.erb index b9e9ca1c48fc9..9d072aff55bbe 100644 --- a/omnibus/config/templates/datadog-agent-mac-app/Info.plist.erb +++ b/omnibus/config/templates/datadog-agent-mac-app/Info.plist.erb @@ -32,5 +32,7 @@ Copyright (c) 2009-<%= year %>, Datadog Inc. NSPrincipalClass NSApplication + NSLocalNetworkUsageDescription + Datadog needs access to local network services to function" diff --git a/omnibus/resources/agent/msi/localbuild/parameters.wxi b/omnibus/resources/agent/msi/localbuild/parameters.wxi index 765ec176d065c..9ee29728fdedd 100644 --- a/omnibus/resources/agent/msi/localbuild/parameters.wxi +++ b/omnibus/resources/agent/msi/localbuild/parameters.wxi @@ -8,8 +8,6 @@ - - diff --git a/omnibus/resources/agent/msi/source.wxs.erb b/omnibus/resources/agent/msi/source.wxs.erb index 6052c001d7639..5442ec2c52d10 100644 --- a/omnibus/resources/agent/msi/source.wxs.erb +++ b/omnibus/resources/agent/msi/source.wxs.erb @@ -205,8 +205,8 @@ Name="ConfigRoot" /> - - + + - - - - - - - - - - - - - - - - - @@ -466,7 +427,7 @@ - + @@ -516,23 +477,20 @@ - - - - + - + - + - + @@ -546,12 +504,12 @@ > - + @@ -559,8 +517,8 @@ - - + + @@ -616,7 +574,7 @@ WelcomeDlg License Agreement IF NOT UPGRADE Customize - Apikey + Apikey Site DDAgentUser VerifyReady @@ -632,7 +590,7 @@ (NOT WixUI_InstallMode) AND (NOT PREVIOUSFOUND) AND (NOT DATADOGYAMLEXISTS) WixUI_InstallMode OR PREVIOUSFOUND OR DATADOGYAMLEXISTS - + (NOT WixUI_InstallMode) AND (NOT PREVIOUSFOUND) (NOT WixUI_InstallMode) AND PREVIOUSFOUND WixUI_InstallMode diff --git a/omnibus/resources/dogstatsd/msi/localbuild/parameters.wxi b/omnibus/resources/dogstatsd/msi/localbuild/parameters.wxi index 6d46f995012c4..b29a1e92c8029 100644 --- a/omnibus/resources/dogstatsd/msi/localbuild/parameters.wxi +++ b/omnibus/resources/dogstatsd/msi/localbuild/parameters.wxi @@ -8,7 +8,5 @@ - - diff --git a/pkg/aggregator/aggregator.go b/pkg/aggregator/aggregator.go index 623ee7809a5bb..b1fa7fb464c5c 100644 --- a/pkg/aggregator/aggregator.go +++ b/pkg/aggregator/aggregator.go @@ -261,10 +261,10 @@ type BufferedAggregator struct { health *health.Handle agentName string // Name of the agent for telemetry metrics - tlmContainerTagsEnabled bool // Whether we should call the tagger to tag agent telemetry metrics - agentTags func(types.TagCardinality) ([]string, error) // This function gets the agent tags from the tagger (defined as a struct field to ease testing) - globalTags func(types.TagCardinality) ([]string, error) // This function gets global tags from the tagger when host tags are not available - + tlmContainerTagsEnabled bool // Whether we should call the tagger to tag agent telemetry metrics + agentTags func(types.TagCardinality) ([]string, error) // This function gets the agent tags from the tagger (defined as a struct field to ease testing) + globalTags func(types.TagCardinality) ([]string, error) // This function gets global tags from the tagger when host tags are not available + tagger tagger.Component flushAndSerializeInParallel FlushAndSerializeInParallel } @@ -283,7 +283,7 @@ func NewFlushAndSerializeInParallel(config model.Config) FlushAndSerializeInPara } // NewBufferedAggregator instantiates a BufferedAggregator -func NewBufferedAggregator(s serializer.MetricSerializer, eventPlatformForwarder eventplatform.Component, hostname string, flushInterval time.Duration) *BufferedAggregator { +func NewBufferedAggregator(s serializer.MetricSerializer, eventPlatformForwarder eventplatform.Component, tagger tagger.Component, hostname string, flushInterval time.Duration) *BufferedAggregator { bufferSize := pkgconfigsetup.Datadog().GetInt("aggregator_buffer_size") agentName := flavor.GetFlavor() @@ -336,6 +336,7 @@ func NewBufferedAggregator(s serializer.MetricSerializer, eventPlatformForwarder tlmContainerTagsEnabled: pkgconfigsetup.Datadog().GetBool("basic_telemetry_add_container_tags"), agentTags: tagger.AgentTags, globalTags: tagger.GlobalTags, + tagger: tagger, flushAndSerializeInParallel: NewFlushAndSerializeInParallel(pkgconfigsetup.Datadog()), } @@ -475,7 +476,7 @@ func (agg *BufferedAggregator) addServiceCheck(sc servicecheck.ServiceCheck) { sc.Ts = time.Now().Unix() } tb := tagset.NewHashlessTagsAccumulatorFromSlice(sc.Tags) - tagger.EnrichTags(tb, sc.OriginInfo) + agg.tagger.EnrichTags(tb, sc.OriginInfo) tb.SortUniq() sc.Tags = tb.Get() @@ -489,7 +490,7 @@ func (agg *BufferedAggregator) addEvent(e event.Event) { e.Ts = time.Now().Unix() } tb := tagset.NewHashlessTagsAccumulatorFromSlice(e.Tags) - tagger.EnrichTags(tb, e.OriginInfo) + agg.tagger.EnrichTags(tb, e.OriginInfo) tb.SortUniq() e.Tags = tb.Get() @@ -837,13 +838,13 @@ func (agg *BufferedAggregator) tags(withVersion bool) []string { var tags []string var err error - tags, err = agg.globalTags(tagger.ChecksCardinality()) + tags, err = agg.globalTags(agg.tagger.ChecksCardinality()) if err != nil { log.Debugf("Couldn't get Global tags: %v", err) } if agg.tlmContainerTagsEnabled { - agentTags, err := agg.agentTags(tagger.ChecksCardinality()) + agentTags, err := agg.agentTags(agg.tagger.ChecksCardinality()) if err == nil { if tags == nil { tags = agentTags @@ -955,5 +956,6 @@ func (agg *BufferedAggregator) handleRegisterSampler(id checkid.ID) { pkgconfigsetup.Datadog().GetDuration("check_sampler_stateful_metric_expiration_time"), agg.tagsStore, id, + agg.tagger, ) } diff --git a/pkg/aggregator/aggregator_test.go b/pkg/aggregator/aggregator_test.go index dd2920ab4f208..2b51ce784d230 100644 --- a/pkg/aggregator/aggregator_test.go +++ b/pkg/aggregator/aggregator_test.go @@ -22,13 +22,15 @@ import ( "github.com/stretchr/testify/require" "github.com/DataDog/datadog-agent/comp/core" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/comp/core/tagger/types" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" orchestratorforwarder "github.com/DataDog/datadog-agent/comp/forwarder/orchestrator" "github.com/DataDog/datadog-agent/comp/serializer/compression/compressionimpl" checkid "github.com/DataDog/datadog-agent/pkg/collector/check/id" - pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" + configmock "github.com/DataDog/datadog-agent/pkg/config/mock" "github.com/DataDog/datadog-agent/pkg/metrics" "github.com/DataDog/datadog-agent/pkg/metrics/event" "github.com/DataDog/datadog-agent/pkg/metrics/servicecheck" @@ -144,7 +146,8 @@ func TestAddServiceCheckDefaultValues(t *testing.T) { // - s := &MockSerializerIterableSerie{} - agg := NewBufferedAggregator(s, nil, "resolved-hostname", DefaultFlushInterval) + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + agg := NewBufferedAggregator(s, nil, taggerComponent, "resolved-hostname", DefaultFlushInterval) agg.addServiceCheck(servicecheck.ServiceCheck{ // leave Host and Ts fields blank @@ -176,7 +179,8 @@ func TestAddEventDefaultValues(t *testing.T) { // - s := &MockSerializerIterableSerie{} - agg := NewBufferedAggregator(s, nil, "resolved-hostname", DefaultFlushInterval) + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + agg := NewBufferedAggregator(s, nil, taggerComponent, "resolved-hostname", DefaultFlushInterval) agg.addEvent(event.Event{ // only populate required fields @@ -225,7 +229,9 @@ func TestDefaultData(t *testing.T) { // - s := &MockSerializerIterableSerie{} - agg := NewBufferedAggregator(s, nil, "hostname", DefaultFlushInterval) + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + agg := NewBufferedAggregator(s, nil, taggerComponent, "hostname", DefaultFlushInterval) + start := time.Now() // Check only the name for `datadog.agent.up` as the timestamp may not be the same. @@ -575,9 +581,12 @@ func TestTags(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - defer pkgconfigsetup.Datadog().SetWithoutSource("basic_telemetry_add_container_tags", nil) - pkgconfigsetup.Datadog().SetWithoutSource("basic_telemetry_add_container_tags", tt.tlmContainerTagsEnabled) - agg := NewBufferedAggregator(nil, nil, tt.hostname, time.Second) + mockConfig := configmock.New(t) + mockConfig.SetWithoutSource("basic_telemetry_add_container_tags", tt.tlmContainerTagsEnabled) + + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + + agg := NewBufferedAggregator(nil, nil, taggerComponent, tt.hostname, time.Second) agg.agentTags = tt.agentTags agg.globalTags = tt.globalTags assert.ElementsMatch(t, tt.want, agg.tags(tt.withVersion)) @@ -586,9 +595,8 @@ func TestTags(t *testing.T) { } func TestTimeSamplerFlush(t *testing.T) { - pc := pkgconfigsetup.Datadog().GetInt("dogstatsd_pipeline_count") - pkgconfigsetup.Datadog().SetWithoutSource("dogstatsd_pipeline_count", 1) - defer pkgconfigsetup.Datadog().SetWithoutSource("dogstatsd_pipeline_count", pc) + mockConfig := configmock.New(t) + mockConfig.SetWithoutSource("dogstatsd_pipeline_count", 1) s := &MockSerializerIterableSerie{} s.On("AreSeriesEnabled").Return(true) @@ -606,14 +614,13 @@ func TestTimeSamplerFlush(t *testing.T) { func TestAddDJMRecurrentSeries(t *testing.T) { // this test IS USING globals (recurrentSeries) // - - - djmEnabled := pkgconfigsetup.Datadog().GetBool("djm_config.enabled") - pkgconfigsetup.Datadog().SetWithoutSource("djm_config.enabled", true) - defer pkgconfigsetup.Datadog().SetWithoutSource("djm_config.enabled", djmEnabled) + mockConfig := configmock.New(t) + mockConfig.SetWithoutSource("djm_config.enabled", true) s := &MockSerializerIterableSerie{} // NewBufferedAggregator with DJM enable will create a new recurrentSeries - NewBufferedAggregator(s, nil, "hostname", DefaultFlushInterval) + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + NewBufferedAggregator(s, nil, taggerComponent, "hostname", DefaultFlushInterval) expectedRecurrentSeries := metrics.Series{&metrics.Serie{ Name: "datadog.djm.agent_host", diff --git a/pkg/aggregator/check_sampler.go b/pkg/aggregator/check_sampler.go index 0efa8238da958..8bd0b29a68a0a 100644 --- a/pkg/aggregator/check_sampler.go +++ b/pkg/aggregator/check_sampler.go @@ -9,6 +9,7 @@ import ( "math" "time" + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/pkg/aggregator/ckey" "github.com/DataDog/datadog-agent/pkg/aggregator/internal/tags" checkid "github.com/DataDog/datadog-agent/pkg/collector/check/id" @@ -33,12 +34,12 @@ type CheckSampler struct { } // newCheckSampler returns a newly initialized CheckSampler -func newCheckSampler(expirationCount int, expireMetrics bool, contextResolverMetrics bool, statefulTimeout time.Duration, cache *tags.Store, id checkid.ID) *CheckSampler { +func newCheckSampler(expirationCount int, expireMetrics bool, contextResolverMetrics bool, statefulTimeout time.Duration, cache *tags.Store, id checkid.ID, tagger tagger.Component) *CheckSampler { return &CheckSampler{ id: id, series: make([]*metrics.Serie, 0), sketches: make(metrics.SketchSeriesList, 0), - contextResolver: newCountBasedContextResolver(expirationCount, cache, string(id)), + contextResolver: newCountBasedContextResolver(expirationCount, cache, tagger, string(id)), metrics: metrics.NewCheckMetrics(expireMetrics, statefulTimeout), sketchMap: make(sketchMap), lastBucketValue: make(map[ckey.ContextKey]int64), diff --git a/pkg/aggregator/check_sampler_bench_test.go b/pkg/aggregator/check_sampler_bench_test.go index 4c731fd090390..9f001097d583c 100644 --- a/pkg/aggregator/check_sampler_bench_test.go +++ b/pkg/aggregator/check_sampler_bench_test.go @@ -13,6 +13,8 @@ import ( "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/hostname" log "github.com/DataDog/datadog-agent/comp/core/log/def" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" @@ -43,16 +45,17 @@ func benchmarkAddBucket(bucketValue int64, b *testing.B) { // For some reasons using InitAggregator[WithInterval] doesn't fix the problem, // but this do. deps := fxutil.Test[benchmarkDeps](b, core.MockBundle()) + taggerComponent := fxutil.Test[tagger.Mock](b, taggerimpl.MockModule()) forwarderOpts := forwarder.NewOptionsWithResolvers(pkgconfigsetup.Datadog(), deps.Log, resolver.NewSingleDomainResolvers(map[string][]string{"hello": {"world"}})) options := DefaultAgentDemultiplexerOptions() options.DontStartForwarders = true sharedForwarder := forwarder.NewDefaultForwarder(pkgconfigsetup.Datadog(), deps.Log, forwarderOpts) orchestratorForwarder := optional.NewOption[defaultforwarder.Forwarder](defaultforwarder.NoopForwarder{}) eventPlatformForwarder := optional.NewOptionPtr[eventplatform.Forwarder](eventplatformimpl.NewNoopEventPlatformForwarder(deps.Hostname)) - demux := InitAndStartAgentDemultiplexer(deps.Log, sharedForwarder, &orchestratorForwarder, options, eventPlatformForwarder, deps.Compressor, "hostname") + demux := InitAndStartAgentDemultiplexer(deps.Log, sharedForwarder, &orchestratorForwarder, options, eventPlatformForwarder, deps.Compressor, taggerComponent, "hostname") defer demux.Stop(true) - checkSampler := newCheckSampler(1, true, true, 1000, tags.NewStore(true, "bench"), checkid.ID("hello:world:1234")) + checkSampler := newCheckSampler(1, true, true, 1000, tags.NewStore(true, "bench"), checkid.ID("hello:world:1234"), taggerComponent) bucket := &metrics.HistogramBucket{ Name: "my.histogram", @@ -71,7 +74,8 @@ func benchmarkAddBucket(bucketValue int64, b *testing.B) { } func benchmarkAddBucketWideBounds(bucketValue int64, b *testing.B) { - checkSampler := newCheckSampler(1, true, true, 1000, tags.NewStore(true, "bench"), checkid.ID("hello:world:1234")) + taggerComponent := fxutil.Test[tagger.Mock](b, taggerimpl.MockModule()) + checkSampler := newCheckSampler(1, true, true, 1000, tags.NewStore(true, "bench"), checkid.ID("hello:world:1234"), taggerComponent) bounds := []float64{0, .0005, .001, .003, .005, .007, .01, .015, .02, .025, .03, .04, .05, .06, .07, .08, .09, .1, .5, 1, 5, 10} bucket := &metrics.HistogramBucket{ diff --git a/pkg/aggregator/check_sampler_test.go b/pkg/aggregator/check_sampler_test.go index f6a5ee08a9058..c800ea664272c 100644 --- a/pkg/aggregator/check_sampler_test.go +++ b/pkg/aggregator/check_sampler_test.go @@ -16,7 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/DataDog/datadog-agent/comp/core/tagger" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/pkg/aggregator/ckey" "github.com/DataDog/datadog-agent/pkg/aggregator/internal/tags" checkid "github.com/DataDog/datadog-agent/pkg/collector/check/id" @@ -27,12 +27,14 @@ import ( func generateContextKey(sample metrics.MetricSampleContext) ckey.ContextKey { k := ckey.NewKeyGenerator() tb := tagset.NewHashingTagsAccumulator() - sample.GetTags(tb, tb, tagger.EnrichTags) + taggerComponent := nooptagger.NewTaggerClient() + sample.GetTags(tb, tb, taggerComponent.EnrichTags) return k.Generate(sample.GetName(), sample.GetHost(), tb) } func testCheckGaugeSampling(t *testing.T, store *tags.Store) { - checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234")) + taggerComponent := nooptagger.NewTaggerClient() + checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234"), taggerComponent) mSample1 := metrics.MetricSample{ Name: "my.metric.name", @@ -95,7 +97,8 @@ func TestCheckGaugeSampling(t *testing.T) { } func testCheckRateSampling(t *testing.T, store *tags.Store) { - checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234")) + taggerComponent := nooptagger.NewTaggerClient() + checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234"), taggerComponent) mSample1 := metrics.MetricSample{ Name: "my.metric.name", @@ -148,7 +151,8 @@ func TestCheckRateSampling(t *testing.T) { } func testHistogramCountSampling(t *testing.T, store *tags.Store) { - checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234")) + taggerComponent := nooptagger.NewTaggerClient() + checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234"), taggerComponent) mSample1 := metrics.MetricSample{ Name: "my.metric.name", @@ -213,7 +217,8 @@ func TestHistogramCountSampling(t *testing.T) { } func testCheckHistogramBucketSampling(t *testing.T, store *tags.Store) { - checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234")) + taggerComponent := nooptagger.NewTaggerClient() + checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234"), taggerComponent) bucket1 := &metrics.HistogramBucket{ Name: "my.histogram", @@ -290,7 +295,8 @@ func TestCheckHistogramBucketSampling(t *testing.T) { } func testCheckHistogramBucketDontFlushFirstValue(t *testing.T, store *tags.Store) { - checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234")) + taggerComponent := nooptagger.NewTaggerClient() + checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234"), taggerComponent) bucket1 := &metrics.HistogramBucket{ Name: "my.histogram", @@ -345,7 +351,8 @@ func TestCheckHistogramBucketDontFlushFirstValue(t *testing.T) { } func testCheckHistogramBucketInfinityBucket(t *testing.T, store *tags.Store) { - checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234")) + taggerComponent := nooptagger.NewTaggerClient() + checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234"), taggerComponent) bucket1 := &metrics.HistogramBucket{ Name: "my.histogram", @@ -380,7 +387,8 @@ func TestCheckHistogramBucketInfinityBucket(t *testing.T) { } func testCheckDistribution(t *testing.T, store *tags.Store) { - checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234")) + taggerComponent := nooptagger.NewTaggerClient() + checkSampler := newCheckSampler(1, true, true, 1*time.Second, store, checkid.ID("hello:world:1234"), taggerComponent) mSample1 := metrics.MetricSample{ Name: "my.metric.name", diff --git a/pkg/aggregator/context_resolver.go b/pkg/aggregator/context_resolver.go index 79e0a051bc6db..5db6186c1b325 100644 --- a/pkg/aggregator/context_resolver.go +++ b/pkg/aggregator/context_resolver.go @@ -72,6 +72,7 @@ type contextResolver struct { bytesByMtype []uint64 dataBytesByMtype []uint64 tagsCache *tags.Store + tagger tagger.Component keyGenerator *ckey.KeyGenerator taggerBuffer *tagset.HashingTagsAccumulator metricBuffer *tagset.HashingTagsAccumulator @@ -82,7 +83,7 @@ func (cr *contextResolver) generateContextKey(metricSampleContext metrics.Metric return cr.keyGenerator.GenerateWithTags2(metricSampleContext.GetName(), metricSampleContext.GetHost(), cr.taggerBuffer, cr.metricBuffer) } -func newContextResolver(cache *tags.Store, id string) *contextResolver { +func newContextResolver(tagger tagger.Component, cache *tags.Store, id string) *contextResolver { return &contextResolver{ id: id, contextsByKey: make(map[ckey.ContextKey]resolverEntry), @@ -91,6 +92,7 @@ func newContextResolver(cache *tags.Store, id string) *contextResolver { bytesByMtype: make([]uint64, metrics.NumMetricTypes), dataBytesByMtype: make([]uint64, metrics.NumMetricTypes), tagsCache: cache, + tagger: tagger, keyGenerator: ckey.NewKeyGenerator(), taggerBuffer: tagset.NewHashingTagsAccumulator(), metricBuffer: tagset.NewHashingTagsAccumulator(), @@ -99,7 +101,7 @@ func newContextResolver(cache *tags.Store, id string) *contextResolver { // trackContext returns the contextKey associated with the context of the metricSample and tracks that context func (cr *contextResolver) trackContext(metricSampleContext metrics.MetricSampleContext, timestamp int64) ckey.ContextKey { - metricSampleContext.GetTags(cr.taggerBuffer, cr.metricBuffer, tagger.EnrichTags) // tags here are not sorted and can contain duplicates + metricSampleContext.GetTags(cr.taggerBuffer, cr.metricBuffer, cr.tagger.EnrichTags) // tags here are not sorted and can contain duplicates defer cr.taggerBuffer.Reset() defer cr.metricBuffer.Reset() @@ -219,9 +221,9 @@ type timestampContextResolver struct { counterExpireTime int64 } -func newTimestampContextResolver(cache *tags.Store, id string, contextExpireTime, counterExpireTime int64) *timestampContextResolver { +func newTimestampContextResolver(tagger tagger.Component, cache *tags.Store, id string, contextExpireTime, counterExpireTime int64) *timestampContextResolver { return ×tampContextResolver{ - resolver: newContextResolver(cache, id), + resolver: newContextResolver(tagger, cache, id), contextExpireTime: contextExpireTime, counterExpireTime: counterExpireTime, @@ -279,9 +281,9 @@ type countBasedContextResolver struct { expireCountInterval int64 } -func newCountBasedContextResolver(expireCountInterval int, cache *tags.Store, id string) *countBasedContextResolver { +func newCountBasedContextResolver(expireCountInterval int, cache *tags.Store, tagger tagger.Component, id string) *countBasedContextResolver { return &countBasedContextResolver{ - resolver: newContextResolver(cache, id), + resolver: newContextResolver(tagger, cache, id), expireCount: 0, expireCountInterval: int64(expireCountInterval), } diff --git a/pkg/aggregator/context_resolver_bench_test.go b/pkg/aggregator/context_resolver_bench_test.go index 4c07a90676c9a..a89be1f263d79 100644 --- a/pkg/aggregator/context_resolver_bench_test.go +++ b/pkg/aggregator/context_resolver_bench_test.go @@ -9,6 +9,7 @@ import ( "strconv" "testing" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/pkg/aggregator/internal/tags" "github.com/DataDog/datadog-agent/pkg/metrics" ) @@ -26,7 +27,7 @@ func benchmarkContextResolver(numContexts int, b *testing.B) { }) } cache := tags.NewStore(true, "test") - cr := newContextResolver(cache, "0") + cr := newContextResolver(nooptagger.NewTaggerClient(), cache, "0") b.ResetTimer() for n := 0; n < b.N; n++ { diff --git a/pkg/aggregator/context_resolver_test.go b/pkg/aggregator/context_resolver_test.go index 748f9b5c51bbe..6ad790c00c90e 100644 --- a/pkg/aggregator/context_resolver_test.go +++ b/pkg/aggregator/context_resolver_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/pkg/aggregator/ckey" "github.com/DataDog/datadog-agent/pkg/aggregator/internal/tags" "github.com/DataDog/datadog-agent/pkg/metrics" @@ -74,7 +75,7 @@ func testTrackContext(t *testing.T, store *tags.Store) { SampleRate: 1, } - contextResolver := newContextResolver(store, "test") + contextResolver := newContextResolver(nooptagger.NewTaggerClient(), store, "test") // Track the 2 contexts contextKey1 := contextResolver.trackContext(&mSample1, 0) @@ -138,7 +139,7 @@ func testExpireContexts(t *testing.T, store *tags.Store) { Tags: []string{"foo"}, SampleRate: 1, } - contextResolver := newTimestampContextResolver(store, "test", 2, 4) + contextResolver := newTimestampContextResolver(nooptagger.NewTaggerClient(), store, "test", 2, 4) // Track the 2 contexts contextKey1 := contextResolver.trackContext(&mSample1, 4) // expires after 6 @@ -190,7 +191,7 @@ func testCountBasedExpireContexts(t *testing.T, store *tags.Store) { mSample1 := metrics.MetricSample{Name: "my.metric.name1"} mSample2 := metrics.MetricSample{Name: "my.metric.name2"} mSample3 := metrics.MetricSample{Name: "my.metric.name3"} - contextResolver := newCountBasedContextResolver(2, store, "test") + contextResolver := newCountBasedContextResolver(2, store, nooptagger.NewTaggerClient(), "test") contextKey1 := contextResolver.trackContext(&mSample1) contextKey2 := contextResolver.trackContext(&mSample2) @@ -215,7 +216,7 @@ func TestCountBasedExpireContexts(t *testing.T) { } func testTagDeduplication(t *testing.T, store *tags.Store) { - resolver := newContextResolver(store, "test") + resolver := newContextResolver(nooptagger.NewTaggerClient(), store, "test") ckey := resolver.trackContext(&metrics.MetricSample{ Name: "foo", @@ -253,7 +254,7 @@ func (s *mockSample) GetTags(tb, mb tagset.TagsAccumulator, _ metrics.EnrichTags } func TestOriginTelemetry(t *testing.T) { - r := newContextResolver(tags.NewStore(true, "test"), "test") + r := newContextResolver(nooptagger.NewTaggerClient(), tags.NewStore(true, "test"), "test") r.trackContext(&mockSample{"foo", []string{"foo"}, []string{"ook"}}, 0) r.trackContext(&mockSample{"foo", []string{"foo"}, []string{"eek"}}, 0) r.trackContext(&mockSample{"foo", []string{"bar"}, []string{"ook"}}, 0) diff --git a/pkg/aggregator/demultiplexer_agent.go b/pkg/aggregator/demultiplexer_agent.go index 914e544e91c2b..bc2e424b33199 100644 --- a/pkg/aggregator/demultiplexer_agent.go +++ b/pkg/aggregator/demultiplexer_agent.go @@ -13,6 +13,7 @@ import ( "time" log "github.com/DataDog/datadog-agent/comp/core/log/def" + "github.com/DataDog/datadog-agent/comp/core/tagger" forwarder "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" orchestratorforwarder "github.com/DataDog/datadog-agent/comp/forwarder/orchestrator" @@ -125,8 +126,9 @@ func InitAndStartAgentDemultiplexer( options AgentDemultiplexerOptions, eventPlatformForwarder eventplatform.Component, compressor compression.Component, + tagger tagger.Component, hostname string) *AgentDemultiplexer { - demux := initAgentDemultiplexer(log, sharedForwarder, orchestratorForwarder, options, eventPlatformForwarder, compressor, hostname) + demux := initAgentDemultiplexer(log, sharedForwarder, orchestratorForwarder, options, eventPlatformForwarder, compressor, tagger, hostname) go demux.run() return demux } @@ -138,6 +140,7 @@ func initAgentDemultiplexer( options AgentDemultiplexerOptions, eventPlatformForwarder eventplatform.Component, compressor compression.Component, + tagger tagger.Component, hostname string) *AgentDemultiplexer { // prepare the multiple forwarders // ------------------------------- @@ -154,7 +157,7 @@ func initAgentDemultiplexer( // prepare the embedded aggregator // -- - agg := NewBufferedAggregator(sharedSerializer, eventPlatformForwarder, hostname, options.FlushInterval) + agg := NewBufferedAggregator(sharedSerializer, eventPlatformForwarder, tagger, hostname, options.FlushInterval) // statsd samplers // --------------- @@ -170,7 +173,7 @@ func initAgentDemultiplexer( // the sampler tagsStore := tags.NewStore(pkgconfigsetup.Datadog().GetBool("aggregator_use_tags_store"), fmt.Sprintf("timesampler #%d", i)) - statsdSampler := NewTimeSampler(TimeSamplerID(i), bucketSize, tagsStore, agg.hostname) + statsdSampler := NewTimeSampler(TimeSamplerID(i), bucketSize, tagsStore, tagger, agg.hostname) // its worker (process loop + flush/serialization mechanism) @@ -187,6 +190,7 @@ func initAgentDemultiplexer( metricSamplePool, noAggSerializer, agg.flushAndSerializeInParallel, + tagger, ) } diff --git a/pkg/aggregator/demultiplexer_agent_test.go b/pkg/aggregator/demultiplexer_agent_test.go index 3fa626b843e33..13d75d0cfaa56 100644 --- a/pkg/aggregator/demultiplexer_agent_test.go +++ b/pkg/aggregator/demultiplexer_agent_test.go @@ -13,8 +13,11 @@ import ( "time" "github.com/stretchr/testify/require" + "go.uber.org/fx" "github.com/DataDog/datadog-agent/comp/core" + "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" @@ -62,7 +65,7 @@ func TestDemuxNoAggOptionDisabled(t *testing.T) { opts := demuxTestOptions() deps := createDemultiplexerAgentTestDeps(t) - demux := initAgentDemultiplexer(deps.Log, NewForwarderTest(deps.Log), deps.OrchestratorFwd, opts, deps.EventPlatform, deps.Compressor, "") + demux := initAgentDemultiplexer(deps.Log, NewForwarderTest(deps.Log), deps.OrchestratorFwd, opts, deps.EventPlatform, deps.Compressor, deps.Tagger, "") batch := testDemuxSamples(t) @@ -84,7 +87,7 @@ func TestDemuxNoAggOptionEnabled(t *testing.T) { mockSerializer.On("AreSketchesEnabled").Return(true) opts.EnableNoAggregationPipeline = true deps := createDemultiplexerAgentTestDeps(t) - demux := initAgentDemultiplexer(deps.Log, NewForwarderTest(deps.Log), deps.OrchestratorFwd, opts, deps.EventPlatform, deps.Compressor, "") + demux := initAgentDemultiplexer(deps.Log, NewForwarderTest(deps.Log), deps.OrchestratorFwd, opts, deps.EventPlatform, deps.Compressor, deps.Tagger, "") demux.statsd.noAggStreamWorker.serializer = mockSerializer // the no agg pipeline will use our mocked serializer go demux.run() @@ -153,9 +156,12 @@ type DemultiplexerAgentTestDeps struct { OrchestratorFwd orchestratorforwarder.Component EventPlatform eventplatform.Component Compressor compression.Component + Tagger tagger.Component } func createDemultiplexerAgentTestDeps(t *testing.T) DemultiplexerAgentTestDeps { + taggerComponent := fxutil.Test[tagger.Mock](t, taggerimpl.MockModule()) + return fxutil.Test[DemultiplexerAgentTestDeps]( t, defaultforwarder.MockModule(), @@ -163,5 +169,6 @@ func createDemultiplexerAgentTestDeps(t *testing.T) DemultiplexerAgentTestDeps { orchestratorimpl.MockModule(), eventplatformimpl.MockModule(), compressionimpl.MockModule(), + fx.Provide(func() tagger.Component { return taggerComponent }), ) } diff --git a/pkg/aggregator/demultiplexer_mock.go b/pkg/aggregator/demultiplexer_mock.go index 9bdd3dec2334d..4e9f6ea5c8d11 100644 --- a/pkg/aggregator/demultiplexer_mock.go +++ b/pkg/aggregator/demultiplexer_mock.go @@ -12,6 +12,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/hostname" log "github.com/DataDog/datadog-agent/comp/core/log/def" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" @@ -32,5 +33,5 @@ type TestDeps struct { func InitAndStartAgentDemultiplexerForTest(deps TestDeps, options AgentDemultiplexerOptions, hostname string) *AgentDemultiplexer { orchestratorForwarder := optional.NewOption[defaultforwarder.Forwarder](defaultforwarder.NoopForwarder{}) eventPlatformForwarder := optional.NewOptionPtr[eventplatform.Forwarder](eventplatformimpl.NewNoopEventPlatformForwarder(deps.Hostname)) - return InitAndStartAgentDemultiplexer(deps.Log, deps.SharedForwarder, &orchestratorForwarder, options, eventPlatformForwarder, deps.Compressor, hostname) + return InitAndStartAgentDemultiplexer(deps.Log, deps.SharedForwarder, &orchestratorForwarder, options, eventPlatformForwarder, deps.Compressor, nooptagger.NewTaggerClient(), hostname) } diff --git a/pkg/aggregator/demultiplexer_serverless.go b/pkg/aggregator/demultiplexer_serverless.go index 686ce5e6c096f..fe03010e9e88b 100644 --- a/pkg/aggregator/demultiplexer_serverless.go +++ b/pkg/aggregator/demultiplexer_serverless.go @@ -12,6 +12,7 @@ import ( log "github.com/DataDog/datadog-agent/comp/core/log/def" logimpl "github.com/DataDog/datadog-agent/comp/core/log/impl" + "github.com/DataDog/datadog-agent/comp/core/tagger" forwarder "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/serializer/compression/compressionimpl" "github.com/DataDog/datadog-agent/pkg/aggregator/internal/tags" @@ -43,7 +44,7 @@ type ServerlessDemultiplexer struct { } // InitAndStartServerlessDemultiplexer creates and starts new Demultiplexer for the serverless agent. -func InitAndStartServerlessDemultiplexer(keysPerDomain map[string][]string, forwarderTimeout time.Duration) *ServerlessDemultiplexer { +func InitAndStartServerlessDemultiplexer(keysPerDomain map[string][]string, forwarderTimeout time.Duration, tagger tagger.Component) *ServerlessDemultiplexer { bufferSize := pkgconfigsetup.Datadog().GetInt("aggregator_buffer_size") logger := logimpl.NewTemporaryLoggerWithoutInit() forwarder := forwarder.NewSyncForwarder(pkgconfigsetup.Datadog(), logger, keysPerDomain, forwarderTimeout) @@ -52,7 +53,7 @@ func InitAndStartServerlessDemultiplexer(keysPerDomain map[string][]string, forw metricSamplePool := metrics.NewMetricSamplePool(MetricSamplePoolBatchSize, utils.IsTelemetryEnabled(pkgconfigsetup.Datadog())) tagsStore := tags.NewStore(pkgconfigsetup.Datadog().GetBool("aggregator_use_tags_store"), "timesampler") - statsdSampler := NewTimeSampler(TimeSamplerID(0), bucketSize, tagsStore, "") + statsdSampler := NewTimeSampler(TimeSamplerID(0), bucketSize, tagsStore, tagger, "") flushAndSerializeInParallel := NewFlushAndSerializeInParallel(pkgconfigsetup.Datadog()) statsdWorker := newTimeSamplerWorker(statsdSampler, DefaultFlushInterval, bufferSize, metricSamplePool, flushAndSerializeInParallel, tagsStore) diff --git a/pkg/aggregator/demultiplexer_test.go b/pkg/aggregator/demultiplexer_test.go index 244565ddfd428..03e668898d906 100644 --- a/pkg/aggregator/demultiplexer_test.go +++ b/pkg/aggregator/demultiplexer_test.go @@ -14,6 +14,7 @@ import ( "go.uber.org/fx" "github.com/DataDog/datadog-agent/comp/core" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" @@ -172,7 +173,7 @@ func TestDemuxFlushAggregatorToSerializer(t *testing.T) { opts := demuxTestOptions() opts.FlushInterval = time.Hour deps := createDemuxDeps(t, opts, eventplatformimpl.NewDefaultParams()) - demux := initAgentDemultiplexer(deps.Log, deps.SharedForwarder, deps.OrchestratorFwd, opts, deps.EventPlatformFwd, deps.Compressor, "") + demux := initAgentDemultiplexer(deps.Log, deps.SharedForwarder, deps.OrchestratorFwd, opts, deps.EventPlatformFwd, deps.Compressor, nooptagger.NewTaggerClient(), "") demux.Aggregator().tlmContainerTagsEnabled = false require.NotNil(demux) require.NotNil(demux.aggregator) @@ -299,7 +300,7 @@ func createDemuxDepsWithOrchestratorFwd( return aggregatorDeps{ TestDeps: deps.TestDeps, - Demultiplexer: InitAndStartAgentDemultiplexer(deps.Log, deps.SharedForwarder, deps.OrchestratorForwarder, opts, deps.Eventplatform, deps.Compressor, ""), + Demultiplexer: InitAndStartAgentDemultiplexer(deps.Log, deps.SharedForwarder, deps.OrchestratorForwarder, opts, deps.Eventplatform, deps.Compressor, nooptagger.NewTaggerClient(), ""), OrchestratorFwd: deps.OrchestratorForwarder, EventPlatformFwd: deps.Eventplatform, } diff --git a/pkg/aggregator/mocksender/mocksender.go b/pkg/aggregator/mocksender/mocksender.go index 85420860a4672..f1f9155430f8c 100644 --- a/pkg/aggregator/mocksender/mocksender.go +++ b/pkg/aggregator/mocksender/mocksender.go @@ -19,8 +19,7 @@ import ( "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" "github.com/DataDog/datadog-agent/comp/serializer/compression/compressionimpl" - //nolint:revive // TODO(AML) Fix revive linter - forwarder "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/pkg/aggregator" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" checkid "github.com/DataDog/datadog-agent/pkg/collector/check/id" @@ -40,10 +39,11 @@ func CreateDefaultDemultiplexer() *aggregator.AgentDemultiplexer { opts.FlushInterval = 1 * time.Hour opts.DontStartForwarders = true log := logimpl.NewTemporaryLoggerWithoutInit() - sharedForwarder := forwarder.NewDefaultForwarder(pkgconfigsetup.Datadog(), log, forwarder.NewOptions(pkgconfigsetup.Datadog(), log, nil)) + sharedForwarder := defaultforwarder.NewDefaultForwarder(pkgconfigsetup.Datadog(), log, defaultforwarder.NewOptions(pkgconfigsetup.Datadog(), log, nil)) orchestratorForwarder := optional.NewOption[defaultforwarder.Forwarder](defaultforwarder.NoopForwarder{}) eventPlatformForwarder := optional.NewOptionPtr[eventplatform.Forwarder](eventplatformimpl.NewNoopEventPlatformForwarder(hostnameimpl.NewHostnameService())) - return aggregator.InitAndStartAgentDemultiplexer(log, sharedForwarder, &orchestratorForwarder, opts, eventPlatformForwarder, compressionimpl.NewMockCompressor(), "") + taggerComponent := nooptagger.NewTaggerClient() + return aggregator.InitAndStartAgentDemultiplexer(log, sharedForwarder, &orchestratorForwarder, opts, eventPlatformForwarder, compressionimpl.NewMockCompressor(), taggerComponent, "") } diff --git a/pkg/aggregator/no_aggregation_stream_worker.go b/pkg/aggregator/no_aggregation_stream_worker.go index 2569067934bd1..9f2b2cb83e98e 100644 --- a/pkg/aggregator/no_aggregation_stream_worker.go +++ b/pkg/aggregator/no_aggregation_stream_worker.go @@ -50,6 +50,7 @@ type noAggregationStreamWorker struct { stopChan chan trigger hostTagProvider *HostTagProvider + tagger tagger.Component logThrottling util.SimpleThrottler } @@ -82,6 +83,7 @@ func init() { //nolint:revive // TODO(AML) Fix revive linter func newNoAggregationStreamWorker(maxMetricsPerPayload int, _ *metrics.MetricSamplePool, serializer serializer.MetricSerializer, flushConfig FlushAndSerializeInParallel, + tagger tagger.Component, ) *noAggregationStreamWorker { return &noAggregationStreamWorker{ serializer: serializer, @@ -101,6 +103,8 @@ func newNoAggregationStreamWorker(maxMetricsPerPayload int, _ *metrics.MetricSam // warning for the unsupported metric types should appear maximum 200 times // every 5 minutes. logThrottling: util.NewSimpleThrottler(200, 5*time.Minute, "Pausing the unsupported metric type warning message for 5m"), + + tagger: tagger, } } @@ -199,7 +203,7 @@ func (w *noAggregationStreamWorker) run() { } // enrich metric sample tags - sample.GetTags(w.taggerBuffer, w.metricBuffer, tagger.EnrichTags) + sample.GetTags(w.taggerBuffer, w.metricBuffer, w.tagger.EnrichTags) w.metricBuffer.AppendHashlessAccumulator(w.taggerBuffer) // if the value is a rate, we have to account for the 10s interval diff --git a/pkg/aggregator/sender_test.go b/pkg/aggregator/sender_test.go index d9617143798b9..19b6a01b74c47 100644 --- a/pkg/aggregator/sender_test.go +++ b/pkg/aggregator/sender_test.go @@ -19,6 +19,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/hostname" log "github.com/DataDog/datadog-agent/comp/core/log/def" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" @@ -57,7 +58,7 @@ func testDemux(log log.Component, hostname hostname.Component) *AgentDemultiplex opts.DontStartForwarders = true orchestratorForwarder := optional.NewOption[defaultforwarder.Forwarder](defaultforwarder.NoopForwarder{}) eventPlatformForwarder := optional.NewOptionPtr[eventplatform.Forwarder](eventplatformimpl.NewNoopEventPlatformForwarder(hostname)) - demux := initAgentDemultiplexer(log, NewForwarderTest(log), &orchestratorForwarder, opts, eventPlatformForwarder, compressionimpl.NewMockCompressor(), defaultHostname) + demux := initAgentDemultiplexer(log, NewForwarderTest(log), &orchestratorForwarder, opts, eventPlatformForwarder, compressionimpl.NewMockCompressor(), nooptagger.NewTaggerClient(), defaultHostname) return demux } diff --git a/pkg/aggregator/time_sampler.go b/pkg/aggregator/time_sampler.go index 08a4c17eda40b..677cad0bc51a3 100644 --- a/pkg/aggregator/time_sampler.go +++ b/pkg/aggregator/time_sampler.go @@ -10,6 +10,7 @@ import ( "io" "strconv" + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/pkg/aggregator/ckey" "github.com/DataDog/datadog-agent/pkg/aggregator/internal/tags" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -44,7 +45,7 @@ type TimeSampler struct { } // NewTimeSampler returns a newly initialized TimeSampler -func NewTimeSampler(id TimeSamplerID, interval int64, cache *tags.Store, hostname string) *TimeSampler { +func NewTimeSampler(id TimeSamplerID, interval int64, cache *tags.Store, tagger tagger.Component, hostname string) *TimeSampler { if interval == 0 { interval = bucketSize } @@ -57,7 +58,7 @@ func NewTimeSampler(id TimeSamplerID, interval int64, cache *tags.Store, hostnam s := &TimeSampler{ interval: interval, - contextResolver: newTimestampContextResolver(cache, idString, contextExpireTime, counterExpireTime), + contextResolver: newTimestampContextResolver(tagger, cache, idString, contextExpireTime, counterExpireTime), metricsByTimestamp: map[int64]metrics.ContextMetrics{}, sketchMap: make(sketchMap), id: id, diff --git a/pkg/aggregator/time_sampler_test.go b/pkg/aggregator/time_sampler_test.go index 42253d5f571e6..89c1db534a574 100644 --- a/pkg/aggregator/time_sampler_test.go +++ b/pkg/aggregator/time_sampler_test.go @@ -15,11 +15,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/DataDog/opentelemetry-mapping-go/pkg/quantile" + + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/pkg/aggregator/ckey" "github.com/DataDog/datadog-agent/pkg/aggregator/internal/tags" "github.com/DataDog/datadog-agent/pkg/metrics" "github.com/DataDog/datadog-agent/pkg/tagset" - "github.com/DataDog/opentelemetry-mapping-go/pkg/quantile" ) func generateSerieContextKey(serie *metrics.Serie) ckey.ContextKey { @@ -32,7 +34,7 @@ func generateSerieContextKey(serie *metrics.Serie) ckey.ContextKey { } func testTimeSampler(store *tags.Store) *TimeSampler { - sampler := NewTimeSampler(TimeSamplerID(0), 10, store, "host") + sampler := NewTimeSampler(TimeSamplerID(0), 10, store, nooptagger.NewTaggerClient(), "host") return sampler } @@ -533,7 +535,7 @@ func TestFlushMissingContext(t *testing.T) { } func benchmarkTimeSampler(b *testing.B, store *tags.Store) { - sampler := NewTimeSampler(TimeSamplerID(0), 10, store, "host") + sampler := NewTimeSampler(TimeSamplerID(0), 10, store, nooptagger.NewTaggerClient(), "host") sample := metrics.MetricSample{ Name: "my.metric.name", diff --git a/pkg/cli/subcommands/check/command.go b/pkg/cli/subcommands/check/command.go index 56f224389b455..a571f1bf03c67 100644 --- a/pkg/cli/subcommands/check/command.go +++ b/pkg/cli/subcommands/check/command.go @@ -296,7 +296,7 @@ func run( // Create the CheckScheduler, but do not attach it to // AutoDiscovery. - pkgcollector.InitCheckScheduler(collector, demultiplexer, logReceiver) + pkgcollector.InitCheckScheduler(collector, demultiplexer, logReceiver, tagger) waitCtx, cancelTimeout := context.WithTimeout( context.Background(), time.Duration(cliParams.discoveryTimeout)*time.Second) diff --git a/pkg/clusteragent/admission/controllers/webhook/controller_base.go b/pkg/clusteragent/admission/controllers/webhook/controller_base.go index 3bdda115d6e0d..bc7a8c72d44ac 100644 --- a/pkg/clusteragent/admission/controllers/webhook/controller_base.go +++ b/pkg/clusteragent/admission/controllers/webhook/controller_base.go @@ -94,7 +94,9 @@ func (c *controllerBase) generateWebhooks(wmeta workloadmeta.Component, pa workl // Note: the auto_instrumentation pod injection filter is used across // multiple mutating webhooks, so we add it as a hard dependency to each // of the components that use it via the injectionFilter parameter. - injectionFilter := autoinstrumentation.GetInjectionFilter() + // TODO: for now we ignore the error returned by NewInjectionFilter, but we should not and surface it + // in the admission controller section in agent status. + injectionFilter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) var webhooks []Webhook var validatingWebhooks []Webhook @@ -118,14 +120,14 @@ func (c *controllerBase) generateWebhooks(wmeta workloadmeta.Component, pa workl webhooks = append(webhooks, mutatingWebhooks...) // APM Instrumentation webhook needs to be registered after the configWebhook webhook. - apm, err := autoinstrumentation.NewWebhook(wmeta, injectionFilter) + apm, err := autoinstrumentation.NewWebhook(wmeta, datadogConfig, injectionFilter) if err == nil { webhooks = append(webhooks, apm) } else { log.Errorf("failed to register APM Instrumentation webhook: %v", err) } - cws, err := cwsinstrumentation.NewCWSInstrumentation(wmeta) + cws, err := cwsinstrumentation.NewCWSInstrumentation(wmeta, datadogConfig) if err == nil { webhooks = append(webhooks, cws.WebhookForPods(), cws.WebhookForCommands()) } else { diff --git a/pkg/clusteragent/admission/mutate/agent_sidecar/agent_sidecar.go b/pkg/clusteragent/admission/mutate/agent_sidecar/agent_sidecar.go index f0741c1819942..783207a15d2c8 100644 --- a/pkg/clusteragent/admission/mutate/agent_sidecar/agent_sidecar.go +++ b/pkg/clusteragent/admission/mutate/agent_sidecar/agent_sidecar.go @@ -72,7 +72,7 @@ type Webhook struct { func NewWebhook(datadogConfig config.Component) *Webhook { nsSelector, objSelector := labelSelectors(datadogConfig) - containerRegistry := mutatecommon.ContainerRegistry("admission_controller.agent_sidecar.container_registry") + containerRegistry := mutatecommon.ContainerRegistry(datadogConfig, "admission_controller.agent_sidecar.container_registry") return &Webhook{ name: webhookName, diff --git a/pkg/clusteragent/admission/mutate/autoinstrumentation/auto_instrumentation.go b/pkg/clusteragent/admission/mutate/autoinstrumentation/auto_instrumentation.go index c2fbdd7b0cbdd..7cdb660c87dae 100644 --- a/pkg/clusteragent/admission/mutate/autoinstrumentation/auto_instrumentation.go +++ b/pkg/clusteragent/admission/mutate/autoinstrumentation/auto_instrumentation.go @@ -10,7 +10,6 @@ package autoinstrumentation import ( - "encoding/json" "errors" "fmt" "os" @@ -26,11 +25,11 @@ import ( "k8s.io/client-go/dynamic" "github.com/DataDog/datadog-agent/cmd/cluster-agent/admission" + "github.com/DataDog/datadog-agent/comp/core/config" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/common" "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/metrics" mutatecommon "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common" - pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/util/kubernetes" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -39,82 +38,58 @@ const ( volumeName = "datadog-auto-instrumentation" mountPath = "/datadog-lib" - // defaultMilliCPURequest defines default milli cpu request number. - defaultMilliCPURequest int64 = 50 // 0.05 core - // defaultMemoryRequest defines default memory request size. - defaultMemoryRequest int64 = 100 * 1024 * 1024 // 100 MB (recommended minimum by Alpine) - webhookName = "lib_injection" + + // apmInjectionErrorAnnotationKey this annotation is added when the apm auto-instrumentation admission controller failed to mutate the Pod. + apmInjectionErrorAnnotationKey = "apm.datadoghq.com/injection-error" ) // Webhook is the auto instrumentation webhook type Webhook struct { - name string - isEnabled bool - endpoint string - resources []string - operations []admissionregistrationv1.OperationType - initSecurityContext *corev1.SecurityContext - initResourceRequirements corev1.ResourceRequirements - containerRegistry string - injectorImageTag string - injectionFilter mutatecommon.InjectionFilter - pinnedLibraries []libInfo - version version - wmeta workloadmeta.Component + name string + resources []string + operations []admissionregistrationv1.OperationType + + wmeta workloadmeta.Component + + // use to store all the config option from the config component to avoid costly lookups in the admission webhook hot path. + config webhookConfig + + // precomputed mutators for the security and profiling products + securityClientLibraryPodMutators []podMutator + profilingClientLibraryPodMutators []podMutator } // NewWebhook returns a new Webhook dependent on the injection filter. -func NewWebhook(wmeta workloadmeta.Component, filter mutatecommon.InjectionFilter) (*Webhook, error) { +func NewWebhook(wmeta workloadmeta.Component, datadogConfig config.Component, filter mutatecommon.InjectionFilter) (*Webhook, error) { // Note: the webhook is not functional with the filter being disabled-- // and the filter is _global_! so we need to make sure that it was // initialized as it validates the configuration itself. - if filter.NSFilter == nil { + if filter == nil { return nil, errors.New("filter required for auto_instrumentation webhook") - } else if err := filter.NSFilter.Err(); err != nil { - return nil, err - } - - initSecurityContext, err := parseInitSecurityContext() - if err != nil { - return nil, err + } else if err := filter.InitError(); err != nil { + return nil, fmt.Errorf("filter error: %w", err) } - initResourceRequirements, err := initResources() + config, err := retrieveConfig(datadogConfig, filter) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to retrieve autoinstrumentation config, err: %w", err) } - v, err := instrumentationVersion(pkgconfigsetup.Datadog().GetString("apm_config.instrumentation.version")) - if err != nil { - return nil, fmt.Errorf("invalid version for key apm_config.instrumentation.version: %w", err) - } + webhook := &Webhook{ + name: webhookName, - var ( - isEnabled = pkgconfigsetup.Datadog().GetBool("admission_controller.auto_instrumentation.enabled") - containerRegistry = mutatecommon.ContainerRegistry("admission_controller.auto_instrumentation.container_registry") - pinnedLibraries []libInfo - ) + resources: []string{"pods"}, + operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create}, + wmeta: wmeta, - if isEnabled { - pinnedLibraries = getPinnedLibraries(containerRegistry) + config: config, } - return &Webhook{ - name: webhookName, - isEnabled: isEnabled, - endpoint: pkgconfigsetup.Datadog().GetString("admission_controller.auto_instrumentation.endpoint"), - resources: []string{"pods"}, - operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create}, - initSecurityContext: initSecurityContext, - initResourceRequirements: initResourceRequirements, - injectionFilter: filter, - containerRegistry: containerRegistry, - injectorImageTag: pkgconfigsetup.Datadog().GetString("apm_config.instrumentation.injector_image_tag"), - pinnedLibraries: pinnedLibraries, - version: v, - wmeta: wmeta, - }, nil + webhook.securityClientLibraryPodMutators = securityClientLibraryConfigMutators(&webhook.config) + webhook.profilingClientLibraryPodMutators = profilingClientLibraryConfigMutators(&webhook.config) + + return webhook, nil } // Name returns the name of the webhook @@ -129,12 +104,12 @@ func (w *Webhook) WebhookType() common.WebhookType { // IsEnabled returns whether the webhook is enabled func (w *Webhook) IsEnabled() bool { - return w.isEnabled + return w.config.isEnabled } // Endpoint returns the endpoint of the webhook func (w *Webhook) Endpoint() string { - return w.endpoint + return w.config.endpoint } // Resources returns the kubernetes resources for which the webhook should @@ -162,19 +137,9 @@ func (w *Webhook) WebhookFunc() admission.WebhookFunc { } } -func initContainerName(lang language) string { - return fmt.Sprintf("datadog-lib-%s-init", lang) -} - // isPodEligible checks whether we are allowed to inject in this pod. func (w *Webhook) isPodEligible(pod *corev1.Pod) bool { - return w.injectionFilter.ShouldMutatePod(pod) -} - -// isEnabledInNamespace checks whether this namespace is opted into or out of -// single step (auto_instrumentation) outside pod-specific annotations. -func (w *Webhook) isEnabledInNamespace(namespace string) bool { - return w.injectionFilter.NSFilter.IsNamespaceEligible(namespace) + return w.config.injectionFilter.ShouldMutatePod(pod) } func (w *Webhook) inject(pod *corev1.Pod, ns string, _ dynamic.Interface) (bool, error) { @@ -204,13 +169,13 @@ func (w *Webhook) inject(pod *corev1.Pod, ns string, _ dynamic.Interface) (bool, return false, nil } - for _, mutator := range securityClientLibraryConfigMutators() { + for _, mutator := range w.securityClientLibraryPodMutators { if err := mutator.mutatePod(pod); err != nil { return false, fmt.Errorf("error mutating pod for security client: %w", err) } } - for _, mutator := range profilingClientLibraryConfigMutators() { + for _, mutator := range w.profilingClientLibraryPodMutators { if err := mutator.mutatePod(pod); err != nil { return false, fmt.Errorf("error mutating pod for profiling client: %w", err) } @@ -224,32 +189,28 @@ func (w *Webhook) inject(pod *corev1.Pod, ns string, _ dynamic.Interface) (bool, return true, nil } +func initContainerName(lang language) string { + return fmt.Sprintf("datadog-lib-%s-init", lang) +} + // The config for the security products has three states: | true | false. // This is because the products themselves have treat these cases differently: // * - product disactivated but can be activated remotely // * true - product activated, not overridable remotely // * false - product disactivated, not overridable remotely -func securityClientLibraryConfigMutators() []podMutator { - boolVal := func(key string) string { - return strconv.FormatBool(pkgconfigsetup.Datadog().GetBool(key)) - } - return []podMutator{ - configKeyEnvVarMutator{ - envKey: "DD_APPSEC_ENABLED", - configKey: "admission_controller.auto_instrumentation.asm.enabled", - getVal: boolVal, - }, - configKeyEnvVarMutator{ - envKey: "DD_IAST_ENABLED", - configKey: "admission_controller.auto_instrumentation.iast.enabled", - getVal: boolVal, - }, - configKeyEnvVarMutator{ - envKey: "DD_APPSEC_SCA_ENABLED", - configKey: "admission_controller.auto_instrumentation.asm_sca.enabled", - getVal: boolVal, - }, +func securityClientLibraryConfigMutators(config *webhookConfig) []podMutator { + var podMutators []podMutator + if config.asmEnabled != nil { + podMutators = append(podMutators, newConfigEnvVarFromBoolMutator("DD_APPSEC_ENABLED", config.asmEnabled)) + } + if config.iastEnabled != nil { + podMutators = append(podMutators, newConfigEnvVarFromBoolMutator("DD_IAST_ENABLED", config.iastEnabled)) } + if config.asmScaEnabled != nil { + podMutators = append(podMutators, newConfigEnvVarFromBoolMutator("DD_APPSEC_SCA_ENABLED", config.asmScaEnabled)) + } + + return podMutators } // The config for profiling has four states: | "auto" | "true" | "false". @@ -257,14 +218,13 @@ func securityClientLibraryConfigMutators() []podMutator { // * "true" - profiling activated unconditionally, not overridable remotely // * "false" - profiling deactivated, not overridable remotely // * "auto" - profiling activates per-process heuristically, not overridable remotely -func profilingClientLibraryConfigMutators() []podMutator { - return []podMutator{ - configKeyEnvVarMutator{ - envKey: "DD_PROFILING_ENABLED", - configKey: "admission_controller.auto_instrumentation.profiling.enabled", - getVal: pkgconfigsetup.Datadog().GetString, - }, +func profilingClientLibraryConfigMutators(config *webhookConfig) []podMutator { + var podMutators []podMutator + + if config.profilingEnabled != nil { + podMutators = append(podMutators, newConfigEnvVarFromStringlMutator("DD_PROFILING_ENABLED", config.profilingEnabled)) } + return podMutators } func injectApmTelemetryConfig(pod *corev1.Pod) { @@ -287,29 +247,6 @@ func injectApmTelemetryConfig(pod *corev1.Pod) { _ = mutatecommon.InjectEnv(pod, instrumentationInstallIDEnvVar) } -// getPinnedLibraries returns tracing libraries to inject as configured by apm_config.instrumentation.lib_versions -// given a registry. -func getPinnedLibraries(registry string) []libInfo { - // If APM Instrumentation is enabled and configuration apm_config.instrumentation.lib_versions specified, - // inject only the libraries from the configuration - singleStepLibraryVersions := pkgconfigsetup.Datadog(). - GetStringMapString("apm_config.instrumentation.lib_versions") - - var res []libInfo - for lang, version := range singleStepLibraryVersions { - l := language(lang) - if !l.isSupported() { - log.Warnf("APM Instrumentation detected configuration for unsupported language: %s. Tracing library for %s will not be injected", lang, lang) - continue - } - - log.Infof("Library version %s is specified for language %s", version, lang) - res = append(res, l.libInfo("", l.libImageName(registry, version))) - } - - return res -} - type libInfoLanguageDetection struct { libs []libInfo injectionEnabled bool @@ -354,14 +291,14 @@ func (l *libInfoLanguageDetection) containerMutator(v version) containerMutator // The languages information is available in workloadmeta-store // and attached on the pod's owner. func (w *Webhook) getLibrariesLanguageDetection(pod *corev1.Pod) *libInfoLanguageDetection { - if !pkgconfigsetup.Datadog().GetBool("language_detection.enabled") || - !pkgconfigsetup.Datadog().GetBool("language_detection.reporting.enabled") { + if !w.config.languageDetectionEnabled || + !w.config.languageDetectionReportingEnabled { return nil } return &libInfoLanguageDetection{ libs: w.getAutoDetectedLibraries(pod), - injectionEnabled: pkgconfigsetup.Datadog().GetBool("admission_controller.auto_instrumentation.inject_auto_detected_libraries"), + injectionEnabled: w.config.injectAutoDetectedLibraries, } } @@ -369,7 +306,7 @@ func (w *Webhook) getLibrariesLanguageDetection(pod *corev1.Pod) *libInfoLanguag func (w *Webhook) getAllLatestLibraries() []libInfo { var libsToInject []libInfo for _, lang := range supportedLanguages { - libsToInject = append(libsToInject, lang.defaultLibInfo(w.containerRegistry, "")) + libsToInject = append(libsToInject, lang.defaultLibInfo(w.config.containerRegistry, "")) } return libsToInject @@ -457,7 +394,7 @@ func (w *Webhook) initExtractedLibInfo(pod *corev1.Pod) extractedPodLibInfo { languageDetection *libInfoLanguageDetection ) - if w.isEnabledInNamespace(pod.Namespace) { + if w.config.injectionFilter.IsNamespaceEligible(pod.Namespace) { source = libInfoSourceSingleStepInstrumentation languageDetection = w.getLibrariesLanguageDetection(pod) } @@ -482,8 +419,8 @@ func (w *Webhook) extractLibInfo(pod *corev1.Pod) extractedPodLibInfo { // we prefer to use these and not override their behavior. // // N.B. this is empty if auto-instrumentation is disabled. - if len(w.pinnedLibraries) > 0 { - return extracted.withLibs(w.pinnedLibraries) + if len(w.config.pinnedLibraries) > 0 { + return extracted.withLibs(w.config.pinnedLibraries) } // if the language_detection injection is enabled @@ -530,7 +467,7 @@ func (w *Webhook) getAutoDetectedLibraries(pod *corev1.Pod) []libInfo { // Currently we only support deployments switch ownerKind { case "Deployment": - return getLibListFromDeploymentAnnotations(store, ownerName, pod.Namespace, w.containerRegistry) + return getLibListFromDeploymentAnnotations(store, ownerName, pod.Namespace, w.config.containerRegistry) default: log.Debugf("This ownerKind:%s is not yet supported by the process language auto-detection feature", ownerKind) return nil @@ -554,20 +491,20 @@ func (w *Webhook) extractLibrariesFromAnnotations(pod *corev1.Pod) []libInfo { for _, l := range supportedLanguages { extractLibInfo(l.customLibAnnotationExtractor()) - extractLibInfo(l.libVersionAnnotationExtractor(w.containerRegistry)) + extractLibInfo(l.libVersionAnnotationExtractor(w.config.containerRegistry)) for _, ctr := range pod.Spec.Containers { extractLibInfo(l.ctrCustomLibAnnotationExtractor(ctr.Name)) - extractLibInfo(l.ctrLibVersionAnnotationExtractor(ctr.Name, w.containerRegistry)) + extractLibInfo(l.ctrLibVersionAnnotationExtractor(ctr.Name, w.config.containerRegistry)) } } return libList } -func (w *Webhook) initContainerMutators() containerMutators { +func (w *Webhook) newContainerMutators(requirements corev1.ResourceRequirements) containerMutators { return containerMutators{ - containerResourceRequirements{w.initResourceRequirements}, - containerSecurityContext{w.initSecurityContext}, + containerResourceRequirements{requirements}, + containerSecurityContext{w.config.initSecurityContext}, } } @@ -586,14 +523,162 @@ func (w *Webhook) newInjector(startTime time.Time, pod *corev1.Pod, opts ...inje opts = append(opts, opt) } - return newInjector(startTime, w.containerRegistry, w.injectorImageTag, opts...). - podMutator(w.version) + return newInjector(startTime, w.config.containerRegistry, w.config.injectorImageTag, opts...). + podMutator(w.config.version) +} + +func initContainerIsSidecar(container *corev1.Container) bool { + return container.RestartPolicy != nil && *container.RestartPolicy == corev1.ContainerRestartPolicyAlways +} + +// podSumRessourceRequirements computes the sum of cpu/memory necessary for the whole pod. +// This is computed as max(max(initContainer resources), sum(container resources) + sum(sidecar containers)) +// for both limit and request +// https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/#resource-sharing-within-containers +func podSumRessourceRequirements(pod *corev1.Pod) corev1.ResourceRequirements { + ressourceRequirement := corev1.ResourceRequirements{ + Limits: corev1.ResourceList{}, + Requests: corev1.ResourceList{}, + } + + for _, k := range [2]corev1.ResourceName{corev1.ResourceMemory, corev1.ResourceCPU} { + // Take max(initContainer ressource) + for i := range pod.Spec.InitContainers { + c := &pod.Spec.InitContainers[i] + if initContainerIsSidecar(c) { + // This is a sidecar container, since it will run alongside the main containers + // we need to add it's resources to the main container's resources + continue + } + if limit, ok := c.Resources.Limits[k]; ok { + existing := ressourceRequirement.Limits[k] + if limit.Cmp(existing) == 1 { + ressourceRequirement.Limits[k] = limit + } + } + if request, ok := c.Resources.Requests[k]; ok { + existing := ressourceRequirement.Requests[k] + if request.Cmp(existing) == 1 { + ressourceRequirement.Requests[k] = request + } + } + } + + limitSum := resource.Quantity{} + reqSum := resource.Quantity{} + for i := range pod.Spec.Containers { + c := &pod.Spec.Containers[i] + if l, ok := c.Resources.Limits[k]; ok { + limitSum.Add(l) + } + if l, ok := c.Resources.Requests[k]; ok { + reqSum.Add(l) + } + } + for i := range pod.Spec.InitContainers { + c := &pod.Spec.InitContainers[i] + if !initContainerIsSidecar(c) { + continue + } + if l, ok := c.Resources.Limits[k]; ok { + limitSum.Add(l) + } + if l, ok := c.Resources.Requests[k]; ok { + reqSum.Add(l) + } + } + + // Take max(sum(container resources) + sum(sidecar container resources)) + existingLimit := ressourceRequirement.Limits[k] + if limitSum.Cmp(existingLimit) == 1 { + ressourceRequirement.Limits[k] = limitSum + } + + existingReq := ressourceRequirement.Requests[k] + if reqSum.Cmp(existingReq) == 1 { + ressourceRequirement.Requests[k] = reqSum + } + } + + return ressourceRequirement +} + +// initContainerResourceRequirements computes init container cpu/memory requests and limits. +// There are two cases: +// +// 1. If a resource quantity was set in config, we use it +// +// 2. If no quantity was set, we try to use as much of the resource as we can without impacting +// pod scheduling. +// Init containers are run one after another. This means that any single init container can use +// the maximum amount of the resource requested by the original pod wihtout changing how much of +// this resource is necessary. +// In particular, for the QoS Guaranteed Limits and Requests have to be equal for every container. +// which means that the max amount of request/limits that we compute is going to be equal to each other +// so our init container will also have request == limit. +// +// In the 2nd case, of we wouldn't have enough memory, we bail on injection +func initContainerResourceRequirements(pod *corev1.Pod, conf initResourceRequirementConfiguration) (requirements corev1.ResourceRequirements, skipInjection bool) { + requirements = corev1.ResourceRequirements{ + Limits: corev1.ResourceList{}, + Requests: corev1.ResourceList{}, + } + podRequirements := podSumRessourceRequirements(pod) + var shouldSkipInjection bool + for _, k := range [2]corev1.ResourceName{corev1.ResourceCPU, corev1.ResourceMemory} { + if q, ok := conf[k]; ok { + requirements.Limits[k] = q + requirements.Requests[k] = q + } else { + if maxPodLim, ok := podRequirements.Limits[k]; ok { + val, ok := maxPodLim.AsInt64() + if !ok { + log.Debugf("Unable do convert resource value to int64, raw value: %v", maxPodLim) + } + // If the pod before adding instrumentation init containers would have had a limits smaller than + // a certain amount, we just don't do anything, for two reasons: + // 1. The init containers need quite a lot of memory/CPU in order to not OOM or initialize in reasonnable time + // 2. The APM libraries themselves will increase footprint of the container by a + // non trivial amount, and we don't want to cause issues for constrained apps + switch k { + case corev1.ResourceMemory: + if val < minimumMemoryLimit { + log.Debugf("The memory limit is too low to acceptable for the datadog library init-container: %v", val) + shouldSkipInjection = true + } + case corev1.ResourceCPU: + if val < minimumCPULimit { + log.Debugf("The cpu limit is too low to acceptable for the datadog library init-container: %v", val) + shouldSkipInjection = true + } + default: + // We don't support other resources + } + requirements.Limits[k] = maxPodLim + } + if maxPodReq, ok := podRequirements.Requests[k]; ok { + requirements.Requests[k] = maxPodReq + } + } + } + if shouldSkipInjection { + return corev1.ResourceRequirements{}, shouldSkipInjection + } + return requirements, false } func (w *Webhook) injectAutoInstruConfig(pod *corev1.Pod, config extractedPodLibInfo) error { if len(config.libs) == 0 { return nil } + requirements, skipInjection := initContainerResourceRequirements(pod, w.config.defaultResourceRequirements) + if skipInjection { + if pod.Annotations == nil { + pod.Annotations = make(map[string]string) + } + pod.Annotations[apmInjectionErrorAnnotationKey] = "The overall pod's containers memory limit is too low to acceptable for the datadog library init-container" + return nil + } var ( lastError error @@ -601,12 +686,12 @@ func (w *Webhook) injectAutoInstruConfig(pod *corev1.Pod, config extractedPodLib injectionType = config.source.injectionType() autoDetected = config.source.isFromLanguageDetection() - initContainerMutators = w.initContainerMutators() + initContainerMutators = w.newContainerMutators(requirements) injector = w.newInjector(time.Now(), pod, injectorWithLibRequirementOptions(libRequirementOptions{ initContainerMutators: initContainerMutators, })) containerMutators = containerMutators{ - config.languageDetection.containerMutator(w.version), + config.languageDetection.containerMutator(w.config.version), } ) @@ -624,7 +709,7 @@ func (w *Webhook) injectAutoInstruConfig(pod *corev1.Pod, config extractedPodLib metrics.LibInjectionAttempts.Inc(langStr, strconv.FormatBool(injected), strconv.FormatBool(autoDetected), injectionType) }() - if err := lib.podMutator(w.version, libRequirementOptions{ + if err := lib.podMutator(w.config.version, libRequirementOptions{ containerMutators: containerMutators, initContainerMutators: initContainerMutators, podMutators: []podMutator{configInjector.podMutator(lib.lang), injector}, @@ -643,59 +728,13 @@ func (w *Webhook) injectAutoInstruConfig(pod *corev1.Pod, config extractedPodLib log.Errorf("Cannot inject library configuration into pod %s: %s", mutatecommon.PodString(pod), err) } - if w.isEnabledInNamespace(pod.Namespace) { + if w.config.injectionFilter.IsNamespaceEligible(pod.Namespace) { _ = basicLibConfigInjector{}.mutatePod(pod) } return lastError } -func initResources() (corev1.ResourceRequirements, error) { - - var resources = corev1.ResourceRequirements{Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{}} - - if pkgconfigsetup.Datadog().IsSet("admission_controller.auto_instrumentation.init_resources.cpu") { - quantity, err := resource.ParseQuantity(pkgconfigsetup.Datadog().GetString("admission_controller.auto_instrumentation.init_resources.cpu")) - if err != nil { - return resources, err - } - resources.Requests[corev1.ResourceCPU] = quantity - resources.Limits[corev1.ResourceCPU] = quantity - } else { - resources.Requests[corev1.ResourceCPU] = *resource.NewMilliQuantity(defaultMilliCPURequest, resource.DecimalSI) - resources.Limits[corev1.ResourceCPU] = *resource.NewMilliQuantity(defaultMilliCPURequest, resource.DecimalSI) - } - - if pkgconfigsetup.Datadog().IsSet("admission_controller.auto_instrumentation.init_resources.memory") { - quantity, err := resource.ParseQuantity(pkgconfigsetup.Datadog().GetString("admission_controller.auto_instrumentation.init_resources.memory")) - if err != nil { - return resources, err - } - resources.Requests[corev1.ResourceMemory] = quantity - resources.Limits[corev1.ResourceMemory] = quantity - } else { - resources.Requests[corev1.ResourceMemory] = *resource.NewQuantity(defaultMemoryRequest, resource.DecimalSI) - resources.Limits[corev1.ResourceMemory] = *resource.NewQuantity(defaultMemoryRequest, resource.DecimalSI) - } - - return resources, nil -} - -func parseInitSecurityContext() (*corev1.SecurityContext, error) { - securityContext := corev1.SecurityContext{} - confKey := "admission_controller.auto_instrumentation.init_security_context" - - if pkgconfigsetup.Datadog().IsSet(confKey) { - confValue := pkgconfigsetup.Datadog().GetString(confKey) - err := json.Unmarshal([]byte(confValue), &securityContext) - if err != nil { - return nil, fmt.Errorf("failed to get init security context from configuration, %s=`%s`: %v", confKey, confValue, err) - } - } - - return &securityContext, nil -} - // Returns the name of Kubernetes resource that owns the pod func getServiceNameFromPod(pod *corev1.Pod) (string, error) { ownerReferences := pod.ObjectMeta.OwnerReferences diff --git a/pkg/clusteragent/admission/mutate/autoinstrumentation/auto_instrumentation_test.go b/pkg/clusteragent/admission/mutate/autoinstrumentation/auto_instrumentation_test.go index 2e776c6c78b3b..7d964f5c112f6 100644 --- a/pkg/clusteragent/admission/mutate/autoinstrumentation/auto_instrumentation_test.go +++ b/pkg/clusteragent/admission/mutate/autoinstrumentation/auto_instrumentation_test.go @@ -16,7 +16,6 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" - "go.uber.org/fx" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -24,7 +23,7 @@ import ( "k8s.io/client-go/kubernetes/scheme" "github.com/DataDog/datadog-agent/comp/core" - configComp "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/config" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common" @@ -208,11 +207,11 @@ func TestInjectAutoInstruConfigV2(t *testing.T) { tt.config(c) } - webhook := mustWebhook(t, wmeta) - require.Equal(t, instrumentationV2, webhook.version) - require.True(t, webhook.version.usesInjector()) + webhook := mustWebhook(t, wmeta, c) + require.Equal(t, instrumentationV2, webhook.config.version) + require.True(t, webhook.config.version.usesInjector()) - webhook.initSecurityContext = tt.expectedSecurityContext + webhook.config.initSecurityContext = tt.expectedSecurityContext if tt.libInfo.source == libInfoSourceNone { tt.libInfo.source = libInfoSourceSingleStepInstrumentation @@ -562,7 +561,7 @@ func TestInjectAutoInstruConfig(t *testing.T) { c := configmock.New(t) c.SetWithoutSource("apm_config.instrumentation.version", "v1") - webhook := mustWebhook(t, wmeta) + webhook := mustWebhook(t, wmeta, c) err := webhook.injectAutoInstruConfig(tt.pod, extractedPodLibInfo{ libs: tt.libsToInject, source: libInfoSourceLibInjection, @@ -971,8 +970,6 @@ func TestExtractLibInfo(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Fix me: since comp-config and pkg-config don't work together, - // we have to set settings twice overrides := map[string]interface{}{ "admission_controller.mutate_unlabelled": true, "admission_controller.container_registry": commonRegistry, @@ -980,10 +977,13 @@ func TestExtractLibInfo(t *testing.T) { if tt.containerRegistry != "" { overrides["admission_controller.auto_instrumentation.container_registry"] = tt.containerRegistry } + mockConfig = configmock.New(t) + for k, v := range overrides { + mockConfig.SetWithoutSource(k, v) + } wmeta := fxutil.Test[workloadmeta.Component](t, core.MockBundle(), - fx.Replace(configComp.MockParams{Overrides: overrides}), workloadmetafxmock.MockModule(workloadmeta.NewParams()), ) mockConfig = configmock.New(t) @@ -995,7 +995,7 @@ func TestExtractLibInfo(t *testing.T) { tt.setupConfig() } - webhook := mustWebhook(t, wmeta) + webhook := mustWebhook(t, wmeta, mockConfig) if tt.expectedPodEligible != nil { require.Equal(t, *tt.expectedPodEligible, webhook.isPodEligible(tt.pod)) @@ -1080,29 +1080,30 @@ func TestInjectLibConfig(t *testing.T) { func TestInjectLibInitContainer(t *testing.T) { tests := []struct { - name string - cpu string - mem string - pod *corev1.Pod - image string - lang language - wantErr bool - wantCPU string - wantMem string - secCtx *corev1.SecurityContext + name string + cpu string + mem string + pod *corev1.Pod + image string + lang language + wantSkipInjection bool + wantErr bool + wantCPU string + wantMem string + secCtx *corev1.SecurityContext }{ { - name: "no resources, no security context", + name: "no_resources,no_security_context", pod: common.FakePod("java-pod"), image: "gcr.io/datadoghq/dd-lib-java-init:v1", lang: java, wantErr: false, - wantCPU: "50m", - wantMem: "100Mi", + wantCPU: "0", + wantMem: "0", secCtx: &corev1.SecurityContext{}, }, { - name: "with resources", + name: "with_resources", pod: common.FakePod("java-pod"), cpu: "100m", mem: "500", @@ -1114,46 +1115,46 @@ func TestInjectLibInitContainer(t *testing.T) { secCtx: &corev1.SecurityContext{}, }, { - name: "cpu only", + name: "cpu_only", pod: common.FakePod("java-pod"), cpu: "200m", image: "gcr.io/datadoghq/dd-lib-java-init:v1", lang: java, wantErr: false, wantCPU: "200m", - wantMem: "100Mi", + wantMem: "0", secCtx: &corev1.SecurityContext{}, }, { - name: "memory only", + name: "memory_only", pod: common.FakePod("java-pod"), mem: "512Mi", image: "gcr.io/datadoghq/dd-lib-java-init:v1", lang: java, wantErr: false, - wantCPU: "50m", + wantCPU: "0", wantMem: "512Mi", secCtx: &corev1.SecurityContext{}, }, { - name: "with invalid resources", + name: "with_invalid_resources", pod: common.FakePod("java-pod"), cpu: "foo", image: "gcr.io/datadoghq/dd-lib-java-init:v1", lang: java, wantErr: true, - wantCPU: "50m", - wantMem: "100Mi", + wantCPU: "0", + wantMem: "0", secCtx: &corev1.SecurityContext{}, }, { - name: "with full security context", + name: "with_full_security_context", pod: common.FakePod("java-pod"), image: "gcr.io/datadoghq/dd-lib-java-init:v1", lang: java, wantErr: false, - wantCPU: "50m", - wantMem: "100Mi", + wantCPU: "0", + wantMem: "0", secCtx: &corev1.SecurityContext{ Capabilities: &corev1.Capabilities{ Add: []corev1.Capability{"NET_ADMIN", "SYS_TIME"}, @@ -1185,13 +1186,13 @@ func TestInjectLibInitContainer(t *testing.T) { }, }, { - name: "with limited security context", + name: "with_limited_security_context", pod: common.FakePod("java-pod"), image: "gcr.io/datadoghq/dd-lib-java-init:v1", lang: java, wantErr: false, - wantCPU: "50m", - wantMem: "100Mi", + wantCPU: "0", + wantMem: "0", secCtx: &corev1.SecurityContext{ Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{"ALL"}, @@ -1204,6 +1205,288 @@ func TestInjectLibInitContainer(t *testing.T) { }, }, }, + { + name: "with_container_resources", + pod: common.FakePodWithResources("java-pod", corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + }), + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + wantErr: false, + wantCPU: "499", + wantMem: "101Mi", + }, + { + name: "init_container_resources", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "java-pod", + }, + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{{Name: "with_init_container_resources_init-1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + }}, {Name: "with_init_container_resources_init-2", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("501"), + corev1.ResourceMemory: resource.MustParse("99Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("501"), + corev1.ResourceMemory: resource.MustParse("99Mi"), + }, + }}}, + Containers: []corev1.Container{{Name: "c1"}}, + }, + }, + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + wantErr: false, + wantCPU: "501", + wantMem: "101Mi", + }, + { + name: "multiple_container_resources", + pod: common.FakePodWithContainer("java-pod", corev1.Container{ + Name: "c1", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + }, + }, corev1.Container{ + Name: "c2", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + }, + }), + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + wantErr: false, + wantCPU: "998", + wantMem: "202Mi", + }, + { + name: "container_and_init_container", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "java-pod", + }, + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{{Name: "i1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("501"), + corev1.ResourceMemory: resource.MustParse("99Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("501"), + corev1.ResourceMemory: resource.MustParse("99Mi"), + }, + }}}, + Containers: []corev1.Container{{Name: "c1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + }}}, + }, + }, + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + wantErr: false, + wantCPU: "501", + wantMem: "101Mi", + }, + { + name: "config_and_resources", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "java-pod", + }, + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{{Name: "i1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("501"), + corev1.ResourceMemory: resource.MustParse("99Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("501"), + corev1.ResourceMemory: resource.MustParse("99Mi"), + }, + }}}, + Containers: []corev1.Container{{Name: "c1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + }}}, + }, + }, + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + wantErr: false, + wantCPU: "501", + wantMem: "101Mi", + }, + { + name: "config_and_resources", + pod: common.FakePodWithContainer("java-pod", corev1.Container{Name: "c1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + }}), + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + cpu: "100", + mem: "256Mi", + wantErr: false, + wantCPU: "100", + wantMem: "256Mi", + }, + { + name: "low_memory_skip", + pod: common.FakePodWithContainer("java-pod", corev1.Container{Name: "c1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("50Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("50Mi"), + }, + }}), + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + wantErr: false, + wantSkipInjection: true, + }, + { + name: "low_cpu_skip", + pod: common.FakePodWithContainer("java-pod", corev1.Container{Name: "c1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("25"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("25"), + }, + }}), + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + wantErr: false, + wantSkipInjection: true, + }, + { + name: "config_override_low_limit_skip", + pod: common.FakePodWithContainer("java-pod", corev1.Container{Name: "c1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("50Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("499"), + corev1.ResourceMemory: resource.MustParse("50Mi"), + }, + }}), + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + cpu: "100", + mem: "51Mi", + wantErr: false, + wantSkipInjection: false, + wantCPU: "100", + wantMem: "51Mi", + }, + { + name: "sidecar_container", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "java-pod", + }, + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "init-container-1", + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("501"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("501"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + }, + }, { + Name: "sidecar-container-1", + RestartPolicy: pointer.Ptr(corev1.ContainerRestartPolicyAlways), + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500"), + corev1.ResourceMemory: resource.MustParse("50Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500"), + corev1.ResourceMemory: resource.MustParse("50Mi"), + }, + }, + }, + }, + Containers: []corev1.Container{{Name: "c1", Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("200"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("200"), + corev1.ResourceMemory: resource.MustParse("101Mi"), + }, + }}}, + }, + }, + image: "gcr.io/datadoghq/dd-lib-java-init:v1", + lang: java, + wantErr: false, + wantCPU: "700", + wantMem: "151Mi", + }, } for _, tt := range tests { @@ -1220,8 +1503,8 @@ func TestInjectLibInitContainer(t *testing.T) { if tt.mem != "" { conf.SetWithoutSource("admission_controller.auto_instrumentation.init_resources.memory", tt.mem) } - - wh, err := NewWebhook(wmeta, GetInjectionFilter()) + filter, _ := NewInjectionFilter(conf) + wh, err := NewWebhook(wmeta, conf, filter) if (err != nil) != tt.wantErr { t.Errorf("injectLibInitContainer() error = %v, wantErr %v", err, tt.wantErr) } @@ -1230,10 +1513,16 @@ func TestInjectLibInitContainer(t *testing.T) { } // N.B. this is a bit hacky but consistent. - wh.initSecurityContext = tt.secCtx + wh.config.initSecurityContext = tt.secCtx - c := tt.lang.libInfo("", tt.image).initContainers(wh.version)[0] - c.Mutators = wh.initContainerMutators() + c := tt.lang.libInfo("", tt.image).initContainers(wh.config.version)[0] + requirements, skipInjection := initContainerResourceRequirements(tt.pod, wh.config.defaultResourceRequirements) + require.Equal(t, tt.wantSkipInjection, skipInjection) + if tt.wantSkipInjection { + return + } + c.Mutators = wh.newContainerMutators(requirements) + initalInitContainerCount := len(tt.pod.Spec.InitContainers) err = c.mutatePod(tt.pod) if (err != nil) != tt.wantErr { t.Errorf("injectLibInitContainer() error = %v, wantErr %v", err, tt.wantErr) @@ -1242,16 +1531,17 @@ func TestInjectLibInitContainer(t *testing.T) { if err != nil { return } - require.Len(t, tt.pod.Spec.InitContainers, 1) + require.Len(t, tt.pod.Spec.InitContainers, initalInitContainerCount+1) - req := tt.pod.Spec.InitContainers[0].Resources.Requests[corev1.ResourceCPU] - lim := tt.pod.Spec.InitContainers[0].Resources.Limits[corev1.ResourceCPU] + req := tt.pod.Spec.InitContainers[initalInitContainerCount].Resources.Requests[corev1.ResourceCPU] + lim := tt.pod.Spec.InitContainers[initalInitContainerCount].Resources.Limits[corev1.ResourceCPU] wantCPUQuantity := resource.MustParse(tt.wantCPU) + t.Log(wantCPUQuantity, req) require.Zero(t, wantCPUQuantity.Cmp(req)) // Cmp returns 0 if equal require.Zero(t, wantCPUQuantity.Cmp(lim)) - req = tt.pod.Spec.InitContainers[0].Resources.Requests[corev1.ResourceMemory] - lim = tt.pod.Spec.InitContainers[0].Resources.Limits[corev1.ResourceMemory] + req = tt.pod.Spec.InitContainers[initalInitContainerCount].Resources.Requests[corev1.ResourceMemory] + lim = tt.pod.Spec.InitContainers[initalInitContainerCount].Resources.Limits[corev1.ResourceMemory] wantMemQuantity := resource.MustParse(tt.wantMem) require.Zero(t, wantMemQuantity.Cmp(req)) require.Zero(t, wantMemQuantity.Cmp(lim)) @@ -2917,7 +3207,8 @@ func TestInjectAutoInstrumentation(t *testing.T) { } } - webhook, errInitAPMInstrumentation := NewWebhook(wmeta, GetInjectionFilter()) + filter, _ := NewInjectionFilter(mockConfig) + webhook, errInitAPMInstrumentation := NewWebhook(wmeta, mockConfig, filter) if tt.wantWebhookInitErr { require.Error(t, errInitAPMInstrumentation) return @@ -2959,7 +3250,7 @@ func TestInjectAutoInstrumentation(t *testing.T) { for _, contEnv := range container.Env { for _, expectEnv := range tt.expectedEnvs { if expectEnv.Name == contEnv.Name { - require.Equal(t, expectEnv.Value, contEnv.Value) + require.Equalf(t, expectEnv.Value, contEnv.Value, "for envvar %s", expectEnv.Name) envCount++ break } @@ -3173,14 +3464,15 @@ func TestShouldInject(t *testing.T) { mockConfig = configmock.New(t) tt.setupConfig() - webhook := mustWebhook(t, wmeta) + webhook := mustWebhook(t, wmeta, mockConfig) require.Equal(t, tt.want, webhook.isPodEligible(tt.pod), "expected webhook.isPodEligible() to be %t", tt.want) }) } } -func mustWebhook(t *testing.T, wmeta workloadmeta.Component) *Webhook { - webhook, err := NewWebhook(wmeta, GetInjectionFilter()) +func mustWebhook(t *testing.T, wmeta workloadmeta.Component, ddConfig config.Component) *Webhook { + filter, _ := NewInjectionFilter(ddConfig) + webhook, err := NewWebhook(wmeta, ddConfig, filter) require.NoError(t, err) return webhook } diff --git a/pkg/clusteragent/admission/mutate/autoinstrumentation/config.go b/pkg/clusteragent/admission/mutate/autoinstrumentation/config.go new file mode 100644 index 0000000000000..b8acd7e84ca2c --- /dev/null +++ b/pkg/clusteragent/admission/mutate/autoinstrumentation/config.go @@ -0,0 +1,181 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build kubeapiserver + +package autoinstrumentation + +import ( + "encoding/json" + "fmt" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + + "github.com/DataDog/datadog-agent/comp/core/config" + mutatecommon "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common" + "github.com/DataDog/datadog-agent/pkg/util/log" +) + +const ( + minimumCPULimit int64 = 50 // 0.05 core, otherwise copying + library initialization is going to take forever + minimumMemoryLimit int64 = 100 * 1024 * 1024 // 100 MB (recommended minimum by Alpine) +) + +// webhookConfig use to store options from the config.Component for the autoinstrumentation webhook +type webhookConfig struct { + // isEnabled is the flag to enable the autoinstrumentation webhook + isEnabled bool + endpoint string + version version // autoinstrumentation logic version + + // optional features + languageDetectionEnabled bool + languageDetectionReportingEnabled bool + injectAutoDetectedLibraries bool + // keep pointers to bool to differentiate between unset and false + // for backward compatibility with the previous implementation. + // TODO: remove the pointers when the backward compatibility is not needed anymore. + asmEnabled *bool + iastEnabled *bool + asmScaEnabled *bool + profilingEnabled *string + + // configuration for the libraries init-containers to inject. + containerRegistry string + injectorImageTag string + injectionFilter mutatecommon.InjectionFilter + pinnedLibraries []libInfo + initSecurityContext *corev1.SecurityContext + defaultResourceRequirements initResourceRequirementConfiguration +} + +type initResourceRequirementConfiguration map[corev1.ResourceName]resource.Quantity + +// retrieveConfig retrieves the configuration for the autoinstrumentation webhook from the datadog config +func retrieveConfig(datadogConfig config.Component, injectionFilter mutatecommon.InjectionFilter) (webhookConfig, error) { + + webhookConfig := webhookConfig{ + isEnabled: datadogConfig.GetBool("admission_controller.auto_instrumentation.enabled"), + endpoint: datadogConfig.GetString("admission_controller.auto_instrumentation.endpoint"), + + languageDetectionEnabled: datadogConfig.GetBool("language_detection.enabled"), + languageDetectionReportingEnabled: datadogConfig.GetBool("language_detection.reporting.enabled"), + injectAutoDetectedLibraries: datadogConfig.GetBool("admission_controller.auto_instrumentation.inject_auto_detected_libraries"), + + asmEnabled: getOptionalBoolValue(datadogConfig, "admission_controller.auto_instrumentation.asm.enabled"), + iastEnabled: getOptionalBoolValue(datadogConfig, "admission_controller.auto_instrumentation.iast.enabled"), + asmScaEnabled: getOptionalBoolValue(datadogConfig, "admission_controller.auto_instrumentation.asm_sca.enabled"), + profilingEnabled: getOptionalStringValue(datadogConfig, "admission_controller.auto_instrumentation.profiling.enabled"), + + containerRegistry: mutatecommon.ContainerRegistry(datadogConfig, "admission_controller.auto_instrumentation.container_registry"), + injectorImageTag: datadogConfig.GetString("apm_config.instrumentation.injector_image_tag"), + injectionFilter: injectionFilter, + } + webhookConfig.pinnedLibraries = getPinnedLibraries(datadogConfig, webhookConfig.containerRegistry) + + var err error + if webhookConfig.version, err = instrumentationVersion(datadogConfig.GetString("apm_config.instrumentation.version")); err != nil { + return webhookConfig, fmt.Errorf("invalid version for key apm_config.instrumentation.version: %w", err) + } + + webhookConfig.initSecurityContext, err = parseInitSecurityContext(datadogConfig) + if err != nil { + return webhookConfig, fmt.Errorf("unable to parse init-container's SecurityContext from configuration: %w", err) + } + + webhookConfig.defaultResourceRequirements, err = initDefaultResources(datadogConfig) + if err != nil { + return webhookConfig, fmt.Errorf("unable to parse init-container's resources from configuration: %w", err) + } + + return webhookConfig, nil +} + +// getOptionalBoolValue returns a pointer to a bool corresponding to the config value if the key is set in the config +func getOptionalBoolValue(datadogConfig config.Component, key string) *bool { + var value *bool + if datadogConfig.IsSet(key) { + tmp := datadogConfig.GetBool(key) + value = &tmp + } + + return value +} + +// getOptionalBoolValue returns a pointer to a bool corresponding to the config value if the key is set in the config +func getOptionalStringValue(datadogConfig config.Component, key string) *string { + var value *string + if datadogConfig.IsSet(key) { + tmp := datadogConfig.GetString(key) + value = &tmp + } + + return value +} + +// getPinnedLibraries returns tracing libraries to inject as configured by apm_config.instrumentation.lib_versions +// given a registry. +func getPinnedLibraries(datadogConfig config.Component, registry string) []libInfo { + // If APM Instrumentation is enabled and configuration apm_config.instrumentation.lib_versions specified, + // inject only the libraries from the configuration + singleStepLibraryVersions := datadogConfig.GetStringMapString("apm_config.instrumentation.lib_versions") + + var res []libInfo + for lang, version := range singleStepLibraryVersions { + l := language(lang) + if !l.isSupported() { + log.Warnf("APM Instrumentation detected configuration for unsupported language: %s. Tracing library for %s will not be injected", lang, lang) + continue + } + + log.Infof("Library version %s is specified for language %s", version, lang) + res = append(res, l.libInfo("", l.libImageName(registry, version))) + } + + return res +} + +func initDefaultResources(datadogConfig config.Component) (initResourceRequirementConfiguration, error) { + + var conf = initResourceRequirementConfiguration{} + + if datadogConfig.IsSet("admission_controller.auto_instrumentation.init_resources.cpu") { + quantity, err := resource.ParseQuantity(datadogConfig.GetString("admission_controller.auto_instrumentation.init_resources.cpu")) + if err != nil { + return conf, err + } + conf[corev1.ResourceCPU] = quantity + } /* else { + conf[corev1.ResourceCPU] = *resource.NewMilliQuantity(minimumCPULimit, resource.DecimalSI) + }*/ + + if datadogConfig.IsSet("admission_controller.auto_instrumentation.init_resources.memory") { + quantity, err := resource.ParseQuantity(datadogConfig.GetString("admission_controller.auto_instrumentation.init_resources.memory")) + if err != nil { + return conf, err + } + conf[corev1.ResourceMemory] = quantity + } /*else { + conf[corev1.ResourceCPU] = *resource.NewMilliQuantity(minimumMemoryLimit, resource.DecimalSI) + }*/ + + return conf, nil +} + +func parseInitSecurityContext(datadogConfig config.Component) (*corev1.SecurityContext, error) { + securityContext := corev1.SecurityContext{} + confKey := "admission_controller.auto_instrumentation.init_security_context" + + if datadogConfig.IsSet(confKey) { + confValue := datadogConfig.GetString(confKey) + err := json.Unmarshal([]byte(confValue), &securityContext) + if err != nil { + return nil, fmt.Errorf("failed to get init security context from configuration, %s=`%s`: %v", confKey, confValue, err) + } + } + + return &securityContext, nil +} diff --git a/pkg/clusteragent/admission/mutate/autoinstrumentation/injection_filter.go b/pkg/clusteragent/admission/mutate/autoinstrumentation/injection_filter.go index de75b2b4e290e..2e605b63be77a 100644 --- a/pkg/clusteragent/admission/mutate/autoinstrumentation/injection_filter.go +++ b/pkg/clusteragent/admission/mutate/autoinstrumentation/injection_filter.go @@ -10,28 +10,33 @@ package autoinstrumentation import ( "fmt" + "github.com/DataDog/datadog-agent/comp/core/config" mutatecommon "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common" - pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/util/containers" apiServerCommon "github.com/DataDog/datadog-agent/pkg/util/kubernetes/apiserver/common" "github.com/DataDog/datadog-agent/pkg/util/log" ) -// GetNamespaceInjectionFilter is an accessor for the NamespaceInjectionFilter -func GetNamespaceInjectionFilter() mutatecommon.NamespaceInjectionFilter { - filter, err := makeAPMSSINamespaceFilter() - return &injectionFilter{filter: filter, err: err} -} - -// GetInjectionFilter constructs an injection filter using the autoinstrumentation +// NewInjectionFilter constructs an injection filter using the autoinstrumentation // GetNamespaceInjectionFilter. -func GetInjectionFilter() mutatecommon.InjectionFilter { - return mutatecommon.InjectionFilter{ - NSFilter: GetNamespaceInjectionFilter(), +func NewInjectionFilter(datadogConfig config.Component) (mutatecommon.InjectionFilter, error) { + filter, err := makeAPMSSINamespaceFilter( + datadogConfig.GetStringSlice("apm_config.instrumentation.enabled_namespaces"), + datadogConfig.GetStringSlice("apm_config.instrumentation.disabled_namespaces"), + ) + + injectionFilter := &injectionFilter{ + apmInstrumentationEnabled: datadogConfig.GetBool("apm_config.instrumentation.enabled"), + filter: filter, + + err: err, } + return mutatecommon.NewInjectionFilter(injectionFilter), err } type injectionFilter struct { + apmInstrumentationEnabled bool + filter *containers.Filter err error } @@ -45,9 +50,7 @@ type injectionFilter struct { // This DOES NOT respect `mutate_unlabelled` since it is a namespace // specific check. func (f *injectionFilter) IsNamespaceEligible(ns string) bool { - apmInstrumentationEnabled := pkgconfigsetup.Datadog().GetBool("apm_config.instrumentation.enabled") - - if !apmInstrumentationEnabled { + if !f.apmInstrumentationEnabled { log.Debugf("APM Instrumentation is disabled") return false } @@ -84,10 +87,7 @@ func (f *injectionFilter) Err() error { // namespaces that are not included in the list of disabled namespaces and that // are not one of the ones disabled by default. // - Enabled and disabled namespaces: return error. -func makeAPMSSINamespaceFilter() (*containers.Filter, error) { - apmEnabledNamespaces := pkgconfigsetup.Datadog().GetStringSlice("apm_config.instrumentation.enabled_namespaces") - apmDisabledNamespaces := pkgconfigsetup.Datadog().GetStringSlice("apm_config.instrumentation.disabled_namespaces") - +func makeAPMSSINamespaceFilter(apmEnabledNamespaces, apmDisabledNamespaces []string) (*containers.Filter, error) { if len(apmEnabledNamespaces) > 0 && len(apmDisabledNamespaces) > 0 { return nil, fmt.Errorf("apm.instrumentation.enabled_namespaces and apm.instrumentation.disabled_namespaces configuration cannot be set together") } diff --git a/pkg/clusteragent/admission/mutate/autoinstrumentation/injection_filter_test.go b/pkg/clusteragent/admission/mutate/autoinstrumentation/injection_filter_test.go index 85b0ad4a06be1..2c6b158a99858 100644 --- a/pkg/clusteragent/admission/mutate/autoinstrumentation/injection_filter_test.go +++ b/pkg/clusteragent/admission/mutate/autoinstrumentation/injection_filter_test.go @@ -10,9 +10,10 @@ package autoinstrumentation import ( "testing" + "github.com/stretchr/testify/require" + "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common" mockconfig "github.com/DataDog/datadog-agent/pkg/config/mock" - "github.com/stretchr/testify/require" ) func TestFailingInjectionConfig(t *testing.T) { @@ -87,10 +88,10 @@ func TestFailingInjectionConfig(t *testing.T) { c.SetWithoutSource("apm_config.instrumentation.enabled_namespaces", tt.enabledNamespaces) c.SetWithoutSource("apm_config.instrumentation.disabled_namespaces", tt.disabledNamespaces) - nsFilter := GetNamespaceInjectionFilter() + nsFilter, _ := NewInjectionFilter(c) require.NotNil(t, nsFilter, "we should always get a filter") - _, err := NewWebhook(wmeta, common.InjectionFilter{NSFilter: nsFilter}) + _, err := NewWebhook(wmeta, c, nsFilter) if tt.expectedWebhookError { require.Error(t, err) } else { diff --git a/pkg/clusteragent/admission/mutate/autoinstrumentation/mutators.go b/pkg/clusteragent/admission/mutate/autoinstrumentation/mutators.go index 9debc63664d05..bd9345134ebfd 100644 --- a/pkg/clusteragent/admission/mutate/autoinstrumentation/mutators.go +++ b/pkg/clusteragent/admission/mutate/autoinstrumentation/mutators.go @@ -8,10 +8,11 @@ package autoinstrumentation import ( + "strconv" + corev1 "k8s.io/api/core/v1" "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common" - pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" ) // containerMutator describes something that can mutate a container. @@ -160,16 +161,39 @@ func appendOrPrepend[T any](item T, toList []T, prepend bool) []T { } type configKeyEnvVarMutator struct { - configKey string - envKey string - getVal func(string) string + envKey string + envVal string } -func (c configKeyEnvVarMutator) mutatePod(pod *corev1.Pod) error { - if pkgconfigsetup.Datadog().IsSet(c.configKey) { - _ = common.InjectEnv(pod, corev1.EnvVar{Name: c.envKey, Value: c.getVal(c.configKey)}) +func newConfigEnvVarFromBoolMutator(key string, val *bool) configKeyEnvVarMutator { + m := configKeyEnvVarMutator{ + envKey: key, + } + + if val == nil { + m.envVal = strconv.FormatBool(false) + } else { + m.envVal = strconv.FormatBool(*val) + } + + return m +} + +func newConfigEnvVarFromStringlMutator(key string, val *string) configKeyEnvVarMutator { + m := configKeyEnvVarMutator{ + envKey: key, + } + + if val != nil { + m.envVal = *val } + return m +} + +func (c configKeyEnvVarMutator) mutatePod(pod *corev1.Pod) error { + _ = common.InjectEnv(pod, corev1.EnvVar{Name: c.envKey, Value: c.envVal}) + return nil } diff --git a/pkg/clusteragent/admission/mutate/autoinstrumentation/mutators_test.go b/pkg/clusteragent/admission/mutate/autoinstrumentation/mutators_test.go index fde28642dfeb4..eb3162ba84be5 100644 --- a/pkg/clusteragent/admission/mutate/autoinstrumentation/mutators_test.go +++ b/pkg/clusteragent/admission/mutate/autoinstrumentation/mutators_test.go @@ -10,10 +10,12 @@ package autoinstrumentation import ( "testing" - "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common" - "github.com/DataDog/datadog-agent/pkg/util/pointer" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + + "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/mutate/common" + "github.com/DataDog/datadog-agent/pkg/util/pointer" ) func TestVolumeMount(t *testing.T) { @@ -55,8 +57,16 @@ func TestVolumeMount(t *testing.T) { } func TestInitContainer(t *testing.T) { - resources, err := initResources() - require.NoError(t, err) + resources := corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("500Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("500Mi"), + }, + } c := initContainer{ Container: corev1.Container{ diff --git a/pkg/clusteragent/admission/mutate/common/common.go b/pkg/clusteragent/admission/mutate/common/common.go index 190cd18b54282..08817081b0337 100644 --- a/pkg/clusteragent/admission/mutate/common/common.go +++ b/pkg/clusteragent/admission/mutate/common/common.go @@ -19,8 +19,8 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/client-go/dynamic" + "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/metrics" - pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -180,12 +180,12 @@ func containsVolumeMount(volumeMounts []corev1.VolumeMount, element corev1.Volum // ContainerRegistry gets the container registry config using the specified // config option, and falls back to the default container registry if no // webhook-specific container registry is set. -func ContainerRegistry(specificConfigOpt string) string { - if pkgconfigsetup.Datadog().IsSet(specificConfigOpt) { - return pkgconfigsetup.Datadog().GetString(specificConfigOpt) +func ContainerRegistry(datadogConfig config.Component, specificConfigOpt string) string { + if datadogConfig.IsSet(specificConfigOpt) { + return datadogConfig.GetString(specificConfigOpt) } - return pkgconfigsetup.Datadog().GetString("admission_controller.container_registry") + return datadogConfig.GetString("admission_controller.container_registry") } // MarkVolumeAsSafeToEvictForAutoscaler adds the Kubernetes cluster-autoscaler diff --git a/pkg/clusteragent/admission/mutate/common/ns_injection_filter.go b/pkg/clusteragent/admission/mutate/common/ns_injection_filter.go index 94e05458c551c..21addd6b9d249 100644 --- a/pkg/clusteragent/admission/mutate/common/ns_injection_filter.go +++ b/pkg/clusteragent/admission/mutate/common/ns_injection_filter.go @@ -15,16 +15,32 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/log" ) -// InjectionFilter encapsulates the logic for deciding whether +// InjectionFilter is an interface to determine if a pod should be mutated. +type InjectionFilter interface { + // ShouldMutatePod checks if a pod is mutable per explicit rules and + // the NSFilter if InjectionFilter has one. + ShouldMutatePod(pod *corev1.Pod) bool + // IsNamespaceEligible returns true if a namespace is eligible for injection/mutation. + IsNamespaceEligible(ns string) bool + // InitError returns an error if the InjectionFilter failed to initialize. + InitError() error +} + +// NewInjectionFilter creates a new InjectionFilter with the given NamespaceInjectionFilter. +// the InjectionFilter encapsulates the logic for deciding whether // we can do pod mutation based on a NSFilter (NamespaceInjectionFilter). // See: InjectionFilter.ShouldMutatePod. -type InjectionFilter struct { +func NewInjectionFilter(filter NamespaceInjectionFilter) InjectionFilter { + return &injectionFilterImpl{NSFilter: filter} +} + +type injectionFilterImpl struct { NSFilter NamespaceInjectionFilter } // ShouldMutatePod checks if a pod is mutable per explicit rules and // the NSFilter if InjectionFilter has one. -func (f InjectionFilter) ShouldMutatePod(pod *corev1.Pod) bool { +func (f injectionFilterImpl) ShouldMutatePod(pod *corev1.Pod) bool { switch getPodMutationLabelFlag(pod) { case podMutationDisabled: return false @@ -39,6 +55,16 @@ func (f InjectionFilter) ShouldMutatePod(pod *corev1.Pod) bool { return pkgconfigsetup.Datadog().GetBool("admission_controller.mutate_unlabelled") } +// IsNamespaceEligible returns true if a namespace is eligible for injection/mutation. +func (f injectionFilterImpl) IsNamespaceEligible(ns string) bool { + return f.NSFilter.IsNamespaceEligible(ns) +} + +// IsNamespaceEligible returns true if a namespace is eligible for injection/mutation. +func (f injectionFilterImpl) InitError() error { + return f.NSFilter.Err() +} + type podMutationLabelFlag int const ( @@ -79,6 +105,6 @@ func getPodMutationLabelFlag(pod *corev1.Pod) podMutationLabelFlag { type NamespaceInjectionFilter interface { // IsNamespaceEligible returns true if a namespace is eligible for injection/mutation. IsNamespaceEligible(ns string) bool - // Err returns an error if creation of the NamespaceInjectionFilter failed. + // Err returns an error if the InjectionFilter failed to initialize. Err() error } diff --git a/pkg/clusteragent/admission/mutate/common/test_utils.go b/pkg/clusteragent/admission/mutate/common/test_utils.go index 94f9e579934d2..b29aa8ca36d0c 100644 --- a/pkg/clusteragent/admission/mutate/common/test_utils.go +++ b/pkg/clusteragent/admission/mutate/common/test_utils.go @@ -239,6 +239,11 @@ func FakePod(name string) *corev1.Pod { return FakePodWithContainer(name, corev1.Container{Name: name + "-container"}) } +// FakePodWithResources with resource requirements +func FakePodWithResources(name string, reqs corev1.ResourceRequirements) *corev1.Pod { + return FakePodWithContainer(name, corev1.Container{Name: name + "-container", Resources: reqs}) +} + func withContainer(pod *corev1.Pod, nameSuffix string) *corev1.Pod { pod.Spec.Containers = append(pod.Spec.Containers, corev1.Container{Name: pod.Name + nameSuffix}) return pod diff --git a/pkg/clusteragent/admission/mutate/config/config_test.go b/pkg/clusteragent/admission/mutate/config/config_test.go index e6c985cae29c9..4b481218151b1 100644 --- a/pkg/clusteragent/admission/mutate/config/config_test.go +++ b/pkg/clusteragent/admission/mutate/config/config_test.go @@ -79,7 +79,8 @@ func TestInjectHostIP(t *testing.T) { pod = mutatecommon.WithLabels(pod, map[string]string{"admission.datadoghq.com/enabled": "true"}) wmeta := fxutil.Test[workloadmeta.Component](t, core.MockBundle(), workloadmetafxmock.MockModule(workloadmeta.NewParams())) datadogConfig := fxutil.Test[config.Component](t, core.MockBundle()) - webhook := NewWebhook(wmeta, autoinstrumentation.GetInjectionFilter(), datadogConfig) + filter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) + webhook := NewWebhook(wmeta, filter, datadogConfig) injected, err := webhook.inject(pod, "", nil) assert.Nil(t, err) assert.True(t, injected) @@ -91,7 +92,8 @@ func TestInjectService(t *testing.T) { pod = mutatecommon.WithLabels(pod, map[string]string{"admission.datadoghq.com/enabled": "true", "admission.datadoghq.com/config.mode": "service"}) wmeta := fxutil.Test[workloadmeta.Component](t, core.MockBundle(), workloadmetafxmock.MockModule(workloadmeta.NewParams())) datadogConfig := fxutil.Test[config.Component](t, core.MockBundle()) - webhook := NewWebhook(wmeta, autoinstrumentation.GetInjectionFilter(), datadogConfig) + filter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) + webhook := NewWebhook(wmeta, filter, datadogConfig) injected, err := webhook.inject(pod, "", nil) assert.Nil(t, err) assert.True(t, injected) @@ -121,7 +123,8 @@ func TestInjectEntityID(t *testing.T) { fx.Replace(config.MockParams{Overrides: tt.configOverrides}), ) datadogConfig := fxutil.Test[config.Component](t, core.MockBundle()) - webhook := NewWebhook(wmeta, autoinstrumentation.GetInjectionFilter(), datadogConfig) + filter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) + webhook := NewWebhook(wmeta, filter, datadogConfig) injected, err := webhook.inject(pod, "", nil) assert.Nil(t, err) assert.True(t, injected) @@ -309,7 +312,8 @@ func TestInjectSocket(t *testing.T) { pod = mutatecommon.WithLabels(pod, map[string]string{"admission.datadoghq.com/enabled": "true", "admission.datadoghq.com/config.mode": "socket"}) wmeta := fxutil.Test[workloadmeta.Component](t, core.MockBundle(), workloadmetafxmock.MockModule(workloadmeta.NewParams())) datadogConfig := fxutil.Test[config.Component](t, core.MockBundle()) - webhook := NewWebhook(wmeta, autoinstrumentation.GetInjectionFilter(), datadogConfig) + filter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) + webhook := NewWebhook(wmeta, filter, datadogConfig) injected, err := webhook.inject(pod, "", nil) assert.Nil(t, err) assert.True(t, injected) @@ -337,7 +341,8 @@ func TestInjectSocket_VolumeTypeSocket(t *testing.T) { }), ) datadogConfig := fxutil.Test[config.Component](t, core.MockBundle()) - webhook := NewWebhook(wmeta, autoinstrumentation.GetInjectionFilter(), datadogConfig) + filter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) + webhook := NewWebhook(wmeta, filter, datadogConfig) injected, err := webhook.inject(pod, "", nil) assert.Nil(t, err) assert.True(t, injected) @@ -433,7 +438,8 @@ func TestInjectSocketWithConflictingVolumeAndInitContainer(t *testing.T) { wmeta := fxutil.Test[workloadmeta.Component](t, core.MockBundle(), workloadmetafxmock.MockModule(workloadmeta.NewParams())) datadogConfig := fxutil.Test[config.Component](t, core.MockBundle()) - webhook := NewWebhook(wmeta, autoinstrumentation.GetInjectionFilter(), datadogConfig) + filter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) + webhook := NewWebhook(wmeta, filter, datadogConfig) injected, err := webhook.inject(pod, "", nil) assert.True(t, injected) assert.Nil(t, err) @@ -473,7 +479,8 @@ func TestJSONPatchCorrectness(t *testing.T) { fx.Replace(config.MockParams{Overrides: tt.overrides}), ) datadogConfig := fxutil.Test[config.Component](t, core.MockBundle()) - webhook := NewWebhook(wmeta, autoinstrumentation.GetInjectionFilter(), datadogConfig) + filter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) + webhook := NewWebhook(wmeta, filter, datadogConfig) request := admission.Request{ Raw: podJSON, Namespace: "bar", @@ -504,7 +511,8 @@ func BenchmarkJSONPatch(b *testing.B) { wmeta := fxutil.Test[workloadmeta.Component](b, core.MockBundle()) datadogConfig := fxutil.Test[config.Component](b, core.MockBundle()) - webhook := NewWebhook(wmeta, autoinstrumentation.GetInjectionFilter(), datadogConfig) + filter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) + webhook := NewWebhook(wmeta, filter, datadogConfig) podJSON := obj.(*admiv1.AdmissionReview).Request.Object.Raw b.ResetTimer() diff --git a/pkg/clusteragent/admission/mutate/cwsinstrumentation/cws_instrumentation.go b/pkg/clusteragent/admission/mutate/cwsinstrumentation/cws_instrumentation.go index b079c12b32e2c..e965cbe7ff376 100644 --- a/pkg/clusteragent/admission/mutate/cwsinstrumentation/cws_instrumentation.go +++ b/pkg/clusteragent/admission/mutate/cwsinstrumentation/cws_instrumentation.go @@ -30,6 +30,7 @@ import ( "k8s.io/utils/strings/slices" "github.com/DataDog/datadog-agent/cmd/cluster-agent/admission" + "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/workloadmeta/collectors/util" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/clusteragent/admission/common" @@ -293,7 +294,7 @@ type CWSInstrumentation struct { } // NewCWSInstrumentation parses the webhook config and returns a new instance of CWSInstrumentation -func NewCWSInstrumentation(wmeta workloadmeta.Component) (*CWSInstrumentation, error) { +func NewCWSInstrumentation(wmeta workloadmeta.Component, datadogConfig config.Component) (*CWSInstrumentation, error) { ci := CWSInstrumentation{ wmeta: wmeta, } @@ -313,7 +314,7 @@ func NewCWSInstrumentation(wmeta workloadmeta.Component) (*CWSInstrumentation, e cwsInjectorImageName := pkgconfigsetup.Datadog().GetString("admission_controller.cws_instrumentation.image_name") cwsInjectorImageTag := pkgconfigsetup.Datadog().GetString("admission_controller.cws_instrumentation.image_tag") - cwsInjectorContainerRegistry := mutatecommon.ContainerRegistry("admission_controller.cws_instrumentation.container_registry") + cwsInjectorContainerRegistry := mutatecommon.ContainerRegistry(datadogConfig, "admission_controller.cws_instrumentation.container_registry") if len(cwsInjectorImageName) == 0 { return nil, fmt.Errorf("can't initialize CWS Instrumentation without an image_name") diff --git a/pkg/clusteragent/admission/mutate/cwsinstrumentation/cws_instrumentation_test.go b/pkg/clusteragent/admission/mutate/cwsinstrumentation/cws_instrumentation_test.go index dcaecf230eae7..fccb37527cc23 100644 --- a/pkg/clusteragent/admission/mutate/cwsinstrumentation/cws_instrumentation_test.go +++ b/pkg/clusteragent/admission/mutate/cwsinstrumentation/cws_instrumentation_test.go @@ -489,7 +489,7 @@ func Test_injectCWSCommandInstrumentation(t *testing.T) { initialCommand = strings.Join(tt.args.exec.Command, " ") } - ci, err := NewCWSInstrumentation(wmeta) + ci, err := NewCWSInstrumentation(wmeta, mockConfig) if err != nil { require.Fail(t, "couldn't instantiate CWS Instrumentation", "%v", err) } else { @@ -846,7 +846,7 @@ func Test_injectCWSPodInstrumentation(t *testing.T) { mockConfig.SetWithoutSource("admission_controller.cws_instrumentation.remote_copy.mount_volume", tt.args.cwsInjectorMountVolumeForRemoteCopy) mockConfig.SetWithoutSource("cluster_agent.service_account_name", tt.args.cwsInjectorServiceAccountName) - ci, err := NewCWSInstrumentation(wmeta) + ci, err := NewCWSInstrumentation(wmeta, mockConfig) if err != nil { require.Fail(t, "couldn't instantiate CWS Instrumentation", "%v", err) } else { diff --git a/pkg/clusteragent/admission/mutate/tagsfromlabels/tags_test.go b/pkg/clusteragent/admission/mutate/tagsfromlabels/tags_test.go index f18a990e27472..29ec9c583afbb 100644 --- a/pkg/clusteragent/admission/mutate/tagsfromlabels/tags_test.go +++ b/pkg/clusteragent/admission/mutate/tagsfromlabels/tags_test.go @@ -175,7 +175,8 @@ func Test_injectTags(t *testing.T) { datadogConfig := fxutil.Test[config.Component](t, core.MockBundle()) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - webhook := NewWebhook(wmeta, datadogConfig, autoinstrumentation.GetInjectionFilter()) + filter, _ := autoinstrumentation.NewInjectionFilter(datadogConfig) + webhook := NewWebhook(wmeta, datadogConfig, filter) _, err := webhook.injectTags(tt.pod, "ns", nil) assert.NoError(t, err) assert.Len(t, tt.pod.Spec.Containers, 1) @@ -275,8 +276,9 @@ func TestGetAndCacheOwner(t *testing.T) { kubeObj := newUnstructuredWithSpec(map[string]interface{}{"foo": "bar"}) owner := newOwner(kubeObj) wmeta := fxutil.Test[workloadmeta.Component](t, core.MockBundle(), workloadmetafxmock.MockModule(workloadmeta.NewParams())) - datadogConfig := fxutil.Test[config.Component](t, core.MockBundle()) - webhook := NewWebhook(wmeta, datadogConfig, autoinstrumentation.GetInjectionFilter()) + config := fxutil.Test[config.Component](t, core.MockBundle()) + filter, _ := autoinstrumentation.NewInjectionFilter(config) + webhook := NewWebhook(wmeta, config, filter) // Cache hit cache.Cache.Set(ownerInfo.buildID(testNamespace), owner, webhook.ownerCacheTTL) diff --git a/pkg/collector/corechecks/cluster/orchestrator/collector_bundle.go b/pkg/collector/corechecks/cluster/orchestrator/collector_bundle.go index f27aaf9adaa88..aa527ef1eb220 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/collector_bundle.go +++ b/pkg/collector/corechecks/cluster/orchestrator/collector_bundle.go @@ -66,7 +66,7 @@ func NewCollectorBundle(chk *OrchestratorCheck) *CollectorBundle { bundle := &CollectorBundle{ discoverCollectors: chk.orchestratorConfig.CollectorDiscoveryEnabled, check: chk, - inventory: inventory.NewCollectorInventory(chk.cfg, chk.wlmStore), + inventory: inventory.NewCollectorInventory(chk.cfg, chk.wlmStore, chk.tagger), runCfg: &collectors.CollectorRunConfig{ K8sCollectorRunConfig: collectors.K8sCollectorRunConfig{ APIClient: chk.apiClient, diff --git a/pkg/collector/corechecks/cluster/orchestrator/collectors/ecs/task.go b/pkg/collector/corechecks/cluster/orchestrator/collectors/ecs/task.go index d7e4f761c67cd..bff76168e2054 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/collectors/ecs/task.go +++ b/pkg/collector/corechecks/cluster/orchestrator/collectors/ecs/task.go @@ -11,6 +11,7 @@ package ecs import ( "fmt" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/collectors" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/processors" @@ -27,7 +28,7 @@ type TaskCollector struct { } // NewTaskCollector creates a new collector for the ECS Task resource. -func NewTaskCollector() *TaskCollector { +func NewTaskCollector(tagger tagger.Component) *TaskCollector { return &TaskCollector{ metadata: &collectors.CollectorMetadata{ IsStable: false, @@ -36,7 +37,7 @@ func NewTaskCollector() *TaskCollector { Name: "ecstasks", NodeType: orchestrator.ECSTask, }, - processor: processors.NewProcessor(new(ecs.TaskHandlers)), + processor: processors.NewProcessor(ecs.NewTaskHandlers(tagger)), } } diff --git a/pkg/collector/corechecks/cluster/orchestrator/collectors/inventory/inventory.go b/pkg/collector/corechecks/cluster/orchestrator/collectors/inventory/inventory.go index 8c45cf940105f..a077c1f1fb36b 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/collectors/inventory/inventory.go +++ b/pkg/collector/corechecks/cluster/orchestrator/collectors/inventory/inventory.go @@ -12,6 +12,7 @@ import ( "fmt" "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/collectors" k8sCollectors "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/collectors/k8s" @@ -24,7 +25,7 @@ type CollectorInventory struct { // NewCollectorInventory returns a new inventory containing all known // collectors. -func NewCollectorInventory(cfg config.Component, store workloadmeta.Component) *CollectorInventory { +func NewCollectorInventory(cfg config.Component, store workloadmeta.Component, tagger tagger.Component) *CollectorInventory { return &CollectorInventory{ collectors: []collectors.CollectorVersions{ k8sCollectors.NewClusterCollectorVersions(), @@ -48,7 +49,7 @@ func NewCollectorInventory(cfg config.Component, store workloadmeta.Component) * k8sCollectors.NewServiceAccountCollectorVersions(), k8sCollectors.NewStatefulSetCollectorVersions(), k8sCollectors.NewStorageClassCollectorVersions(), - k8sCollectors.NewUnassignedPodCollectorVersions(cfg, store), + k8sCollectors.NewUnassignedPodCollectorVersions(cfg, store, tagger), k8sCollectors.NewVerticalPodAutoscalerCollectorVersions(), k8sCollectors.NewHorizontalPodAutoscalerCollectorVersions(), k8sCollectors.NewNetworkPolicyCollectorVersions(), diff --git a/pkg/collector/corechecks/cluster/orchestrator/collectors/k8s/cr.go b/pkg/collector/corechecks/cluster/orchestrator/collectors/k8s/cr.go index 003968213b756..107301727fee9 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/collectors/k8s/cr.go +++ b/pkg/collector/corechecks/cluster/orchestrator/collectors/k8s/cr.go @@ -22,7 +22,7 @@ import ( ) const ( - defaultMaximumCRDQuota = 10000 + defaultMaximumCRDQuota = 5000 ) // NewCRCollectorVersion builds the group of collector versions. diff --git a/pkg/collector/corechecks/cluster/orchestrator/collectors/k8s/pod_unassigned.go b/pkg/collector/corechecks/cluster/orchestrator/collectors/k8s/pod_unassigned.go index 98220268d68bf..6c5bbb321b60f 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/collectors/k8s/pod_unassigned.go +++ b/pkg/collector/corechecks/cluster/orchestrator/collectors/k8s/pod_unassigned.go @@ -9,6 +9,7 @@ package k8s import ( "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/collectors" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/processors" @@ -22,9 +23,9 @@ import ( ) // NewUnassignedPodCollectorVersions builds the group of collector versions. -func NewUnassignedPodCollectorVersions(cfg config.Component, store workloadmeta.Component) collectors.CollectorVersions { +func NewUnassignedPodCollectorVersions(cfg config.Component, store workloadmeta.Component, tagger tagger.Component) collectors.CollectorVersions { return collectors.NewCollectorVersions( - NewUnassignedPodCollector(cfg, store), + NewUnassignedPodCollector(cfg, store, tagger), ) } @@ -39,7 +40,7 @@ type UnassignedPodCollector struct { // NewUnassignedPodCollector creates a new collector for the Kubernetes Pod // resource that is not assigned to any node. -func NewUnassignedPodCollector(cfg config.Component, store workloadmeta.Component) *UnassignedPodCollector { +func NewUnassignedPodCollector(cfg config.Component, store workloadmeta.Component, tagger tagger.Component) *UnassignedPodCollector { return &UnassignedPodCollector{ metadata: &collectors.CollectorMetadata{ IsDefaultVersion: true, @@ -51,7 +52,7 @@ func NewUnassignedPodCollector(cfg config.Component, store workloadmeta.Componen NodeType: orchestrator.K8sPod, Version: "v1", }, - processor: processors.NewProcessor(k8sProcessors.NewPodHandlers(cfg, store)), + processor: processors.NewProcessor(k8sProcessors.NewPodHandlers(cfg, store, tagger)), } } diff --git a/pkg/collector/corechecks/cluster/orchestrator/discovery/collector_discovery_test.go b/pkg/collector/corechecks/cluster/orchestrator/discovery/collector_discovery_test.go index 3b95d12e01f5b..99dabadf1a215 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/discovery/collector_discovery_test.go +++ b/pkg/collector/corechecks/cluster/orchestrator/discovery/collector_discovery_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/DataDog/datadog-agent/comp/core" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" workloadmetamock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/mock" @@ -32,7 +33,9 @@ func TestWalkAPIResources(t *testing.T) { workloadmetafxmock.MockModule(workloadmeta.NewParams()), )) - inventory := inventory.NewCollectorInventory(cfg, mockStore) + fakeTagger := taggerimpl.SetupFakeTagger(t) + + inventory := inventory.NewCollectorInventory(cfg, mockStore, fakeTagger) provider := NewAPIServerDiscoveryProvider() preferredResources := []*v1.APIResourceList{ diff --git a/pkg/collector/corechecks/cluster/orchestrator/manifest_buffer_test.go b/pkg/collector/corechecks/cluster/orchestrator/manifest_buffer_test.go index 24d6f80b2e4ba..e4b8941f24808 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/manifest_buffer_test.go +++ b/pkg/collector/corechecks/cluster/orchestrator/manifest_buffer_test.go @@ -20,6 +20,7 @@ import ( model "github.com/DataDog/agent-payload/v5/process" "github.com/DataDog/datadog-agent/comp/core" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" workloadmetamock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/mock" @@ -108,7 +109,9 @@ func getManifestBuffer(t *testing.T) *ManifestBuffer { workloadmetafxmock.MockModule(workloadmeta.NewParams()), )) - orchCheck := newCheck(cfg, mockStore).(*OrchestratorCheck) + fakeTagger := taggerimpl.SetupFakeTagger(t) + + orchCheck := newCheck(cfg, mockStore, fakeTagger).(*OrchestratorCheck) mb := NewManifestBuffer(orchCheck) mb.Cfg.MaxBufferedManifests = 2 mb.Cfg.ManifestBufferFlushInterval = 3 * time.Second diff --git a/pkg/collector/corechecks/cluster/orchestrator/orchestrator.go b/pkg/collector/corechecks/cluster/orchestrator/orchestrator.go index 1bad3b2c21634..f557174398836 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/orchestrator.go +++ b/pkg/collector/corechecks/cluster/orchestrator/orchestrator.go @@ -16,6 +16,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" configcomp "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -78,6 +79,7 @@ type OrchestratorCheck struct { collectorBundle *CollectorBundle wlmStore workloadmeta.Component cfg configcomp.Component + tagger tagger.Component stopCh chan struct{} clusterID string groupID *atomic.Int32 @@ -86,12 +88,13 @@ type OrchestratorCheck struct { orchestratorInformerFactory *collectors.OrchestratorInformerFactory } -func newOrchestratorCheck(base core.CheckBase, instance *OrchestratorInstance, cfg configcomp.Component, wlmStore workloadmeta.Component) *OrchestratorCheck { +func newOrchestratorCheck(base core.CheckBase, instance *OrchestratorInstance, cfg configcomp.Component, wlmStore workloadmeta.Component, tagger tagger.Component) *OrchestratorCheck { return &OrchestratorCheck{ CheckBase: base, orchestratorConfig: orchcfg.NewDefaultOrchestratorConfig(), instance: instance, wlmStore: wlmStore, + tagger: tagger, cfg: cfg, stopCh: make(chan struct{}), groupID: atomic.NewInt32(rand.Int31()), @@ -100,16 +103,17 @@ func newOrchestratorCheck(base core.CheckBase, instance *OrchestratorInstance, c } // Factory creates a new check factory -func Factory(wlm workloadmeta.Component, cfg configcomp.Component) optional.Option[func() check.Check] { - return optional.NewOption(func() check.Check { return newCheck(cfg, wlm) }) +func Factory(wlm workloadmeta.Component, cfg configcomp.Component, tagger tagger.Component) optional.Option[func() check.Check] { + return optional.NewOption(func() check.Check { return newCheck(cfg, wlm, tagger) }) } -func newCheck(cfg configcomp.Component, wlm workloadmeta.Component) check.Check { +func newCheck(cfg configcomp.Component, wlm workloadmeta.Component, tagger tagger.Component) check.Check { return newOrchestratorCheck( core.NewCheckBase(CheckName), &OrchestratorInstance{}, cfg, wlm, + tagger, ) } diff --git a/pkg/collector/corechecks/cluster/orchestrator/orchestrator_test.go b/pkg/collector/corechecks/cluster/orchestrator/orchestrator_test.go index 3ba183bd8c7c0..9bb9340e5046f 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/orchestrator_test.go +++ b/pkg/collector/corechecks/cluster/orchestrator/orchestrator_test.go @@ -16,6 +16,7 @@ import ( "go.uber.org/fx" "github.com/DataDog/datadog-agent/comp/core" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" workloadmetamock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/mock" @@ -42,10 +43,12 @@ func newCollectorBundle(t *testing.T, chk *OrchestratorCheck) *CollectorBundle { workloadmetafxmock.MockModule(workloadmeta.NewParams()), )) + fakeTagger := taggerimpl.SetupFakeTagger(t) + bundle := &CollectorBundle{ discoverCollectors: chk.orchestratorConfig.CollectorDiscoveryEnabled, check: chk, - inventory: inventory.NewCollectorInventory(cfg, mockStore), + inventory: inventory.NewCollectorInventory(cfg, mockStore, fakeTagger), runCfg: &collectors.CollectorRunConfig{ K8sCollectorRunConfig: collectors.K8sCollectorRunConfig{ APIClient: chk.apiClient, @@ -79,7 +82,9 @@ func TestOrchestratorCheckSafeReSchedule(t *testing.T) { workloadmetafxmock.MockModule(workloadmeta.NewParams()), )) - orchCheck := newCheck(cfg, mockStore).(*OrchestratorCheck) + fakeTagger := taggerimpl.SetupFakeTagger(t) + + orchCheck := newCheck(cfg, mockStore, fakeTagger).(*OrchestratorCheck) orchCheck.apiClient = cl orchCheck.orchestratorInformerFactory = getOrchestratorInformerFactory(cl) diff --git a/pkg/collector/corechecks/cluster/orchestrator/processors/ecs/task.go b/pkg/collector/corechecks/cluster/orchestrator/processors/ecs/task.go index 7f45e5329b716..c5131f61d7cf8 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/processors/ecs/task.go +++ b/pkg/collector/corechecks/cluster/orchestrator/processors/ecs/task.go @@ -12,6 +12,8 @@ import ( "k8s.io/apimachinery/pkg/types" model "github.com/DataDog/agent-payload/v5/process" + + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/processors" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/processors/common" transformers "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs" @@ -20,6 +22,14 @@ import ( // TaskHandlers implements the Handlers interface for ECS Tasks. type TaskHandlers struct { common.BaseHandlers + tagger tagger.Component +} + +// NewTaskHandlers returns a new TaskHandlers. +func NewTaskHandlers(tagger tagger.Component) *TaskHandlers { + return &TaskHandlers{ + tagger: tagger, + } } // BuildMessageBody is a handler called to build a message body out of a list of extracted resources. @@ -50,7 +60,7 @@ func (t *TaskHandlers) BuildMessageBody(ctx processors.ProcessorContext, resourc //nolint:revive // TODO(CAPP) Fix revive linter func (t *TaskHandlers) ExtractResource(ctx processors.ProcessorContext, resource interface{}) (resourceModel interface{}) { r := resource.(transformers.TaskWithContainers) - return transformers.ExtractECSTask(r) + return transformers.ExtractECSTask(r, t.tagger) } // ResourceList is a handler called to convert a list passed as a generic diff --git a/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod.go b/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod.go index 7985fcfd6151e..645aba5787c98 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod.go +++ b/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod.go @@ -14,6 +14,7 @@ import ( model "github.com/DataDog/agent-payload/v5/process" "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/tags" taggertypes "github.com/DataDog/datadog-agent/comp/core/tagger/types" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" @@ -37,11 +38,11 @@ type PodHandlers struct { } // NewPodHandlers creates and returns a new PodHanlders object -func NewPodHandlers(cfg config.Component, store workloadmeta.Component) *PodHandlers { +func NewPodHandlers(cfg config.Component, store workloadmeta.Component, tagger tagger.Component) *PodHandlers { podHandlers := new(PodHandlers) // initialise tag provider - podHandlers.tagProvider = podtagprovider.NewPodTagProvider(cfg, store) + podHandlers.tagProvider = podtagprovider.NewPodTagProvider(cfg, store, tagger) return podHandlers } diff --git a/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod_tag_provider/node_provider.go b/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod_tag_provider/node_provider.go index 9235a7e02de58..0c80fe420a317 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod_tag_provider/node_provider.go +++ b/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod_tag_provider/node_provider.go @@ -14,11 +14,17 @@ import ( taggertypes "github.com/DataDog/datadog-agent/comp/core/tagger/types" ) -type nodePodTagProvider struct{} +type nodePodTagProvider struct { + tagger tagger.Component +} -func newNodePodTagProvider() PodTagProvider { return &nodePodTagProvider{} } +func newNodePodTagProvider(tagger tagger.Component) PodTagProvider { + return &nodePodTagProvider{ + tagger: tagger, + } +} // GetTags implements PodTagProvider#GetTags func (p *nodePodTagProvider) GetTags(pod *corev1.Pod, cardinality taggertypes.TagCardinality) ([]string, error) { - return tagger.Tag(taggertypes.NewEntityID(taggertypes.KubernetesPodUID, string(pod.UID)), cardinality) + return p.tagger.Tag(taggertypes.NewEntityID(taggertypes.KubernetesPodUID, string(pod.UID)), cardinality) } diff --git a/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod_tag_provider/provider.go b/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod_tag_provider/provider.go index 3665cdcee470f..11d4465c578ba 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod_tag_provider/provider.go +++ b/pkg/collector/corechecks/cluster/orchestrator/processors/k8s/pod_tag_provider/provider.go @@ -10,6 +10,7 @@ package podtagprovider import ( "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" taggertypes "github.com/DataDog/datadog-agent/comp/core/tagger/types" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -25,12 +26,12 @@ type PodTagProvider interface { // NewPodTagProvider returns a new PodTagProvider // In case of CLC runner, the provider will calculate tags based on the pod resource on demand each time // In case of Node agent or Cluster agent, the provider will get pod tags by querying the tagger -func NewPodTagProvider(cfg config.Component, store workloadmeta.Component) PodTagProvider { +func NewPodTagProvider(cfg config.Component, store workloadmeta.Component, tagger tagger.Component) PodTagProvider { if pkgconfigsetup.IsCLCRunner(pkgconfigsetup.Datadog()) { // Running in a CLC Runner return newCLCTagProvider(cfg, store) } // Running in the Node Agent or in the Cluster Agent - return newNodePodTagProvider() + return newNodePodTagProvider(tagger) } diff --git a/pkg/collector/corechecks/cluster/orchestrator/processors/processor.go b/pkg/collector/corechecks/cluster/orchestrator/processors/processor.go index 6b7995eaeaded..bd53e21cb7df5 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/processors/processor.go +++ b/pkg/collector/corechecks/cluster/orchestrator/processors/processor.go @@ -12,6 +12,7 @@ import ( "k8s.io/apimachinery/pkg/types" model "github.com/DataDog/agent-payload/v5/process" + "github.com/DataDog/datadog-agent/pkg/orchestrator" "github.com/DataDog/datadog-agent/pkg/orchestrator/config" pkgorchestratormodel "github.com/DataDog/datadog-agent/pkg/orchestrator/model" diff --git a/pkg/collector/corechecks/cluster/orchestrator/stub.go b/pkg/collector/corechecks/cluster/orchestrator/stub.go index a69ee03910eba..b2c0226f8a47c 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/stub.go +++ b/pkg/collector/corechecks/cluster/orchestrator/stub.go @@ -10,6 +10,7 @@ package orchestrator import ( configcomp "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -21,6 +22,6 @@ const ( ) // Factory creates a new check factory -func Factory(_ workloadmeta.Component, _ configcomp.Component) optional.Option[func() check.Check] { +func Factory(workloadmeta.Component, configcomp.Component, tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs/task.go b/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs/task.go index 4f01d045b3514..3b8bd25a28df6 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs/task.go +++ b/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs/task.go @@ -35,7 +35,7 @@ type TaskWithContainers struct { } // ExtractECSTask returns the protobuf model corresponding to an ECS Task resource. -func ExtractECSTask(task TaskWithContainers) *model.ECSTask { +func ExtractECSTask(task TaskWithContainers, tagger tagger.Component) *model.ECSTask { if task.Task == nil { return nil } diff --git a/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs/task_test.go b/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs/task_test.go index da8c80740d59e..aac8f01a64e24 100644 --- a/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs/task_test.go +++ b/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs/task_test.go @@ -15,6 +15,7 @@ import ( model "github.com/DataDog/agent-payload/v5/process" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/util/pointer" ) @@ -22,6 +23,8 @@ import ( func TestExtractECSTask(t *testing.T) { now := time.Date(2024, 1, 1, 11, 1, 1, 1, time.UTC) + fakeTagger := taggerimpl.SetupFakeTagger(t) + actual := ExtractECSTask(TaskWithContainers{ Task: &workloadmeta.ECSTask{ EntityID: workloadmeta.EntityID{ @@ -125,7 +128,9 @@ func TestExtractECSTask(t *testing.T) { }, }, }, - }) + }, + fakeTagger, + ) expected := &model.ECSTask{ Arn: "arn:aws:ecs:us-east-1:123456789012:task/12345678-1234-1234-1234-123456789012", diff --git a/pkg/collector/corechecks/containerimage/check.go b/pkg/collector/corechecks/containerimage/check.go index 791373763743e..7479ebd236fbb 100644 --- a/pkg/collector/corechecks/containerimage/check.go +++ b/pkg/collector/corechecks/containerimage/check.go @@ -13,6 +13,7 @@ import ( "gopkg.in/yaml.v2" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -87,19 +88,21 @@ func (c *Config) Parse(data []byte) error { type Check struct { core.CheckBase workloadmetaStore workloadmeta.Component + tagger tagger.Component instance *Config processor *processor stopCh chan struct{} } // Factory returns a new check factory -func Factory(store workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(store workloadmeta.Component, tagger tagger.Component) optional.Option[func() check.Check] { return optional.NewOption(func() check.Check { return core.NewLongRunningCheckWrapper(&Check{ CheckBase: core.NewCheckBase(CheckName), workloadmetaStore: store, instance: &Config{}, stopCh: make(chan struct{}), + tagger: tagger, }) }) } @@ -123,7 +126,7 @@ func (c *Check) Configure(senderManager sender.SenderManager, _ uint64, config, return err } - c.processor = newProcessor(sender, c.instance.ChunkSize, time.Duration(c.instance.NewImagesMaxLatencySeconds)*time.Second) + c.processor = newProcessor(sender, c.instance.ChunkSize, time.Duration(c.instance.NewImagesMaxLatencySeconds)*time.Second, c.tagger) return nil } diff --git a/pkg/collector/corechecks/containerimage/processor.go b/pkg/collector/corechecks/containerimage/processor.go index c9dcea2cefaeb..8998bc5435b7f 100644 --- a/pkg/collector/corechecks/containerimage/processor.go +++ b/pkg/collector/corechecks/containerimage/processor.go @@ -29,16 +29,18 @@ import ( var sourceAgent = "agent" type processor struct { - queue chan *model.ContainerImage + queue chan *model.ContainerImage + tagger tagger.Component } -func newProcessor(sender sender.Sender, maxNbItem int, maxRetentionTime time.Duration) *processor { +func newProcessor(sender sender.Sender, maxNbItem int, maxRetentionTime time.Duration, tagger tagger.Component) *processor { hname, err := hostname.Get(context.TODO()) if err != nil { log.Warnf("Error getting hostname: %v", err) } return &processor{ + tagger: tagger, queue: queue.NewQueue(maxNbItem, maxRetentionTime, func(images []*model.ContainerImage) { encoded, err := proto.Marshal(&model.ContainerImagePayload{ Version: "v1", @@ -75,7 +77,7 @@ func (p *processor) processRefresh(allImages []*workloadmeta.ContainerImageMetad func (p *processor) processImage(img *workloadmeta.ContainerImageMetadata) { entityID := types.NewEntityID(types.ContainerImageMetadata, img.ID) - ddTags, err := tagger.Tag(entityID, types.HighCardinality) + ddTags, err := p.tagger.Tag(entityID, types.HighCardinality) if err != nil { log.Errorf("Could not retrieve tags for container image %s: %v", img.ID, err) } diff --git a/pkg/collector/corechecks/containerimage/processor_test.go b/pkg/collector/corechecks/containerimage/processor_test.go index 7d0e359281428..669c17d7d0884 100644 --- a/pkg/collector/corechecks/containerimage/processor_test.go +++ b/pkg/collector/corechecks/containerimage/processor_test.go @@ -18,6 +18,7 @@ import ( "go.uber.org/atomic" "google.golang.org/protobuf/proto" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" @@ -26,6 +27,8 @@ import ( ) func TestProcessEvents(t *testing.T) { + fakeTagger := taggerimpl.SetupFakeTagger(t) + tests := []struct { name string inputEvents []workloadmeta.Event @@ -422,7 +425,7 @@ func TestProcessEvents(t *testing.T) { // Define a max size of 1 for the queue. With a size > 1, it's difficult to // control the number of events sent on each call. - p := newProcessor(sender, 1, 50*time.Millisecond) + p := newProcessor(sender, 1, 50*time.Millisecond, fakeTagger) p.processEvents(workloadmeta.EventBundle{ Events: test.inputEvents, diff --git a/pkg/collector/corechecks/containers/containerd/check.go b/pkg/collector/corechecks/containers/containerd/check.go index 7be48e75b7168..1c24fa3cdf650 100644 --- a/pkg/collector/corechecks/containers/containerd/check.go +++ b/pkg/collector/corechecks/containers/containerd/check.go @@ -19,6 +19,7 @@ import ( "gopkg.in/yaml.v2" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -52,6 +53,7 @@ type ContainerdCheck struct { client cutil.ContainerdItf httpClient http.Client store workloadmeta.Component + tagger tagger.Component } // ContainerdConfig contains the custom options and configurations set by the user. @@ -62,12 +64,13 @@ type ContainerdConfig struct { } // Factory is used to create register the check and initialize it. -func Factory(store workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(store workloadmeta.Component, tagger tagger.Component) optional.Option[func() check.Check] { return optional.NewOption(func() check.Check { return &ContainerdCheck{ CheckBase: corechecks.NewCheckBase(CheckName), instance: &ContainerdConfig{}, store: store, + tagger: tagger, } }) } @@ -99,7 +102,7 @@ func (c *ContainerdCheck) Configure(senderManager sender.SenderManager, _ uint64 } c.httpClient = http.Client{Timeout: time.Duration(1) * time.Second} - c.processor = generic.NewProcessor(metrics.GetProvider(optional.NewOption(c.store)), generic.NewMetadataContainerAccessor(c.store), metricsAdapter{}, getProcessorFilter(c.containerFilter, c.store)) + c.processor = generic.NewProcessor(metrics.GetProvider(optional.NewOption(c.store)), generic.NewMetadataContainerAccessor(c.store), metricsAdapter{}, getProcessorFilter(c.containerFilter, c.store), c.tagger) c.processor.RegisterExtension("containerd-custom-metrics", &containerdCustomMetricsExtension{}) c.subscriber = createEventSubscriber("ContainerdCheck", c.client, cutil.FiltersWithNamespaces(c.instance.ContainerdFilters)) @@ -247,5 +250,5 @@ func (c *ContainerdCheck) collectEvents(sender sender.Sender) { } events := c.subscriber.Flush(time.Now().Unix()) // Process events - computeEvents(events, sender, c.containerFilter) + c.computeEvents(events, sender, c.containerFilter) } diff --git a/pkg/collector/corechecks/containers/containerd/check_metrics_extension.go b/pkg/collector/corechecks/containers/containerd/check_metrics_extension.go index 097dde1438a9e..d2d1ad8ddaa56 100644 --- a/pkg/collector/corechecks/containers/containerd/check_metrics_extension.go +++ b/pkg/collector/corechecks/containers/containerd/check_metrics_extension.go @@ -10,6 +10,7 @@ package containerd import ( "time" + "github.com/DataDog/datadog-agent/comp/core/tagger" taggerUtils "github.com/DataDog/datadog-agent/comp/core/tagger/utils" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" @@ -65,6 +66,6 @@ func (cext *containerdCustomMetricsExtension) Process(tags []string, container * } // PostProcess is called once during each check run, after all calls to `Process` -func (cext *containerdCustomMetricsExtension) PostProcess() { +func (cext *containerdCustomMetricsExtension) PostProcess(tagger.Component) { // Nothing to do here } diff --git a/pkg/collector/corechecks/containers/containerd/check_test.go b/pkg/collector/corechecks/containers/containerd/check_test.go index d54bb14bb5038..46019f8cb72e5 100644 --- a/pkg/collector/corechecks/containers/containerd/check_test.go +++ b/pkg/collector/corechecks/containers/containerd/check_test.go @@ -57,7 +57,6 @@ func TestContainerdCheckGenericPart(t *testing.T) { generic.CreateContainerMeta("docker", "cID101"), } fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() containersStats := map[string]mock.ContainerEntry{ "cID100": mock.GetFullSampleContainerEntry(), @@ -65,7 +64,7 @@ func TestContainerdCheckGenericPart(t *testing.T) { } // Inject mock processor in check - mockSender, processor, _ := generic.CreateTestProcessor(containersMeta, containersStats, metricsAdapter{}, getProcessorFilter(nil, nil)) + mockSender, processor, _ := generic.CreateTestProcessor(containersMeta, containersStats, metricsAdapter{}, getProcessorFilter(nil, nil), fakeTagger) processor.RegisterExtension("containerd-custom-metrics", &containerdCustomMetricsExtension{}) // Mock the containerd endpoint diff --git a/pkg/collector/corechecks/containers/containerd/events.go b/pkg/collector/corechecks/containers/containerd/events.go index 91c30213b93f4..92b87e5df7f87 100644 --- a/pkg/collector/corechecks/containers/containerd/events.go +++ b/pkg/collector/corechecks/containers/containerd/events.go @@ -18,7 +18,6 @@ import ( containerdevents "github.com/containerd/containerd/events" "google.golang.org/protobuf/proto" - "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/types" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -29,7 +28,7 @@ import ( ) // computeEvents converts Containerd events into Datadog events -func computeEvents(events []containerdEvent, sender sender.Sender, fil *containers.Filter) { +func (c *ContainerdCheck) computeEvents(events []containerdEvent, sender sender.Sender, fil *containers.Filter) { for _, e := range events { split := strings.Split(e.Topic, "/") if len(split) != 3 { @@ -52,7 +51,7 @@ func computeEvents(events []containerdEvent, sender sender.Sender, fil *containe alertType := event.AlertTypeInfo if split[1] == "containers" || split[1] == "tasks" { // For task events, we use the container ID in order to query the Tagger's API - t, err := tagger.Tag(types.NewEntityID(types.ContainerID, e.ID), types.HighCardinality) + t, err := c.tagger.Tag(types.NewEntityID(types.ContainerID, e.ID), types.HighCardinality) if err != nil { // If there is an error retrieving tags from the Tagger, we can still submit the event as is. log.Errorf("Could not retrieve tags for the container %s: %v", e.ID, err) diff --git a/pkg/collector/corechecks/containers/containerd/events_test.go b/pkg/collector/corechecks/containers/containerd/events_test.go index a4cc07881af0a..e24a807ced4ab 100644 --- a/pkg/collector/corechecks/containers/containerd/events_test.go +++ b/pkg/collector/corechecks/containers/containerd/events_test.go @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" "github.com/DataDog/datadog-agent/pkg/collector/corechecks" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -285,9 +286,11 @@ func TestCheckEvents_PauseContainers(t *testing.T) { // TestComputeEvents checks the conversion of Containerd events to Datadog events func TestComputeEvents(t *testing.T) { + fakeTagger := taggerimpl.SetupFakeTagger(t) containerdCheck := &ContainerdCheck{ instance: &ContainerdConfig{}, CheckBase: corechecks.NewCheckBase("containerd"), + tagger: fakeTagger, } mocked := mocksender.NewMockSender(containerdCheck.ID()) var err error @@ -370,7 +373,7 @@ func TestComputeEvents(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - computeEvents(test.events, mocked, containerdCheck.containerFilter) + containerdCheck.computeEvents(test.events, mocked, containerdCheck.containerFilter) mocked.On("Event", mock.AnythingOfType("event.Event")) if len(mocked.Calls) > 0 { res := (mocked.Calls[0].Arguments.Get(0)).(event.Event) diff --git a/pkg/collector/corechecks/containers/containerd/stub.go b/pkg/collector/corechecks/containers/containerd/stub.go index f2f3209451fd9..42a7f44a99e26 100644 --- a/pkg/collector/corechecks/containers/containerd/stub.go +++ b/pkg/collector/corechecks/containers/containerd/stub.go @@ -9,6 +9,7 @@ package containerd import ( + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -20,6 +21,6 @@ const ( ) // Factory is used to create register the check and initialize it. -func Factory(_ workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(workloadmeta.Component, tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/containers/cri/check.go b/pkg/collector/corechecks/containers/cri/check.go index bd93aeb6a2618..38810a06bee13 100644 --- a/pkg/collector/corechecks/containers/cri/check.go +++ b/pkg/collector/corechecks/containers/cri/check.go @@ -14,6 +14,7 @@ import ( yaml "gopkg.in/yaml.v2" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -44,15 +45,17 @@ type CRICheck struct { instance *CRIConfig processor generic.Processor store workloadmeta.Component + tagger tagger.Component } // Factory is exported for integration testing -func Factory(store workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(store workloadmeta.Component, tagger tagger.Component) optional.Option[func() check.Check] { return optional.NewOption(func() check.Check { return &CRICheck{ CheckBase: core.NewCheckBase(CheckName), instance: &CRIConfig{}, store: store, + tagger: tagger, } }) } @@ -81,7 +84,7 @@ func (c *CRICheck) Configure(senderManager sender.SenderManager, _ uint64, confi log.Warnf("Can't get container include/exclude filter, no filtering will be applied: %v", err) } - c.processor = generic.NewProcessor(metrics.GetProvider(optional.NewOption(c.store)), generic.NewMetadataContainerAccessor(c.store), metricsAdapter{}, getProcessorFilter(containerFilter, c.store)) + c.processor = generic.NewProcessor(metrics.GetProvider(optional.NewOption(c.store)), generic.NewMetadataContainerAccessor(c.store), metricsAdapter{}, getProcessorFilter(containerFilter, c.store), c.tagger) if c.instance.CollectDisk { c.processor.RegisterExtension("cri-custom-metrics", &criCustomMetricsExtension{criGetter: func() (cri.CRIClient, error) { return cri.GetUtil() diff --git a/pkg/collector/corechecks/containers/cri/check_metrics_extension.go b/pkg/collector/corechecks/containers/cri/check_metrics_extension.go index df549afaf294d..a07e262f0ae18 100644 --- a/pkg/collector/corechecks/containers/cri/check_metrics_extension.go +++ b/pkg/collector/corechecks/containers/cri/check_metrics_extension.go @@ -10,6 +10,7 @@ package cri import ( "time" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/containers/generic" @@ -61,6 +62,6 @@ func (cext *criCustomMetricsExtension) Process(tags []string, container *workloa } // PostProcess is called once during each check run, after all calls to `Process` -func (cext *criCustomMetricsExtension) PostProcess() { +func (cext *criCustomMetricsExtension) PostProcess(tagger.Component) { cext.criContainerStats = nil } diff --git a/pkg/collector/corechecks/containers/cri/check_test.go b/pkg/collector/corechecks/containers/cri/check_test.go index ab80a9fb83ef2..f7f052ef84da6 100644 --- a/pkg/collector/corechecks/containers/cri/check_test.go +++ b/pkg/collector/corechecks/containers/cri/check_test.go @@ -38,11 +38,10 @@ func TestCriCheck(t *testing.T) { "cID101": mock.GetFullSampleContainerEntry(), } fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() // Inject mock processor in check mockCri := &crimock.MockCRIClient{} - mockSender, processor, _ := generic.CreateTestProcessor(containersMeta, containersStats, metricsAdapter{}, getProcessorFilter(nil, nil)) + mockSender, processor, _ := generic.CreateTestProcessor(containersMeta, containersStats, metricsAdapter{}, getProcessorFilter(nil, nil), fakeTagger) processor.RegisterExtension("cri-custom-metrics", &criCustomMetricsExtension{criGetter: func() (cri.CRIClient, error) { return mockCri, nil }}) mockCri.On("ListContainerStats").Return(map[string]*criTypes.ContainerStats{ diff --git a/pkg/collector/corechecks/containers/cri/stub.go b/pkg/collector/corechecks/containers/cri/stub.go index 461e27684a243..66cb710de146b 100644 --- a/pkg/collector/corechecks/containers/cri/stub.go +++ b/pkg/collector/corechecks/containers/cri/stub.go @@ -9,6 +9,7 @@ package cri import ( + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -20,6 +21,6 @@ const ( ) // Factory creates a new check instance -func Factory(_ workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(workloadmeta.Component, tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/containers/docker/bundled_events.go b/pkg/collector/corechecks/containers/docker/bundled_events.go index d0688b89be9a6..fc1c5aa525c79 100644 --- a/pkg/collector/corechecks/containers/docker/bundled_events.go +++ b/pkg/collector/corechecks/containers/docker/bundled_events.go @@ -8,6 +8,7 @@ package docker import ( + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/pkg/metrics/event" "github.com/DataDog/datadog-agent/pkg/util/docker" "github.com/DataDog/datadog-agent/pkg/util/log" @@ -16,7 +17,7 @@ import ( // newBundledTransformer returns a transformer that bundles together docker // events from containers that share the same image. that's a behavior that no // longer makes sense, and we'd like to remove it in Agent 8. -func newBundledTransformer(hostname string, types []string) eventTransformer { +func newBundledTransformer(hostname string, types []string, tagger tagger.Component) eventTransformer { filteredEventTypes := make(map[string]struct{}, len(types)) for _, t := range types { filteredEventTypes[t] = struct{}{} @@ -25,12 +26,14 @@ func newBundledTransformer(hostname string, types []string) eventTransformer { return &bundledTransformer{ hostname: hostname, filteredEventTypes: filteredEventTypes, + tagger: tagger, } } type bundledTransformer struct { hostname string filteredEventTypes map[string]struct{} + tagger tagger.Component } func (t *bundledTransformer) Transform(events []*docker.ContainerEvent) ([]event.Event, []error) { @@ -67,7 +70,7 @@ func (t *bundledTransformer) aggregateEvents(events []*docker.ContainerEvent) ma bundle, found := eventsByImage[event.ImageName] if !found { - bundle = newDockerEventBundler(event.ImageName) + bundle = newDockerEventBundler(event.ImageName, t.tagger) eventsByImage[event.ImageName] = bundle } diff --git a/pkg/collector/corechecks/containers/docker/check.go b/pkg/collector/corechecks/containers/docker/check.go index 036e3a4e748e5..d66e303e3bffc 100644 --- a/pkg/collector/corechecks/containers/docker/check.go +++ b/pkg/collector/corechecks/containers/docker/check.go @@ -66,18 +66,20 @@ type DockerCheck struct { okExitCodes map[int]struct{} collectContainerSizeCounter uint64 store workloadmeta.Component + tagger tagger.Component lastEventTime time.Time eventTransformer eventTransformer } // Factory returns a new docker corecheck factory -func Factory(store workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(store workloadmeta.Component, tagger tagger.Component) optional.Option[func() check.Check] { return optional.NewOption(func() check.Check { return &DockerCheck{ CheckBase: core.NewCheckBase(CheckName), instance: &DockerConfig{}, store: store, + tagger: tagger, } }) } @@ -118,11 +120,12 @@ func (d *DockerCheck) Configure(senderManager sender.SenderManager, _ uint64, co d.dockerHostname, // Don't bundle events that are unbundled already. append(filteredEventTypes, d.instance.CollectedEventTypes...), + d.tagger, ) } - d.eventTransformer = newUnbundledTransformer(d.dockerHostname, d.instance.CollectedEventTypes, bundledTransformer) + d.eventTransformer = newUnbundledTransformer(d.dockerHostname, d.instance.CollectedEventTypes, bundledTransformer, d.tagger) } else { - d.eventTransformer = newBundledTransformer(d.dockerHostname, filteredEventTypes) + d.eventTransformer = newBundledTransformer(d.dockerHostname, filteredEventTypes, d.tagger) } d.containerFilter, err = containers.GetSharedMetricFilter() @@ -130,7 +133,7 @@ func (d *DockerCheck) Configure(senderManager sender.SenderManager, _ uint64, co log.Warnf("Can't get container include/exclude filter, no filtering will be applied: %v", err) } - d.processor = generic.NewProcessor(metrics.GetProvider(optional.NewOption(d.store)), generic.NewMetadataContainerAccessor(d.store), metricsAdapter{}, getProcessorFilter(d.containerFilter, d.store)) + d.processor = generic.NewProcessor(metrics.GetProvider(optional.NewOption(d.store)), generic.NewMetadataContainerAccessor(d.store), metricsAdapter{}, getProcessorFilter(d.containerFilter, d.store), d.tagger) d.processor.RegisterExtension("docker-custom-metrics", &dockerCustomMetricsExtension{}) d.configureNetworkProcessor(&d.processor) d.setOkExitCodes() @@ -240,7 +243,7 @@ func (d *DockerCheck) runDockerCustom(sender sender.Sender, du docker.Client, ra isContainerExcluded := d.containerFilter.IsExcluded(annotations, containerName, resolvedImageName, rawContainer.Labels[kubernetes.CriContainerNamespaceLabel]) isContainerRunning := rawContainer.State == string(workloadmeta.ContainerStatusRunning) taggerEntityID := types.NewEntityID(types.ContainerID, rawContainer.ID) - tags, err := getImageTagsFromContainer(taggerEntityID, resolvedImageName, isContainerExcluded || !isContainerRunning) + tags, err := d.getImageTagsFromContainer(taggerEntityID, resolvedImageName, isContainerExcluded || !isContainerRunning) if err != nil { log.Debugf("Unable to fetch tags for image: %s, err: %v", rawContainer.ImageID, err) } else { @@ -263,7 +266,7 @@ func (d *DockerCheck) runDockerCustom(sender sender.Sender, du docker.Client, ra } // Send container size metrics - containerTags, err := tagger.Tag(taggerEntityID, types.HighCardinality) + containerTags, err := d.tagger.Tag(taggerEntityID, types.HighCardinality) if err != nil { log.Warnf("Unable to fetch tags for container: %s, err: %v", rawContainer.ID, err) } @@ -427,3 +430,16 @@ func (d *DockerCheck) setOkExitCodes() { // 143 is returned when docker sends a SIGTERM to stop a container. d.okExitCodes = map[int]struct{}{0: {}, 143: {}} } + +func (d *DockerCheck) getImageTagsFromContainer(taggerEntityID types.EntityID, resolvedImageName string, isContainerExcluded bool) ([]string, error) { + if isContainerExcluded { + return getImageTags(resolvedImageName) + } + + containerTags, err := d.tagger.Tag(taggerEntityID, types.LowCardinality) + if err != nil { + return nil, err + } + + return containerTags, nil +} diff --git a/pkg/collector/corechecks/containers/docker/check_linux_test.go b/pkg/collector/corechecks/containers/docker/check_linux_test.go index b349be5e703bc..563696e6e73b6 100644 --- a/pkg/collector/corechecks/containers/docker/check_linux_test.go +++ b/pkg/collector/corechecks/containers/docker/check_linux_test.go @@ -13,6 +13,7 @@ import ( dockerTypes "github.com/docker/docker/api/types" dockerNetworkTypes "github.com/docker/docker/api/types/network" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/containers/generic" @@ -244,7 +245,7 @@ func TestDockerNetworkExtension(t *testing.T) { dockerNetworkExtension.Process(tags, container1, mockCollector, 0) dockerNetworkExtension.Process(tags, container2, mockCollector, 0) dockerNetworkExtension.Process(tags, container4, mockCollector, 0) - dockerNetworkExtension.PostProcess() + dockerNetworkExtension.PostProcess(nooptagger.NewTaggerClient()) // Running the custom part dockerNetworkExtension.preRun() diff --git a/pkg/collector/corechecks/containers/docker/check_metrics_extension.go b/pkg/collector/corechecks/containers/docker/check_metrics_extension.go index 7ba40bc5c51d3..267d1ec5fe536 100644 --- a/pkg/collector/corechecks/containers/docker/check_metrics_extension.go +++ b/pkg/collector/corechecks/containers/docker/check_metrics_extension.go @@ -11,6 +11,7 @@ import ( "math" "time" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/containers/generic" @@ -108,7 +109,7 @@ func (dn *dockerCustomMetricsExtension) Process(tags []string, container *worklo } // PostProcess is called once during each check run, after all calls to `Process` -func (dn *dockerCustomMetricsExtension) PostProcess() { +func (dn *dockerCustomMetricsExtension) PostProcess(tagger.Component) { // Nothing to do here } diff --git a/pkg/collector/corechecks/containers/docker/check_network.go b/pkg/collector/corechecks/containers/docker/check_network.go index 3e89621573063..ffdd3ad7ad04e 100644 --- a/pkg/collector/corechecks/containers/docker/check_network.go +++ b/pkg/collector/corechecks/containers/docker/check_network.go @@ -16,6 +16,7 @@ import ( dockerTypes "github.com/docker/docker/api/types" + "github.com/DataDog/datadog-agent/comp/core/tagger" taggerUtils "github.com/DataDog/datadog-agent/comp/core/tagger/utils" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" @@ -106,7 +107,7 @@ func (dn *dockerNetworkExtension) Process(tags []string, container *workloadmeta } // PostProcess is called once during each check run, after all calls to `Process` -func (dn *dockerNetworkExtension) PostProcess() { +func (dn *dockerNetworkExtension) PostProcess(tagger.Component) { // Nothing to do here } diff --git a/pkg/collector/corechecks/containers/docker/check_test.go b/pkg/collector/corechecks/containers/docker/check_test.go index 39597bb470b62..23aa7b690336e 100644 --- a/pkg/collector/corechecks/containers/docker/check_test.go +++ b/pkg/collector/corechecks/containers/docker/check_test.go @@ -43,7 +43,6 @@ func TestDockerCheckGenericPart(t *testing.T) { generic.CreateContainerMeta("containerd", "cID101"), } fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() containersStats := map[string]mock.ContainerEntry{ "cID100": mock.GetFullSampleContainerEntry(), @@ -51,7 +50,7 @@ func TestDockerCheckGenericPart(t *testing.T) { } // Inject mock processor in check - mockSender, processor, _ := generic.CreateTestProcessor(containersMeta, containersStats, metricsAdapter{}, getProcessorFilter(nil, nil)) + mockSender, processor, _ := generic.CreateTestProcessor(containersMeta, containersStats, metricsAdapter{}, getProcessorFilter(nil, nil), fakeTagger) processor.RegisterExtension("docker-custom-metrics", &dockerCustomMetricsExtension{}) // Create Docker check @@ -117,7 +116,6 @@ func TestDockerCustomPart(t *testing.T) { mockSender.SetupAcceptAll() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "e2d5394a5321d4a59497f53552a0131b2aafe64faba37f4738e78c531289fc45"), "foo", []string{"image_name:datadog/agent", "short:agent", "tag:latest"}, nil, nil, nil) fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "b781900d227cf8d63a0922705018b66610f789644bf236cb72c8698b31383074"), "foo", []string{"image_name:datadog/agent", "short:agent", "tag:7.32.0-rc.1"}, nil, nil, nil) fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "be2584a7d1a2a3ae9f9c688e9ce7a88991c028507fec7c70a660b705bd2a5b90"), "foo", []string{"app:foo"}, nil, nil, nil) @@ -205,13 +203,14 @@ func TestDockerCustomPart(t *testing.T) { CollectVolumeCount: true, CollectEvent: true, }, - eventTransformer: newBundledTransformer("testhostname", []string{}), + eventTransformer: newBundledTransformer("testhostname", []string{}, fakeTagger), dockerHostname: "testhostname", containerFilter: &containers.Filter{ Enabled: true, NameExcludeList: []*regexp.Regexp{regexp.MustCompile("agent-excluded")}, }, - store: fxutil.Test[workloadmetamock.Mock](t, core.MockBundle(), workloadmetafxmock.MockModule(workloadmeta.NewParams())), + store: fxutil.Test[workloadmetamock.Mock](t, core.MockBundle(), workloadmetafxmock.MockModule(workloadmeta.NewParams())), + tagger: fakeTagger, } err := check.runDockerCustom(mockSender, &dockerClient, dockerClient.FakeContainerList) @@ -251,7 +250,6 @@ func TestContainersRunning(t *testing.T) { // The third one shares the image-related tags, but has a different // "service" tag. fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "e2d5394a5321d4a59497f53552a0131b2aafe64faba37f4738e78c531289fc45"), "foo", []string{"image_name:datadog/agent", "short:agent", "tag:latest", "service:s1"}, nil, nil, nil) fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "b781900d227cf8d63a0922705018b66610f789644bf236cb72c8698b31383074"), "foo", []string{"image_name:datadog/agent", "short:agent", "tag:latest", "service:s1"}, nil, nil, nil) fakeTagger.SetTags(types.NewEntityID(types.ContainerID, "be2584a7d1a2a3ae9f9c688e9ce7a88991c028507fec7c70a660b705bd2a5b90"), "foo", []string{"image_name:datadog/agent", "short:agent", "tag:latest", "service:s2"}, nil, nil, nil) @@ -291,6 +289,7 @@ func TestContainersRunning(t *testing.T) { dockerHostname: "testhostname", containerFilter: &containers.Filter{}, store: fxutil.Test[workloadmetamock.Mock](t, core.MockBundle(), workloadmetafxmock.MockModule(workloadmeta.NewParams())), + tagger: fakeTagger, } err := check.runDockerCustom(mockSender, &dockerClient, dockerClient.FakeContainerList) @@ -304,6 +303,8 @@ func TestContainersRunning(t *testing.T) { } func TestProcess_CPUSharesMetric(t *testing.T) { + fakeTagger := taggerimpl.SetupFakeTagger(t) + containersMeta := []*workloadmeta.Container{ generic.CreateContainerMeta("docker", "cID100"), generic.CreateContainerMeta("docker", "cID101"), @@ -335,7 +336,7 @@ func TestProcess_CPUSharesMetric(t *testing.T) { } // Inject mock processor in check - mockSender, processor, _ := generic.CreateTestProcessor(containersMeta, containersStats, metricsAdapter{}, getProcessorFilter(nil, nil)) + mockSender, processor, _ := generic.CreateTestProcessor(containersMeta, containersStats, metricsAdapter{}, getProcessorFilter(nil, nil), fakeTagger) processor.RegisterExtension("docker-custom-metrics", &dockerCustomMetricsExtension{}) // Create Docker check @@ -343,6 +344,7 @@ func TestProcess_CPUSharesMetric(t *testing.T) { instance: &DockerConfig{}, processor: *processor, dockerHostname: "testhostname", + tagger: fakeTagger, } err := check.runProcessor(mockSender) diff --git a/pkg/collector/corechecks/containers/docker/eventbundle.go b/pkg/collector/corechecks/containers/docker/eventbundle.go index 4dfeac8f769af..c3df8b979e70e 100644 --- a/pkg/collector/corechecks/containers/docker/eventbundle.go +++ b/pkg/collector/corechecks/containers/docker/eventbundle.go @@ -31,14 +31,16 @@ type dockerEventBundle struct { maxTimestamp time.Time countByAction map[events.Action]int alertType event.AlertType + tagger tagger.Component } -func newDockerEventBundler(imageName string) *dockerEventBundle { +func newDockerEventBundler(imageName string, tagger tagger.Component) *dockerEventBundle { return &dockerEventBundle{ imageName: imageName, events: []*docker.ContainerEvent{}, countByAction: make(map[events.Action]int), alertType: event.AlertTypeInfo, + tagger: tagger, } } @@ -92,8 +94,7 @@ func (b *dockerEventBundle) toDatadogEvent(hostname string) (event.Event, error) output.Text = strings.Join(textLines, "\n") for cid := range seenContainers { - - tags, err := tagger.Tag(types.NewEntityID(types.ContainerID, cid), types.HighCardinality) + tags, err := b.tagger.Tag(types.NewEntityID(types.ContainerID, cid), types.HighCardinality) if err != nil { log.Debugf("no tags for %s: %s", cid, err) } else { diff --git a/pkg/collector/corechecks/containers/docker/events.go b/pkg/collector/corechecks/containers/docker/events.go index a1dbc0337df93..7a36f2d84a22e 100644 --- a/pkg/collector/corechecks/containers/docker/events.go +++ b/pkg/collector/corechecks/containers/docker/events.go @@ -13,7 +13,6 @@ import ( "strconv" "time" - "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/types" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/metrics/servicecheck" @@ -83,7 +82,7 @@ func (d *DockerCheck) reportExitCodes(events []*docker.ContainerEvent, sender se status = servicecheck.ServiceCheckCritical } - tags, err := tagger.Tag(types.NewEntityID(types.ContainerID, ev.ContainerID), types.HighCardinality) + tags, err := d.tagger.Tag(types.NewEntityID(types.ContainerID, ev.ContainerID), types.HighCardinality) if err != nil { log.Debugf("no tags for %s: %s", ev.ContainerID, err) tags = []string{} diff --git a/pkg/collector/corechecks/containers/docker/events_test.go b/pkg/collector/corechecks/containers/docker/events_test.go index 898918c6301a1..32399e3a53a20 100644 --- a/pkg/collector/corechecks/containers/docker/events_test.go +++ b/pkg/collector/corechecks/containers/docker/events_test.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/api/types/events" "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" "github.com/DataDog/datadog-agent/pkg/metrics/event" "github.com/DataDog/datadog-agent/pkg/metrics/servicecheck" @@ -20,8 +21,11 @@ import ( ) func TestReportExitCodes(t *testing.T) { + fakeTagger := taggerimpl.SetupFakeTagger(t) + dockerCheck := &DockerCheck{ instance: &DockerConfig{}, + tagger: fakeTagger, } dockerCheck.setOkExitCodes() @@ -87,6 +91,7 @@ func TestReportExitCodes(t *testing.T) { instance: &DockerConfig{ OkExitCodes: []int{0}, }, + tagger: fakeTagger, } dockerCheck.setOkExitCodes() @@ -120,6 +125,8 @@ func TestReportExitCodes(t *testing.T) { } func TestAggregateEvents(t *testing.T) { + fakeTagger := taggerimpl.SetupFakeTagger(t) + testCases := []struct { events []*docker.ContainerEvent filteredActions []string @@ -150,6 +157,7 @@ func TestAggregateEvents(t *testing.T) { "unfiltered_action": 1, }, alertType: event.AlertTypeInfo, + tagger: fakeTagger, }, }, }, @@ -189,6 +197,7 @@ func TestAggregateEvents(t *testing.T) { "other_action": 1, }, alertType: event.AlertTypeInfo, + tagger: fakeTagger, }, }, }, @@ -221,6 +230,7 @@ func TestAggregateEvents(t *testing.T) { "other_action": 1, }, alertType: event.AlertTypeInfo, + tagger: fakeTagger, }, "other_image": { imageName: "other_image", @@ -228,13 +238,14 @@ func TestAggregateEvents(t *testing.T) { "other_action": 1, }, alertType: event.AlertTypeInfo, + tagger: fakeTagger, }, }, }, } for _, tc := range testCases { t.Run("", func(t *testing.T) { - transformer := newBundledTransformer("test-host", tc.filteredActions).(*bundledTransformer) + transformer := newBundledTransformer("test-host", tc.filteredActions, fakeTagger).(*bundledTransformer) bundles := transformer.aggregateEvents(tc.events) for _, b := range bundles { // Strip underlying events to ease testing diff --git a/pkg/collector/corechecks/containers/docker/stub.go b/pkg/collector/corechecks/containers/docker/stub.go index 3f8990f9e8602..12f3c764878fe 100644 --- a/pkg/collector/corechecks/containers/docker/stub.go +++ b/pkg/collector/corechecks/containers/docker/stub.go @@ -9,6 +9,7 @@ package docker import ( + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -19,6 +20,6 @@ const ( CheckName = "docker" ) -func Factory(_ workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(workloadmeta.Component, tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/containers/docker/unbundled_events.go b/pkg/collector/corechecks/containers/docker/unbundled_events.go index 19c2273ebb9c7..e51cf2c17056c 100644 --- a/pkg/collector/corechecks/containers/docker/unbundled_events.go +++ b/pkg/collector/corechecks/containers/docker/unbundled_events.go @@ -17,7 +17,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/util/log" ) -func newUnbundledTransformer(hostname string, types []string, bundledTransformer eventTransformer) eventTransformer { +func newUnbundledTransformer(hostname string, types []string, bundledTransformer eventTransformer, tagger tagger.Component) eventTransformer { collectedEventTypes := make(map[string]struct{}, len(types)) for _, t := range types { collectedEventTypes[t] = struct{}{} @@ -27,6 +27,7 @@ func newUnbundledTransformer(hostname string, types []string, bundledTransformer hostname: hostname, collectedEventTypes: collectedEventTypes, bundledTransformer: bundledTransformer, + tagger: tagger, } } @@ -34,6 +35,7 @@ type unbundledTransformer struct { hostname string collectedEventTypes map[string]struct{} bundledTransformer eventTransformer + tagger tagger.Component } func (t *unbundledTransformer) Transform(events []*docker.ContainerEvent) ([]event.Event, []error) { @@ -56,7 +58,7 @@ func (t *unbundledTransformer) Transform(events []*docker.ContainerEvent) ([]eve emittedEvents.Inc(string(alertType)) - tags, err := tagger.Tag( + tags, err := t.tagger.Tag( types.NewEntityID(types.ContainerID, ev.ContainerID), types.HighCardinality, ) diff --git a/pkg/collector/corechecks/containers/docker/unbundled_events_test.go b/pkg/collector/corechecks/containers/docker/unbundled_events_test.go index 23d3040df1b45..2599f9b8b7d62 100644 --- a/pkg/collector/corechecks/containers/docker/unbundled_events_test.go +++ b/pkg/collector/corechecks/containers/docker/unbundled_events_test.go @@ -129,7 +129,7 @@ func TestUnbundledEventsTransform(t *testing.T) { } fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + for _, ev := range incomingEvents { fakeTagger.SetTags( types.NewEntityID(types.ContainerID, ev.ContainerID), @@ -301,12 +301,13 @@ pokemon/azurill 1 top on test-host t.Run(tt.name, func(t *testing.T) { var eventTransformer eventTransformer = noopEventTransformer{} if tt.bundleUnspecifedEvents { - eventTransformer = newBundledTransformer(hostname, tt.filteredEventTypes) + eventTransformer = newBundledTransformer(hostname, tt.filteredEventTypes, fakeTagger) } transformer := newUnbundledTransformer( hostname, tt.collectedEventTypes, eventTransformer, + fakeTagger, ) evs, errs := transformer.Transform(incomingEvents) require.Nil(t, errs) diff --git a/pkg/collector/corechecks/containers/docker/utils.go b/pkg/collector/corechecks/containers/docker/utils.go index 3b3990cbfdf8f..a514af5e1b753 100644 --- a/pkg/collector/corechecks/containers/docker/utils.go +++ b/pkg/collector/corechecks/containers/docker/utils.go @@ -12,8 +12,6 @@ import ( "github.com/docker/docker/api/types/events" - "github.com/DataDog/datadog-agent/comp/core/tagger" - "github.com/DataDog/datadog-agent/comp/core/tagger/types" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/containers/generic" "github.com/DataDog/datadog-agent/pkg/util/containers" @@ -30,19 +28,6 @@ func getProcessorFilter(legacyFilter *containers.Filter, store workloadmeta.Comp } } -func getImageTagsFromContainer(taggerEntityID types.EntityID, resolvedImageName string, isContainerExcluded bool) ([]string, error) { - if isContainerExcluded { - return getImageTags(resolvedImageName) - } - - containerTags, err := tagger.Tag(taggerEntityID, types.LowCardinality) - if err != nil { - return nil, err - } - - return containerTags, nil -} - func getImageTags(imageName string) ([]string, error) { long, _, short, tag, err := pkgcontainersimage.SplitImageName(imageName) if err != nil { diff --git a/pkg/collector/corechecks/containers/generic/check.go b/pkg/collector/corechecks/containers/generic/check.go index 87c61d6b49390..cf3cacad20579 100644 --- a/pkg/collector/corechecks/containers/generic/check.go +++ b/pkg/collector/corechecks/containers/generic/check.go @@ -12,6 +12,7 @@ import ( yaml "gopkg.in/yaml.v2" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -41,15 +42,17 @@ type ContainerCheck struct { instance *ContainerConfig processor Processor store workloadmeta.Component + tagger tagger.Component } // Factory returns a new check factory -func Factory(store workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(store workloadmeta.Component, tagger tagger.Component) optional.Option[func() check.Check] { return optional.NewOption(func() check.Check { return &ContainerCheck{ CheckBase: core.NewCheckBase(CheckName), instance: &ContainerConfig{}, store: store, + tagger: tagger, } }) } @@ -65,7 +68,7 @@ func (c *ContainerCheck) Configure(senderManager sender.SenderManager, _ uint64, if err != nil { return err } - c.processor = NewProcessor(metrics.GetProvider(optional.NewOption(c.store)), NewMetadataContainerAccessor(c.store), GenericMetricsAdapter{}, LegacyContainerFilter{OldFilter: filter, Store: c.store}) + c.processor = NewProcessor(metrics.GetProvider(optional.NewOption(c.store)), NewMetadataContainerAccessor(c.store), GenericMetricsAdapter{}, LegacyContainerFilter{OldFilter: filter, Store: c.store}, c.tagger) return c.instance.Parse(config) } diff --git a/pkg/collector/corechecks/containers/generic/mock.go b/pkg/collector/corechecks/containers/generic/mock.go index 50d0aa160845a..e14823a8578b0 100644 --- a/pkg/collector/corechecks/containers/generic/mock.go +++ b/pkg/collector/corechecks/containers/generic/mock.go @@ -10,6 +10,7 @@ package generic import ( "time" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" "github.com/DataDog/datadog-agent/pkg/util/containers/metrics/mock" @@ -31,6 +32,7 @@ func CreateTestProcessor(listerContainers []*workloadmeta.Container, metricsContainers map[string]mock.ContainerEntry, metricsAdapter MetricsAdapter, containerFilter ContainerFilter, + tagger tagger.Component, ) (*mocksender.MockSender, *Processor, ContainerAccessor) { mockProvider := mock.NewMetricsProvider() mockCollector := mock.NewCollector("testCollector") @@ -48,7 +50,7 @@ func CreateTestProcessor(listerContainers []*workloadmeta.Container, mockedSender := mocksender.NewMockSender("generic-container") mockedSender.SetupAcceptAll() - p := NewProcessor(mockProvider, &mockAccessor, metricsAdapter, containerFilter) + p := NewProcessor(mockProvider, &mockAccessor, metricsAdapter, containerFilter, tagger) return mockedSender, &p, &mockAccessor } diff --git a/pkg/collector/corechecks/containers/generic/processor.go b/pkg/collector/corechecks/containers/generic/processor.go index 44612d6839c52..9f76abc078e85 100644 --- a/pkg/collector/corechecks/containers/generic/processor.go +++ b/pkg/collector/corechecks/containers/generic/processor.go @@ -32,10 +32,11 @@ type Processor struct { metricsAdapter MetricsAdapter ctrFilter ContainerFilter extensions map[string]ProcessorExtension + tagger tagger.Component } // NewProcessor creates a new processor -func NewProcessor(provider metrics.Provider, lister ContainerAccessor, adapter MetricsAdapter, filter ContainerFilter) Processor { +func NewProcessor(provider metrics.Provider, lister ContainerAccessor, adapter MetricsAdapter, filter ContainerFilter, tagger tagger.Component) Processor { return Processor{ metricsProvider: provider, ctrLister: lister, @@ -44,6 +45,7 @@ func NewProcessor(provider metrics.Provider, lister ContainerAccessor, adapter M extensions: map[string]ProcessorExtension{ NetworkExtensionID: NewProcessorNetwork(), }, + tagger: tagger, } } @@ -73,7 +75,7 @@ func (p *Processor) Run(sender sender.Sender, cacheValidity time.Duration) error entityID := types.NewEntityID(types.ContainerID, container.ID) - tags, err := tagger.Tag(entityID, types.HighCardinality) + tags, err := p.tagger.Tag(entityID, types.HighCardinality) if err != nil { log.Errorf("Could not collect tags for container %q, err: %v", container.ID[:12], err) continue @@ -117,7 +119,7 @@ func (p *Processor) Run(sender sender.Sender, cacheValidity time.Duration) error // Extensions: PostProcess hook for _, extension := range p.extensions { - extension.PostProcess() + extension.PostProcess(p.tagger) } sender.Commit() diff --git a/pkg/collector/corechecks/containers/generic/processor_extension.go b/pkg/collector/corechecks/containers/generic/processor_extension.go index 03c3cb2103498..e2324a69e659d 100644 --- a/pkg/collector/corechecks/containers/generic/processor_extension.go +++ b/pkg/collector/corechecks/containers/generic/processor_extension.go @@ -8,6 +8,7 @@ package generic import ( "time" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/util/containers/metrics" @@ -27,5 +28,5 @@ type ProcessorExtension interface { Process(tags []string, container *workloadmeta.Container, collector metrics.Collector, cacheValidity time.Duration) // PostProcess is called once during each check run, after all calls to `Process` - PostProcess() + PostProcess(tagger tagger.Component) } diff --git a/pkg/collector/corechecks/containers/generic/processor_network.go b/pkg/collector/corechecks/containers/generic/processor_network.go index 52b992dee3937..9173b615fda3c 100644 --- a/pkg/collector/corechecks/containers/generic/processor_network.go +++ b/pkg/collector/corechecks/containers/generic/processor_network.go @@ -78,11 +78,11 @@ func (pn *ProcessorNetwork) Process(tags []string, container *workloadmeta.Conta } // PostProcess actually computes the metrics -func (pn *ProcessorNetwork) PostProcess() { - pn.processGroupedContainerNetwork() +func (pn *ProcessorNetwork) PostProcess(tagger tagger.Component) { + pn.processGroupedContainerNetwork(tagger) } -func (pn *ProcessorNetwork) processGroupedContainerNetwork() { +func (pn *ProcessorNetwork) processGroupedContainerNetwork(tagger tagger.Component) { // Handle all containers that we could not link to any network isolation group for _, containerNetwork := range pn.ungroupedContainerNetwork { pn.generateNetworkMetrics(containerNetwork.tags, containerNetwork.stats) diff --git a/pkg/collector/corechecks/containers/generic/processor_network_test.go b/pkg/collector/corechecks/containers/generic/processor_network_test.go index a6aa31341e2b5..2a2ac804ed312 100644 --- a/pkg/collector/corechecks/containers/generic/processor_network_test.go +++ b/pkg/collector/corechecks/containers/generic/processor_network_test.go @@ -22,7 +22,6 @@ func TestNetworkProcessorExtension(t *testing.T) { mockSender.SetupAcceptAll() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() mockCollector := mock.NewCollector("testCollector") @@ -207,7 +206,7 @@ func TestNetworkProcessorExtension(t *testing.T) { container7Tags, _ := fakeTagger.Tag(types.NewEntityID(types.ContainerID, "7"), types.HighCardinality) networkProcessor.Process(container7Tags, container7, mockCollector, 0) - networkProcessor.PostProcess() + networkProcessor.PostProcess(fakeTagger) // Checking results mockSender.AssertNumberOfCalls(t, "Rate", 12) diff --git a/pkg/collector/corechecks/containers/generic/processor_test.go b/pkg/collector/corechecks/containers/generic/processor_test.go index 45ca6079a12da..5ac5c84f4f020 100644 --- a/pkg/collector/corechecks/containers/generic/processor_test.go +++ b/pkg/collector/corechecks/containers/generic/processor_test.go @@ -19,7 +19,6 @@ import ( func TestProcessorRunFullStatsLinux(t *testing.T) { fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() containersMeta := []*workloadmeta.Container{ // Container with full stats @@ -35,7 +34,7 @@ func TestProcessorRunFullStatsLinux(t *testing.T) { }, } - mockSender, processor, _ := CreateTestProcessor(containersMeta, containersStats, GenericMetricsAdapter{}, nil) + mockSender, processor, _ := CreateTestProcessor(containersMeta, containersStats, GenericMetricsAdapter{}, nil, fakeTagger) err := processor.Run(mockSender, 0) assert.ErrorIs(t, err, nil) @@ -90,7 +89,6 @@ func TestProcessorRunFullStatsLinux(t *testing.T) { func TestProcessorRunPartialStats(t *testing.T) { fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() containersMeta := []*workloadmeta.Container{ // Container without stats @@ -105,7 +103,7 @@ func TestProcessorRunPartialStats(t *testing.T) { }, } - mockSender, processor, _ := CreateTestProcessor(containersMeta, containersStats, GenericMetricsAdapter{}, nil) + mockSender, processor, _ := CreateTestProcessor(containersMeta, containersStats, GenericMetricsAdapter{}, nil, fakeTagger) err := processor.Run(mockSender, 0) assert.ErrorIs(t, err, nil) diff --git a/pkg/collector/corechecks/containers/kubelet/common/pod.go b/pkg/collector/corechecks/containers/kubelet/common/pod.go index 54a105c90bab2..6519e99ceba0b 100644 --- a/pkg/collector/corechecks/containers/kubelet/common/pod.go +++ b/pkg/collector/corechecks/containers/kubelet/common/pod.go @@ -45,13 +45,15 @@ type podMetadata struct { type PodUtils struct { podTagsByPVC map[string][]string podMetadata map[string]*podMetadata + tagger tagger.Component } // NewPodUtils creates a new instance of PodUtils -func NewPodUtils() *PodUtils { +func NewPodUtils(tagger tagger.Component) *PodUtils { return &PodUtils{ podTagsByPVC: map[string][]string{}, podMetadata: map[string]*podMetadata{}, + tagger: tagger, } } @@ -86,7 +88,7 @@ func (p *PodUtils) PopulateForPod(pod *kubelet.Pod) { // volume name. func (p *PodUtils) computePodTagsByPVC(pod *kubelet.Pod) { podUID := types.NewEntityID(types.KubernetesPodUID, pod.Metadata.UID) - tags, _ := tagger.Tag(podUID, types.OrchestratorCardinality) + tags, _ := p.tagger.Tag(podUID, types.OrchestratorCardinality) if len(tags) == 0 { return } diff --git a/pkg/collector/corechecks/containers/kubelet/kubelet.go b/pkg/collector/corechecks/containers/kubelet/kubelet.go index 9c2eaf42c73d3..f3b4056766ee1 100644 --- a/pkg/collector/corechecks/containers/kubelet/kubelet.go +++ b/pkg/collector/corechecks/containers/kubelet/kubelet.go @@ -10,6 +10,7 @@ package kubelet import ( "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -47,41 +48,43 @@ type KubeletCheck struct { providers []Provider podUtils *common.PodUtils store workloadmeta.Component + tagger tagger.Component } // NewKubeletCheck returns a new KubeletCheck -func NewKubeletCheck(base core.CheckBase, instance *common.KubeletConfig, store workloadmeta.Component) *KubeletCheck { +func NewKubeletCheck(base core.CheckBase, instance *common.KubeletConfig, store workloadmeta.Component, tagger tagger.Component) *KubeletCheck { return &KubeletCheck{ CheckBase: base, instance: instance, store: store, + tagger: tagger, } } -func initProviders(filter *containers.Filter, config *common.KubeletConfig, podUtils *common.PodUtils, store workloadmeta.Component) []Provider { - podProvider := pod.NewProvider(filter, config, podUtils) +func initProviders(filter *containers.Filter, config *common.KubeletConfig, podUtils *common.PodUtils, store workloadmeta.Component, tagger tagger.Component) []Provider { + podProvider := pod.NewProvider(filter, config, podUtils, tagger) // nodeProvider collects from the /spec endpoint, which was hidden by default in k8s 1.18 and removed in k8s 1.19. // It is here for backwards compatibility. nodeProvider := node.NewProvider(config) healthProvider := health.NewProvider(config) - summaryProvider := summary.NewProvider(filter, config, store) + summaryProvider := summary.NewProvider(filter, config, store, tagger) sliProvider, err := slis.NewProvider(filter, config, store) if err != nil { log.Warnf("Can't get sli provider: %v", err) } - probeProvider, err := probe.NewProvider(filter, config, store) + probeProvider, err := probe.NewProvider(filter, config, store, tagger) if err != nil { log.Warnf("Can't get probe provider: %v", err) } - kubeletProvider, err := kube.NewProvider(filter, config, store, podUtils) + kubeletProvider, err := kube.NewProvider(filter, config, store, podUtils, tagger) if err != nil { log.Warnf("Can't get kubelet provider: %v", err) } - cadvisorProvider, err := cadvisor.NewProvider(filter, config, store, podUtils) + cadvisorProvider, err := cadvisor.NewProvider(filter, config, store, podUtils, tagger) if err != nil { log.Warnf("Can't get cadvisor provider: %v", err) } @@ -99,9 +102,9 @@ func initProviders(filter *containers.Filter, config *common.KubeletConfig, podU } // Factory returns a new KubeletCheck factory -func Factory(store workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(store workloadmeta.Component, tagger tagger.Component) optional.Option[func() check.Check] { return optional.NewOption(func() check.Check { - return NewKubeletCheck(core.NewCheckBase(CheckName), &common.KubeletConfig{}, store) + return NewKubeletCheck(core.NewCheckBase(CheckName), &common.KubeletConfig{}, store, tagger) }) } @@ -129,8 +132,8 @@ func (k *KubeletCheck) Configure(senderManager sender.SenderManager, _ uint64, c k.instance.SendHistogramBuckets = &sendBuckets } - k.podUtils = common.NewPodUtils() - k.providers = initProviders(filter, k.instance, k.podUtils, k.store) + k.podUtils = common.NewPodUtils(k.tagger) + k.providers = initProviders(filter, k.instance, k.podUtils, k.store, k.tagger) return nil } diff --git a/pkg/collector/corechecks/containers/kubelet/provider/cadvisor/provider.go b/pkg/collector/corechecks/containers/kubelet/provider/cadvisor/provider.go index 7d2a65ad04f71..96672668f4793 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/cadvisor/provider.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/cadvisor/provider.go @@ -75,6 +75,7 @@ type processCache struct { type Provider struct { filter *containers.Filter store workloadmeta.Component + tagger tagger.Component podUtils *common.PodUtils fsUsageBytes map[string]*processCache memUsageBytes map[string]*processCache @@ -83,7 +84,7 @@ type Provider struct { } // NewProvider creates and returns a new Provider, configured based on the values passed in. -func NewProvider(filter *containers.Filter, config *common.KubeletConfig, store workloadmeta.Component, podUtils *common.PodUtils) (*Provider, error) { +func NewProvider(filter *containers.Filter, config *common.KubeletConfig, store workloadmeta.Component, podUtils *common.PodUtils, tagger tagger.Component) (*Provider, error) { // clone instance configuration so we can set our default metrics cadvisorConfig := *config @@ -92,6 +93,7 @@ func NewProvider(filter *containers.Filter, config *common.KubeletConfig, store provider := &Provider{ filter: filter, store: store, + tagger: tagger, podUtils: podUtils, fsUsageBytes: map[string]*processCache{}, memUsageBytes: map[string]*processCache{}, @@ -152,7 +154,7 @@ func (p *Provider) processContainerMetric(metricType, metricName string, metricF // for static pods, see https://github.com/kubernetes/kubernetes/pull/59948 pod := p.getPodByMetricLabel(sample.Metric) if pod != nil && p.podUtils.IsStaticPendingPod(pod.ID) { - podTags, _ := tagger.Tag(taggercommon.BuildTaggerEntityID(pod.GetID()), types.HighCardinality) + podTags, _ := p.tagger.Tag(taggercommon.BuildTaggerEntityID(pod.GetID()), types.HighCardinality) if len(podTags) == 0 { continue } @@ -163,7 +165,7 @@ func (p *Provider) processContainerMetric(metricType, metricName string, metricF tags = podTags } else { cID, _ := kubelet.KubeContainerIDToTaggerEntityID(containerID) - tags, _ = tagger.Tag(cID, types.HighCardinality) + tags, _ = p.tagger.Tag(cID, types.HighCardinality) } if len(tags) == 0 { @@ -208,7 +210,7 @@ func (p *Provider) processPodRate(metricName string, metricFam *prom.MetricFamil continue } entityID := taggercommon.BuildTaggerEntityID(pod.GetID()) - tags, _ := tagger.Tag(entityID, types.HighCardinality) + tags, _ := p.tagger.Tag(entityID, types.HighCardinality) if len(tags) == 0 { continue } @@ -239,7 +241,7 @@ func (p *Provider) processUsageMetric(metricName string, metricFam *prom.MetricF } cID, _ := kubelet.KubeContainerIDToTaggerEntityID(containerID) - tags, _ := tagger.Tag(cID, types.HighCardinality) + tags, _ := p.tagger.Tag(cID, types.HighCardinality) if len(tags) == 0 { continue } @@ -250,7 +252,7 @@ func (p *Provider) processUsageMetric(metricName string, metricFam *prom.MetricF pod := p.getPodByMetricLabel(sample.Metric) if pod != nil && p.podUtils.IsStaticPendingPod(pod.ID) { entityID := taggercommon.BuildTaggerEntityID(pod.EntityID) - podTags, _ := tagger.Tag(entityID, types.HighCardinality) + podTags, _ := p.tagger.Tag(entityID, types.HighCardinality) if len(podTags) == 0 { continue } @@ -287,7 +289,7 @@ func (p *Provider) processLimitMetric(metricName string, metricFam *prom.MetricF samples := p.latestValueByContext(metricFam, p.getEntityIDIfContainerMetric) for containerID, sample := range samples { cID, _ := kubelet.KubeContainerIDToTaggerEntityID(containerID) - tags, _ := tagger.Tag(cID, types.HighCardinality) + tags, _ := p.tagger.Tag(cID, types.HighCardinality) if len(tags) == 0 { continue } diff --git a/pkg/collector/corechecks/containers/kubelet/provider/cadvisor/provider_test.go b/pkg/collector/corechecks/containers/kubelet/provider/cadvisor/provider_test.go index dbc8a8fa43eeb..98ba28357154f 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/cadvisor/provider_test.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/cadvisor/provider_test.go @@ -18,6 +18,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/common/types" + "github.com/DataDog/datadog-agent/comp/core/tagger" taggercommon "github.com/DataDog/datadog-agent/comp/core/tagger/common" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" taggertypes "github.com/DataDog/datadog-agent/comp/core/tagger/types" @@ -92,6 +93,7 @@ type ProviderTestSuite struct { provider *Provider mockSender *mocksender.MockSender store workloadmeta.Component + tagger tagger.Component } func (suite *ProviderTestSuite) SetupTest() { @@ -107,14 +109,15 @@ func (suite *ProviderTestSuite) SetupTest() { suite.mockSender = mockSender fakeTagger := taggerimpl.SetupFakeTagger(suite.T()) - defer fakeTagger.ResetTagger() + for entity, tags := range commontesting.CommonTags { prefix, id, _ := taggercommon.ExtractPrefixAndID(entity) entityID := taggertypes.NewEntityID(prefix, id) fakeTagger.SetTags(entityID, "foo", tags, nil, nil, nil) } + suite.tagger = fakeTagger - podUtils := common.NewPodUtils() + podUtils := common.NewPodUtils(fakeTagger) podsFile := "../../testdata/pods.json" err = commontesting.StorePopulatedFromFile(store, podsFile, podUtils) @@ -140,6 +143,7 @@ func (suite *ProviderTestSuite) SetupTest() { config, store, podUtils, + fakeTagger, ) assert.NoError(suite.T(), err) suite.provider = p @@ -268,7 +272,7 @@ func (suite *ProviderTestSuite) TestIgnoreMetrics() { ignoreMetrics = oldIgnore }) // since we updated ignoreMetrics, we need to recreate the provider - suite.provider, _ = NewProvider(suite.provider.filter, suite.provider.Config, suite.provider.store, suite.provider.podUtils) + suite.provider, _ = NewProvider(suite.provider.filter, suite.provider.Config, suite.provider.store, suite.provider.podUtils, suite.tagger) response := commontesting.NewEndpointResponse( "../../testdata/cadvisor_metrics_pre_1_16.txt", 200, nil) diff --git a/pkg/collector/corechecks/containers/kubelet/provider/kubelet/provider.go b/pkg/collector/corechecks/containers/kubelet/provider/kubelet/provider.go index 2307903d85cd0..5f3fe21e3d85c 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/kubelet/provider.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/kubelet/provider.go @@ -94,11 +94,12 @@ type Provider struct { filter *containers.Filter store workloadmeta.Component podUtils *common.PodUtils + tagger tagger.Component prometheus.Provider } // NewProvider creates and returns a new Provider, configured based on the values passed in. -func NewProvider(filter *containers.Filter, config *common.KubeletConfig, store workloadmeta.Component, podUtils *common.PodUtils) (*Provider, error) { +func NewProvider(filter *containers.Filter, config *common.KubeletConfig, store workloadmeta.Component, podUtils *common.PodUtils, tagger tagger.Component) (*Provider, error) { // clone instance configuration so we can set our default metrics kubeletConfig := *config @@ -115,6 +116,7 @@ func NewProvider(filter *containers.Filter, config *common.KubeletConfig, store filter: filter, store: store, podUtils: podUtils, + tagger: tagger, } transformers := prometheus.Transformers{ @@ -185,7 +187,7 @@ func (p *Provider) kubeletContainerLogFilesystemUsedBytes(metricFam *prom.Metric continue } - tags, _ := tagger.Tag(types.NewEntityID(types.ContainerID, cID), types.HighCardinality) + tags, _ := p.tagger.Tag(types.NewEntityID(types.ContainerID, cID), types.HighCardinality) if len(tags) == 0 { log.Debugf("Tags not found for container: %s/%s/%s:%s", metric.Metric["namespace"], metric.Metric["pod"], metric.Metric["container"], cID) } diff --git a/pkg/collector/corechecks/containers/kubelet/provider/kubelet/provider_test.go b/pkg/collector/corechecks/containers/kubelet/provider/kubelet/provider_test.go index 096b63b898140..bbb51a4ec18f9 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/kubelet/provider_test.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/kubelet/provider_test.go @@ -19,6 +19,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/common/types" + "github.com/DataDog/datadog-agent/comp/core/tagger" taggercommon "github.com/DataDog/datadog-agent/comp/core/tagger/common" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" taggertypes "github.com/DataDog/datadog-agent/comp/core/tagger/types" @@ -123,6 +124,7 @@ type ProviderTestSuite struct { provider *Provider mockSender *mocksender.MockSender store workloadmeta.Component + tagger tagger.Component } func (suite *ProviderTestSuite) SetupTest() { @@ -138,14 +140,15 @@ func (suite *ProviderTestSuite) SetupTest() { suite.mockSender = mockSender fakeTagger := taggerimpl.SetupFakeTagger(suite.T()) - defer fakeTagger.ResetTagger() + for entity, tags := range commontesting.CommonTags { prefix, id, _ := taggercommon.ExtractPrefixAndID(entity) entityID := taggertypes.NewEntityID(prefix, id) fakeTagger.SetTags(entityID, "foo", tags, nil, nil, nil) } + suite.tagger = fakeTagger - podUtils := common.NewPodUtils() + podUtils := common.NewPodUtils(fakeTagger) podsFile := "../../testdata/pods.json" err = commontesting.StorePopulatedFromFile(store, podsFile, podUtils) @@ -172,6 +175,7 @@ func (suite *ProviderTestSuite) SetupTest() { config, store, podUtils, + fakeTagger, ) assert.NoError(suite.T(), err) suite.provider = p diff --git a/pkg/collector/corechecks/containers/kubelet/provider/pod/provider.go b/pkg/collector/corechecks/containers/kubelet/provider/pod/provider.go index 38ee589c389cf..2d51552af013b 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/pod/provider.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/pod/provider.go @@ -47,14 +47,16 @@ type Provider struct { filter *containers.Filter config *common.KubeletConfig podUtils *common.PodUtils + tagger tagger.Component } // NewProvider returns a new Provider -func NewProvider(filter *containers.Filter, config *common.KubeletConfig, podUtils *common.PodUtils) *Provider { +func NewProvider(filter *containers.Filter, config *common.KubeletConfig, podUtils *common.PodUtils, tagger tagger.Component) *Provider { return &Provider{ filter: filter, config: config, podUtils: podUtils, + tagger: tagger, } } @@ -125,7 +127,7 @@ func (p *Provider) generateContainerSpecMetrics(sender sender.Sender, pod *kubel return } - tagList, _ := tagger.Tag(containerID, types.HighCardinality) + tagList, _ := p.tagger.Tag(containerID, types.HighCardinality) // Skip recording containers without kubelet information in tagger or if there are no tags if !isTagKeyPresent(kubeNamespaceTag, tagList) || len(tagList) == 0 { return @@ -145,7 +147,7 @@ func (p *Provider) generateContainerStatusMetrics(sender sender.Sender, pod *kub return } - tagList, _ := tagger.Tag(containerID, types.OrchestratorCardinality) + tagList, _ := p.tagger.Tag(containerID, types.OrchestratorCardinality) // Skip recording containers without kubelet information in tagger or if there are no tags if !isTagKeyPresent(kubeNamespaceTag, tagList) || len(tagList) == 0 { return @@ -189,7 +191,7 @@ func (r *runningAggregator) recordContainer(p *Provider, pod *kubelet.Pod, cStat return } r.podHasRunningContainers[pod.Metadata.UID] = true - tagList, _ := tagger.Tag(containerID, types.LowCardinality) + tagList, _ := p.tagger.Tag(containerID, types.LowCardinality) // Skip recording containers without kubelet information in tagger or if there are no tags if !isTagKeyPresent(kubeNamespaceTag, tagList) || len(tagList) == 0 { return @@ -211,7 +213,7 @@ func (r *runningAggregator) recordPod(p *Provider, pod *kubelet.Pod) { return } entityID := types.NewEntityID(types.KubernetesPodUID, podID) - tagList, _ := tagger.Tag(entityID, types.LowCardinality) + tagList, _ := p.tagger.Tag(entityID, types.LowCardinality) if len(tagList) == 0 { return } diff --git a/pkg/collector/corechecks/containers/kubelet/provider/pod/provider_test.go b/pkg/collector/corechecks/containers/kubelet/provider/pod/provider_test.go index 50ac558c64c7f..0f593fed47711 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/pod/provider_test.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/pod/provider_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/common/types" + "github.com/DataDog/datadog-agent/comp/core/tagger" taggercommon "github.com/DataDog/datadog-agent/comp/core/tagger/common" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" taggertypes "github.com/DataDog/datadog-agent/comp/core/tagger/types" @@ -100,6 +101,7 @@ type ProviderTestSuite struct { testServer *httptest.Server mockSender *mocksender.MockSender kubeUtil kubelet.KubeUtilInterface + tagger tagger.Component } func (suite *ProviderTestSuite) SetupTest() { @@ -115,7 +117,7 @@ func (suite *ProviderTestSuite) SetupTest() { suite.mockSender = mockSender fakeTagger := taggerimpl.SetupFakeTagger(suite.T()) - defer fakeTagger.ResetTagger() + for entity, tags := range commontesting.CommonTags { prefix, id, _ := taggercommon.ExtractPrefixAndID(entity) entityID := taggertypes.NewEntityID(prefix, id) @@ -143,13 +145,16 @@ func (suite *ProviderTestSuite) SetupTest() { }, } + suite.tagger = fakeTagger + suite.provider = &Provider{ config: config, filter: &containers.Filter{ Enabled: true, NameExcludeList: []*regexp.Regexp{regexp.MustCompile("agent-excluded")}, }, - podUtils: common.NewPodUtils(), + podUtils: common.NewPodUtils(fakeTagger), + tagger: fakeTagger, } } diff --git a/pkg/collector/corechecks/containers/kubelet/provider/probe/provider.go b/pkg/collector/corechecks/containers/kubelet/provider/probe/provider.go index ca8d8369e3009..13baf09751679 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/probe/provider.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/probe/provider.go @@ -27,13 +27,15 @@ type Provider struct { filter *containers.Filter store workloadmeta.Component prometheus.Provider + tagger tagger.Component } // NewProvider returns a metrics prometheus kubelet provider and an error -func NewProvider(filter *containers.Filter, config *common.KubeletConfig, store workloadmeta.Component) (*Provider, error) { +func NewProvider(filter *containers.Filter, config *common.KubeletConfig, store workloadmeta.Component, tagger tagger.Component) (*Provider, error) { provider := &Provider{ filter: filter, store: store, + tagger: tagger, } transformers := prometheus.Transformers{ @@ -88,7 +90,7 @@ func (p *Provider) proberProbeTotal(metricFam *prom.MetricFamily, sender sender. continue } - tags, _ := tagger.Tag(types.NewEntityID(types.ContainerID, cID), types.HighCardinality) + tags, _ := p.tagger.Tag(types.NewEntityID(types.ContainerID, cID), types.HighCardinality) if len(tags) == 0 { continue } diff --git a/pkg/collector/corechecks/containers/kubelet/provider/probe/provider_test.go b/pkg/collector/corechecks/containers/kubelet/provider/probe/provider_test.go index 2b21551c07201..0a7fde8493d1f 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/probe/provider_test.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/probe/provider_test.go @@ -274,14 +274,14 @@ func TestProvider_Provide(t *testing.T) { mockSender.SetupAcceptAll() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + for entity, tags := range probeTags { prefix, id, _ := taggercommon.ExtractPrefixAndID(entity) entityID := taggertypes.NewEntityID(prefix, id) fakeTagger.SetTags(entityID, "foo", tags, nil, nil, nil) } - err = commontesting.StorePopulatedFromFile(store, tt.podsFile, common.NewPodUtils()) + err = commontesting.StorePopulatedFromFile(store, tt.podsFile, common.NewPodUtils(fakeTagger)) if err != nil { t.Errorf("unable to populate store from file at: %s, err: %v", tt.podsFile, err) } @@ -314,6 +314,7 @@ func TestProvider_Provide(t *testing.T) { }, config, store, + fakeTagger, ) assert.NoError(t, err) diff --git a/pkg/collector/corechecks/containers/kubelet/provider/slis/provider_test.go b/pkg/collector/corechecks/containers/kubelet/provider/slis/provider_test.go index 47e1d6e11cb9c..75ce2a77a09f2 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/slis/provider_test.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/slis/provider_test.go @@ -15,6 +15,7 @@ import ( "testing" "github.com/DataDog/datadog-agent/comp/core" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" workloadmetamock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/mock" @@ -170,7 +171,9 @@ func TestProvider_Provide(t *testing.T) { mockSender := mocksender.NewMockSender(checkid.ID(t.Name())) mockSender.SetupAcceptAll() - err = commontesting.StorePopulatedFromFile(store, tt.podsFile, common.NewPodUtils()) + fakeTagger := taggerimpl.SetupFakeTagger(t) + + err = commontesting.StorePopulatedFromFile(store, tt.podsFile, common.NewPodUtils(fakeTagger)) if err != nil { t.Errorf("unable to populate store from file at: %s, err: %v", tt.podsFile, err) } @@ -236,7 +239,9 @@ func TestProvider_DisableProvider(t *testing.T) { mockSender := mocksender.NewMockSender(checkid.ID(t.Name())) mockSender.SetupAcceptAll() - err = commontesting.StorePopulatedFromFile(store, "../../testdata/pods.json", common.NewPodUtils()) + fakeTagger := taggerimpl.SetupFakeTagger(t) + + err = commontesting.StorePopulatedFromFile(store, "../../testdata/pods.json", common.NewPodUtils(fakeTagger)) if err != nil { t.Errorf("unable to populate store from file at: %s, err: %v", "../../testdata/pods.json", err) } diff --git a/pkg/collector/corechecks/containers/kubelet/provider/summary/provider.go b/pkg/collector/corechecks/containers/kubelet/provider/summary/provider.go index 37635048ad41d..c3662f9cd90a4 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/summary/provider.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/summary/provider.go @@ -36,13 +36,16 @@ type Provider struct { filter *containers.Filter config *common.KubeletConfig store workloadmeta.Component + tagger tagger.Component defaultRateFilterList []*regexp.Regexp } // NewProvider is created by filter, config and workloadmeta func NewProvider(filter *containers.Filter, config *common.KubeletConfig, - store workloadmeta.Component) *Provider { + store workloadmeta.Component, + tagger tagger.Component, +) *Provider { defaultRateFilterList := []*regexp.Regexp{ regexp.MustCompile("diskio[.]io_service_bytes[.]stats[.]total"), regexp.MustCompile("network[.].._bytes"), @@ -53,6 +56,7 @@ func NewProvider(filter *containers.Filter, filter: filter, config: config, store: store, + tagger: tagger, defaultRateFilterList: defaultRateFilterList, } } @@ -150,7 +154,7 @@ func (p *Provider) processPodStats(sender sender.Sender, } entityID := types.NewEntityID(types.KubernetesPodUID, podStats.PodRef.UID) - podTags, _ := tagger.Tag(entityID, + podTags, _ := p.tagger.Tag(entityID, types.OrchestratorCardinality) if len(podTags) == 0 { @@ -221,7 +225,7 @@ func (p *Provider) processContainerStats(sender sender.Sender, podStats.PodRef.Namespace) { continue } - tags, err := tagger.Tag(types.NewEntityID(types.ContainerID, ctr.ID), types.HighCardinality) + tags, err := p.tagger.Tag(types.NewEntityID(types.ContainerID, ctr.ID), types.HighCardinality) if err != nil || len(tags) == 0 { log.Debugf("Tags not found for container: %s/%s/%s:%s - no metrics will be sent", podStats.PodRef.Namespace, podStats.PodRef.Name, containerName, ctr.ID) diff --git a/pkg/collector/corechecks/containers/kubelet/provider/summary/provider_test.go b/pkg/collector/corechecks/containers/kubelet/provider/summary/provider_test.go index 0661462956d71..66e909cb9d13d 100644 --- a/pkg/collector/corechecks/containers/kubelet/provider/summary/provider_test.go +++ b/pkg/collector/corechecks/containers/kubelet/provider/summary/provider_test.go @@ -336,7 +336,7 @@ func TestProvider_Provide(t *testing.T) { mockSender.SetupAcceptAll() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + for entity, tags := range entityTags { prefix, id, _ := taggercommon.ExtractPrefixAndID(entity) entityID := taggertypes.NewEntityID(prefix, id) @@ -365,6 +365,7 @@ func TestProvider_Provide(t *testing.T) { }, config, store, + fakeTagger, ) assert.NoError(t, err) diff --git a/pkg/collector/corechecks/containers/kubelet/stub.go b/pkg/collector/corechecks/containers/kubelet/stub.go index 5feec0f0df107..1218461201f9d 100644 --- a/pkg/collector/corechecks/containers/kubelet/stub.go +++ b/pkg/collector/corechecks/containers/kubelet/stub.go @@ -9,6 +9,7 @@ package kubelet import ( + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -19,6 +20,6 @@ const ( CheckName = "kubelet" ) -func Factory(_ workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(workloadmeta.Component, tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/ebpf/oomkill/oom_kill.go b/pkg/collector/corechecks/ebpf/oomkill/oom_kill.go index 33b9393ac9af2..5ad080692ca42 100644 --- a/pkg/collector/corechecks/ebpf/oomkill/oom_kill.go +++ b/pkg/collector/corechecks/ebpf/oomkill/oom_kill.go @@ -48,17 +48,21 @@ type OOMKillConfig struct { type OOMKillCheck struct { core.CheckBase instance *OOMKillConfig + tagger tagger.Component } // Factory creates a new check factory -func Factory() optional.Option[func() check.Check] { - return optional.NewOption(newCheck) +func Factory(tagger tagger.Component) optional.Option[func() check.Check] { + return optional.NewOption(func() check.Check { + return newCheck(tagger) + }) } -func newCheck() check.Check { +func newCheck(tagger tagger.Component) check.Check { return &OOMKillCheck{ CheckBase: core.NewCheckBase(CheckName), instance: &OOMKillConfig{}, + tagger: tagger, } } @@ -118,7 +122,7 @@ func (m *OOMKillCheck) Run() error { entityID := types.NewEntityID(types.ContainerID, containerID) var tags []string if !entityID.Empty() { - tags, err = tagger.Tag(entityID, tagger.ChecksCardinality()) + tags, err = m.tagger.Tag(entityID, m.tagger.ChecksCardinality()) if err != nil { log.Errorf("Error collecting tags for container %s: %s", containerID, err) } diff --git a/pkg/collector/corechecks/ebpf/oomkill/stub.go b/pkg/collector/corechecks/ebpf/oomkill/stub.go index d94449b1b2b15..ba05e04befa9b 100644 --- a/pkg/collector/corechecks/ebpf/oomkill/stub.go +++ b/pkg/collector/corechecks/ebpf/oomkill/stub.go @@ -9,6 +9,7 @@ package oomkill import ( + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" ) @@ -19,6 +20,6 @@ const ( ) // Factory creates a new check factory -func Factory() optional.Option[func() check.Check] { +func Factory(tagger tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/ebpf/tcpqueuelength/stub.go b/pkg/collector/corechecks/ebpf/tcpqueuelength/stub.go index 65552c3c8d83b..56da220ab3db2 100644 --- a/pkg/collector/corechecks/ebpf/tcpqueuelength/stub.go +++ b/pkg/collector/corechecks/ebpf/tcpqueuelength/stub.go @@ -9,6 +9,7 @@ package tcpqueuelength import ( + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" ) @@ -19,6 +20,6 @@ const ( ) // Factory creates a new check factory -func Factory() optional.Option[func() check.Check] { +func Factory(tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/ebpf/tcpqueuelength/tcp_queue_length.go b/pkg/collector/corechecks/ebpf/tcpqueuelength/tcp_queue_length.go index 4a0fecf278bc6..4458c8d21609d 100644 --- a/pkg/collector/corechecks/ebpf/tcpqueuelength/tcp_queue_length.go +++ b/pkg/collector/corechecks/ebpf/tcpqueuelength/tcp_queue_length.go @@ -44,17 +44,21 @@ type TCPQueueLengthConfig struct { type TCPQueueLengthCheck struct { core.CheckBase instance *TCPQueueLengthConfig + tagger tagger.Component } // Factory creates a new check factory -func Factory() optional.Option[func() check.Check] { - return optional.NewOption(newCheck) +func Factory(tagger tagger.Component) optional.Option[func() check.Check] { + return optional.NewOption(func() check.Check { + return newCheck(tagger) + }) } -func newCheck() check.Check { +func newCheck(tagger tagger.Component) check.Check { return &TCPQueueLengthCheck{ CheckBase: core.NewCheckBase(CheckName), instance: &TCPQueueLengthConfig{}, + tagger: tagger, } } @@ -113,7 +117,7 @@ func (t *TCPQueueLengthCheck) Run() error { entityID := types.NewEntityID(types.ContainerID, containerID) var tags []string if !entityID.Empty() { - tags, err = tagger.Tag(entityID, types.HighCardinality) + tags, err = t.tagger.Tag(entityID, types.HighCardinality) if err != nil { log.Errorf("Error collecting tags for container %s: %s", k, err) } diff --git a/pkg/collector/corechecks/gpu/nvmlmetrics/clocks.go b/pkg/collector/corechecks/gpu/nvidia/clocks.go similarity index 99% rename from pkg/collector/corechecks/gpu/nvmlmetrics/clocks.go rename to pkg/collector/corechecks/gpu/nvidia/clocks.go index 0d2530cb237ac..1cb15e998c990 100644 --- a/pkg/collector/corechecks/gpu/nvmlmetrics/clocks.go +++ b/pkg/collector/corechecks/gpu/nvidia/clocks.go @@ -5,7 +5,7 @@ //go:build linux -package nvmlmetrics +package nvidia import ( "fmt" diff --git a/pkg/collector/corechecks/gpu/nvmlmetrics/collector.go b/pkg/collector/corechecks/gpu/nvidia/collector.go similarity index 97% rename from pkg/collector/corechecks/gpu/nvmlmetrics/collector.go rename to pkg/collector/corechecks/gpu/nvidia/collector.go index 2b4e105cc9e25..e801336dadb7e 100644 --- a/pkg/collector/corechecks/gpu/nvmlmetrics/collector.go +++ b/pkg/collector/corechecks/gpu/nvidia/collector.go @@ -5,12 +5,12 @@ //go:build linux -// Package nvmlmetrics holds the logic to collect metrics from the NVIDIA Management Library (NVML). +// Package nvidia holds the logic to collect metrics from the NVIDIA Management Library (NVML). // The main entry point is the BuildCollectors functions, which returns a set of collectors that will // gather metrics from the available NVIDIA devices on the system. Each collector is responsible for // a specific subsystem of metrics, such as device metrics, GPM metrics, etc. The collected metrics will // be returned with the associated tags for each device. -package nvmlmetrics +package nvidia import ( "errors" diff --git a/pkg/collector/corechecks/gpu/nvmlmetrics/collector_test.go b/pkg/collector/corechecks/gpu/nvidia/collector_test.go similarity index 99% rename from pkg/collector/corechecks/gpu/nvmlmetrics/collector_test.go rename to pkg/collector/corechecks/gpu/nvidia/collector_test.go index b4100dd85429b..67dbfd0f6f92f 100644 --- a/pkg/collector/corechecks/gpu/nvmlmetrics/collector_test.go +++ b/pkg/collector/corechecks/gpu/nvidia/collector_test.go @@ -5,7 +5,7 @@ //go:build linux -package nvmlmetrics +package nvidia import ( "errors" diff --git a/pkg/collector/corechecks/gpu/nvmlmetrics/convert.go b/pkg/collector/corechecks/gpu/nvidia/convert.go similarity index 98% rename from pkg/collector/corechecks/gpu/nvmlmetrics/convert.go rename to pkg/collector/corechecks/gpu/nvidia/convert.go index 769371e6b74eb..1d912db091530 100644 --- a/pkg/collector/corechecks/gpu/nvmlmetrics/convert.go +++ b/pkg/collector/corechecks/gpu/nvidia/convert.go @@ -5,7 +5,7 @@ //go:build linux -package nvmlmetrics +package nvidia import ( "bytes" diff --git a/pkg/collector/corechecks/gpu/nvmlmetrics/device.go b/pkg/collector/corechecks/gpu/nvidia/device.go similarity index 99% rename from pkg/collector/corechecks/gpu/nvmlmetrics/device.go rename to pkg/collector/corechecks/gpu/nvidia/device.go index 8ee6ec9b5e9f1..82ff9064b27e6 100644 --- a/pkg/collector/corechecks/gpu/nvmlmetrics/device.go +++ b/pkg/collector/corechecks/gpu/nvidia/device.go @@ -5,7 +5,7 @@ //go:build linux -package nvmlmetrics +package nvidia import ( "fmt" diff --git a/pkg/collector/corechecks/gpu/nvmlmetrics/fields.go b/pkg/collector/corechecks/gpu/nvidia/fields.go similarity index 99% rename from pkg/collector/corechecks/gpu/nvmlmetrics/fields.go rename to pkg/collector/corechecks/gpu/nvidia/fields.go index a50b06ac476d6..a111f6f55f776 100644 --- a/pkg/collector/corechecks/gpu/nvmlmetrics/fields.go +++ b/pkg/collector/corechecks/gpu/nvidia/fields.go @@ -5,7 +5,7 @@ //go:build linux -package nvmlmetrics +package nvidia import ( "fmt" diff --git a/pkg/collector/corechecks/gpu/nvmlmetrics/mocks.go b/pkg/collector/corechecks/gpu/nvidia/mocks.go similarity index 99% rename from pkg/collector/corechecks/gpu/nvmlmetrics/mocks.go rename to pkg/collector/corechecks/gpu/nvidia/mocks.go index e512aea2de87c..1e6fd9eb6b848 100644 --- a/pkg/collector/corechecks/gpu/nvmlmetrics/mocks.go +++ b/pkg/collector/corechecks/gpu/nvidia/mocks.go @@ -2,7 +2,7 @@ //go:build linux && test -package nvmlmetrics +package nvidia import mock "github.com/stretchr/testify/mock" diff --git a/pkg/collector/corechecks/gpu/nvmlmetrics/remappedrows.go b/pkg/collector/corechecks/gpu/nvidia/remappedrows.go similarity index 99% rename from pkg/collector/corechecks/gpu/nvmlmetrics/remappedrows.go rename to pkg/collector/corechecks/gpu/nvidia/remappedrows.go index 16a77a189eaf3..c20a84b57887c 100644 --- a/pkg/collector/corechecks/gpu/nvmlmetrics/remappedrows.go +++ b/pkg/collector/corechecks/gpu/nvidia/remappedrows.go @@ -5,7 +5,7 @@ //go:build linux -package nvmlmetrics +package nvidia import ( "fmt" diff --git a/pkg/collector/corechecks/loader.go b/pkg/collector/corechecks/loader.go index 31eab283f1fe5..e25026364abb3 100644 --- a/pkg/collector/corechecks/loader.go +++ b/pkg/collector/corechecks/loader.go @@ -10,6 +10,7 @@ import ( "fmt" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -82,7 +83,7 @@ func (gl *GoCheckLoader) String() string { } func init() { - factory := func(sender.SenderManager, optional.Option[integrations.Component]) (check.Loader, error) { + factory := func(sender.SenderManager, optional.Option[integrations.Component], tagger.Component) (check.Loader, error) { return NewGoCheckLoader() } diff --git a/pkg/collector/corechecks/networkpath/networkpath.go b/pkg/collector/corechecks/networkpath/networkpath.go index 8c810bc423509..31040c24b68b2 100644 --- a/pkg/collector/corechecks/networkpath/networkpath.go +++ b/pkg/collector/corechecks/networkpath/networkpath.go @@ -74,6 +74,12 @@ func (c *Check) Run() error { path.Destination.Service = c.config.DestinationService path.Tags = c.config.Tags + // Perform reverse DNS lookup + path.Destination.ReverseDNSHostname = traceroute.GetHostname(path.Destination.IPAddress) + for i := range path.Hops { + path.Hops[i].Hostname = traceroute.GetHostname(path.Hops[i].IPAddress) + } + // send to EP err = c.SendNetPathMDToEP(senderInstance, path) if err != nil { diff --git a/pkg/collector/corechecks/oracle/activity_queries.go b/pkg/collector/corechecks/oracle/activity_queries.go index 6c4c4694089bd..4ce636e7471a3 100644 --- a/pkg/collector/corechecks/oracle/activity_queries.go +++ b/pkg/collector/corechecks/oracle/activity_queries.go @@ -66,8 +66,8 @@ const activityQueryOnView12 = `SELECT /* DD_ACTIVITY_SAMPLING */ 'CPU' END wait_class, wait_time_micro, - dbms_lob.substr(sql_fulltext, :sql_substr_length, 1) sql_fulltext, - dbms_lob.substr(prev_sql_fulltext, :sql_substr_length, 1) prev_sql_fulltext, + dbms_lob.substr(sql_fulltext, :sql_substr_length_1, 1) sql_fulltext, + dbms_lob.substr(prev_sql_fulltext, :sql_substr_length_2, 1) prev_sql_fulltext, pdb_name, command_name FROM sys.dd_session @@ -133,8 +133,8 @@ const activityQueryOnView11 = `SELECT /* DD_ACTIVITY_SAMPLING */ 'CPU' END wait_class, wait_time_micro, - dbms_lob.substr(sql_fulltext, :sql_substr_length, 1) sql_fulltext, - dbms_lob.substr(prev_sql_fulltext, :sql_substr_length, 1) prev_sql_fulltext, + dbms_lob.substr(sql_fulltext, :sql_substr_length_1, 1) sql_fulltext, + dbms_lob.substr(prev_sql_fulltext, :sql_substr_length_2, 1) prev_sql_fulltext, command_name FROM sys.dd_session WHERE @@ -199,8 +199,8 @@ ELSE END wait_class, s.wait_time_micro, c.name as pdb_name, -dbms_lob.substr(sq.sql_fulltext, :sql_substr_length, 1) sql_fulltext, -dbms_lob.substr(sq_prev.sql_fulltext, :sql_substr_length, 1) prev_sql_fulltext, +dbms_lob.substr(sq.sql_fulltext, :sql_substr_length_1, 1) sql_fulltext, +dbms_lob.substr(sq_prev.sql_fulltext, :sql_substr_length_2, 1) prev_sql_fulltext, comm.command_name FROM v$session s, diff --git a/pkg/collector/corechecks/oracle/testutil.go b/pkg/collector/corechecks/oracle/testutil.go index f230b3afbfb0b..4f9befd877b32 100644 --- a/pkg/collector/corechecks/oracle/testutil.go +++ b/pkg/collector/corechecks/oracle/testutil.go @@ -153,6 +153,11 @@ func newTestCheck(t *testing.T, connectConfig config.ConnectionConfig, instanceC assert.Contains(t, c.configTags, dbmsTag, "c.configTags doesn't contain static tags") } + if oracleLibDir := os.Getenv("ORACLE_TEST_ORACLE_CLIENT_LIB_DIR"); oracleLibDir != "" { + c.config.InstanceConfig.OracleClientLibDir = oracleLibDir + c.config.InstanceConfig.OracleClient = true + } + return c, sender } diff --git a/pkg/collector/corechecks/orchestrator/ecs/ecs.go b/pkg/collector/corechecks/orchestrator/ecs/ecs.go index 5afdee033a1bc..96213cfabe7c8 100644 --- a/pkg/collector/corechecks/orchestrator/ecs/ecs.go +++ b/pkg/collector/corechecks/orchestrator/ecs/ecs.go @@ -22,7 +22,9 @@ import ( "go.uber.org/atomic" model "github.com/DataDog/agent-payload/v5/process" + "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -48,6 +50,7 @@ type Check struct { collectors []collectors.Collector groupID *atomic.Int32 workloadmetaStore workloadmeta.Component + tagger tagger.Component isECSCollectionEnabledFunc func() bool awsAccountID int clusterName string @@ -58,14 +61,15 @@ type Check struct { } // Factory creates a new check factory -func Factory(store workloadmeta.Component) optional.Option[func() check.Check] { - return optional.NewOption(func() check.Check { return newCheck(store) }) +func Factory(store workloadmeta.Component, tagger tagger.Component) optional.Option[func() check.Check] { + return optional.NewOption(func() check.Check { return newCheck(store, tagger) }) } -func newCheck(store workloadmeta.Component) check.Check { +func newCheck(store workloadmeta.Component, tagger tagger.Component) check.Check { return &Check{ CheckBase: core.NewCheckBase(CheckName), workloadmetaStore: store, + tagger: tagger, config: oconfig.NewDefaultOrchestratorConfig(), groupID: atomic.NewInt32(rand.Int31()), isECSCollectionEnabledFunc: oconfig.IsOrchestratorECSExplorerEnabled, @@ -198,7 +202,7 @@ func (c *Check) initConfig() { } func (c *Check) initCollectors() { - c.collectors = []collectors.Collector{ecs.NewTaskCollector()} + c.collectors = []collectors.Collector{ecs.NewTaskCollector(c.tagger)} } // initClusterID generates a cluster ID from the AWS account ID, region and cluster name. diff --git a/pkg/collector/corechecks/orchestrator/ecs/ecs_test.go b/pkg/collector/corechecks/orchestrator/ecs/ecs_test.go index e3912ffe26711..b8c72fc47a3f1 100644 --- a/pkg/collector/corechecks/orchestrator/ecs/ecs_test.go +++ b/pkg/collector/corechecks/orchestrator/ecs/ecs_test.go @@ -15,6 +15,8 @@ import ( "go.uber.org/atomic" "github.com/DataDog/agent-payload/v5/process" + + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/cluster/orchestrator/transformers/ecs" @@ -91,7 +93,7 @@ func (s *fakeSender) Flush() []process.MessageBody { } func TestNotECS(t *testing.T) { - check, _, sender := prepareTest(false, "notECS") + check, _, sender := prepareTest(t, false, "notECS") err := check.Run() require.NoError(t, err) require.Len(t, sender.messages, 0) @@ -107,7 +109,7 @@ func TestECSV4Disabled(t *testing.T) { } func testECS(v4 bool, t *testing.T) { - check, store, sender := prepareTest(v4, "ecs") + check, store, sender := prepareTest(t, v4, "ecs") // add 2 tasks to fake workloadmetaStore task1Id := "123" @@ -151,7 +153,9 @@ func testECS(v4 bool, t *testing.T) { } // prepareTest returns a check, a fake workloadmeta store and a fake sender -func prepareTest(v4 bool, env string) (*Check, *fakeWorkloadmetaStore, *fakeSender) { +func prepareTest(t *testing.T, v4 bool, env string) (*Check, *fakeWorkloadmetaStore, *fakeSender) { + t.Helper() + orchConfig := oconfig.NewDefaultOrchestratorConfig() orchConfig.OrchestrationCollectionEnabled = true @@ -162,9 +166,12 @@ func prepareTest(v4 bool, env string) (*Check, *fakeWorkloadmetaStore, *fakeSend systemInfo, _ := checks.CollectSystemInfo() + tagger := nooptagger.NewTaggerClient() + c := &Check{ sender: sender, workloadmetaStore: store, + tagger: tagger, config: orchConfig, groupID: atomic.NewInt32(0), systemInfo: systemInfo, diff --git a/pkg/collector/corechecks/orchestrator/ecs/stub.go b/pkg/collector/corechecks/orchestrator/ecs/stub.go index 57fbd86bd0f92..20b811e2f6288 100644 --- a/pkg/collector/corechecks/orchestrator/ecs/stub.go +++ b/pkg/collector/corechecks/orchestrator/ecs/stub.go @@ -9,6 +9,7 @@ package ecs import ( + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -20,6 +21,6 @@ const ( ) // Factory creates a new check factory -func Factory(_ workloadmeta.Component) optional.Option[func() check.Check] { +func Factory(workloadmeta.Component, tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/orchestrator/pod/pod.go b/pkg/collector/corechecks/orchestrator/pod/pod.go index 9d9808594b65a..181383cbf8f2d 100644 --- a/pkg/collector/corechecks/orchestrator/pod/pod.go +++ b/pkg/collector/corechecks/orchestrator/pod/pod.go @@ -18,6 +18,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -55,23 +56,25 @@ type Check struct { systemInfo *model.SystemInfo store workloadmeta.Component cfg config.Component + tagger tagger.Component } // Factory creates a new check factory -func Factory(store workloadmeta.Component, cfg config.Component) optional.Option[func() check.Check] { +func Factory(store workloadmeta.Component, cfg config.Component, tagger tagger.Component) optional.Option[func() check.Check] { return optional.NewOption( func() check.Check { - return newCheck(store, cfg) + return newCheck(store, cfg, tagger) }, ) } -func newCheck(store workloadmeta.Component, cfg config.Component) check.Check { +func newCheck(store workloadmeta.Component, cfg config.Component, tagger tagger.Component) check.Check { return &Check{ CheckBase: core.NewCheckBase(CheckName), config: oconfig.NewDefaultOrchestratorConfig(), store: store, cfg: cfg, + tagger: tagger, } } @@ -104,7 +107,7 @@ func (c *Check) Configure( } if c.processor == nil { - c.processor = processors.NewProcessor(k8sProcessors.NewPodHandlers(c.cfg, c.store)) + c.processor = processors.NewProcessor(k8sProcessors.NewPodHandlers(c.cfg, c.store, c.tagger)) } if c.sender == nil { diff --git a/pkg/collector/corechecks/orchestrator/pod/pod_test.go b/pkg/collector/corechecks/orchestrator/pod/pod_test.go index 0b32059a2a848..35a928e017c6f 100644 --- a/pkg/collector/corechecks/orchestrator/pod/pod_test.go +++ b/pkg/collector/corechecks/orchestrator/pod/pod_test.go @@ -25,6 +25,7 @@ import ( "github.com/DataDog/agent-payload/v5/process" "github.com/DataDog/datadog-agent/comp/core" + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" @@ -113,6 +114,7 @@ type PodTestSuite struct { testServer *httptest.Server sender *fakeSender kubeUtil kubelet.KubeUtilInterface + tagger tagger.Mock } func (suite *PodTestSuite) SetupSuite() { @@ -145,11 +147,15 @@ func (suite *PodTestSuite) SetupSuite() { workloadmetafxmock.MockModule(workloadmeta.NewParams()), )) + fakeTagger := taggerimpl.SetupFakeTagger(suite.T()) + suite.tagger = fakeTagger + suite.check = &Check{ sender: sender, - processor: processors.NewProcessor(k8sProcessors.NewPodHandlers(mockConfig, mockStore)), + processor: processors.NewProcessor(k8sProcessors.NewPodHandlers(mockConfig, mockStore, fakeTagger)), hostName: testHostName, config: oconfig.NewDefaultOrchestratorConfig(), + tagger: fakeTagger, } } @@ -168,11 +174,8 @@ func (suite *PodTestSuite) TestPodCheck() { cache.Cache.Set(cacheKey, strings.Repeat("1", 36), cache.NoExpiration) } - fakeTagger := taggerimpl.SetupFakeTagger(suite.T()) - defer func() { cache.Cache.Set(cacheKey, cachedClusterID, cache.NoExpiration) - fakeTagger.ResetTagger() }() err := suite.check.Run() diff --git a/pkg/collector/corechecks/orchestrator/pod/stub.go b/pkg/collector/corechecks/orchestrator/pod/stub.go index 833f879dc2ab7..74cb3cfb7ca96 100644 --- a/pkg/collector/corechecks/orchestrator/pod/stub.go +++ b/pkg/collector/corechecks/orchestrator/pod/stub.go @@ -10,6 +10,7 @@ package pod import ( "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -21,6 +22,6 @@ const ( ) // Factory creates a new check factory -func Factory(_ workloadmeta.Component, _ config.Component) optional.Option[func() check.Check] { +func Factory(workloadmeta.Component, config.Component, tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/sbom/check.go b/pkg/collector/corechecks/sbom/check.go index 53e26c4a198e2..25367efdd1614 100644 --- a/pkg/collector/corechecks/sbom/check.go +++ b/pkg/collector/corechecks/sbom/check.go @@ -16,6 +16,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -108,6 +109,7 @@ func (c *Config) Parse(data []byte) error { type Check struct { core.CheckBase workloadmetaStore workloadmeta.Component + tagger tagger.Component instance *Config processor *processor sender sender.Sender @@ -116,11 +118,12 @@ type Check struct { } // Factory returns a new check factory -func Factory(store workloadmeta.Component, cfg config.Component) optional.Option[func() check.Check] { +func Factory(store workloadmeta.Component, cfg config.Component, tagger tagger.Component) optional.Option[func() check.Check] { return optional.NewOption(func() check.Check { return core.NewLongRunningCheckWrapper(&Check{ CheckBase: core.NewCheckBase(CheckName), workloadmetaStore: store, + tagger: tagger, instance: &Config{}, stopCh: make(chan struct{}), cfg: cfg, @@ -153,6 +156,7 @@ func (c *Check) Configure(senderManager sender.SenderManager, _ uint64, config, if c.processor, err = newProcessor( c.workloadmetaStore, sender, + c.tagger, c.instance.ChunkSize, time.Duration(c.instance.NewSBOMMaxLatencySeconds)*time.Second, c.cfg.GetBool("sbom.host.enabled"), diff --git a/pkg/collector/corechecks/sbom/check_no_trivy.go b/pkg/collector/corechecks/sbom/check_no_trivy.go index 7fd73ceff0a9d..50bfcfa91061b 100644 --- a/pkg/collector/corechecks/sbom/check_no_trivy.go +++ b/pkg/collector/corechecks/sbom/check_no_trivy.go @@ -9,6 +9,7 @@ package sbom import ( "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -20,6 +21,6 @@ const ( ) // Factory returns a new check factory -func Factory(_ workloadmeta.Component, _ config.Component) optional.Option[func() check.Check] { +func Factory(workloadmeta.Component, config.Component, tagger.Component) optional.Option[func() check.Check] { return optional.NewNoneOption[func() check.Check]() } diff --git a/pkg/collector/corechecks/sbom/check_test.go b/pkg/collector/corechecks/sbom/check_test.go index 4134898f31473..9fe71d0f23099 100644 --- a/pkg/collector/corechecks/sbom/check_test.go +++ b/pkg/collector/corechecks/sbom/check_test.go @@ -14,6 +14,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" workloadmetamock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/mock" @@ -109,11 +110,12 @@ host_heartbeat_validity_seconds: 1000000 func TestFactory(t *testing.T) { cfg := config.NewMock(t) + fakeTagger := taggerimpl.SetupFakeTagger(t) mockStore := fxutil.Test[workloadmetamock.Mock](t, fx.Options( core.MockBundle(), workloadmetafxmock.MockModule(workloadmeta.NewParams()), )) - checkFactory := Factory(mockStore, cfg) + checkFactory := Factory(mockStore, cfg, fakeTagger) assert.NotNil(t, checkFactory) check, ok := checkFactory.Get() @@ -168,10 +170,11 @@ func TestConfigure(t *testing.T) { InitHelper: common.GetWorkloadmetaInit(), }), )) + fakeTagger := taggerimpl.SetupFakeTagger(t) cfg := app.Cfg mockStore := app.Store - checkFactory := Factory(mockStore, cfg) + checkFactory := Factory(mockStore, cfg, fakeTagger) assert.NotNil(t, checkFactory) check, ok := checkFactory.Get() diff --git a/pkg/collector/corechecks/sbom/processor.go b/pkg/collector/corechecks/sbom/processor.go index b26e2eaebc596..2040b86a7fd96 100644 --- a/pkg/collector/corechecks/sbom/processor.go +++ b/pkg/collector/corechecks/sbom/processor.go @@ -41,6 +41,7 @@ var /* const */ ( type processor struct { queue chan *model.SBOMEntity workloadmetaStore workloadmeta.Component + tagger tagger.Component imageRepoDigests map[string]string // Map where keys are image repo digest and values are image ID imageUsers map[string]map[string]struct{} // Map where keys are image repo digest and values are set of container IDs sbomScanner *sbomscanner.Scanner @@ -51,7 +52,7 @@ type processor struct { hostHeartbeatValidity time.Duration } -func newProcessor(workloadmetaStore workloadmeta.Component, sender sender.Sender, maxNbItem int, maxRetentionTime time.Duration, hostSBOM bool, hostHeartbeatValidity time.Duration) (*processor, error) { +func newProcessor(workloadmetaStore workloadmeta.Component, sender sender.Sender, tagger tagger.Component, maxNbItem int, maxRetentionTime time.Duration, hostSBOM bool, hostHeartbeatValidity time.Duration) (*processor, error) { sbomScanner := sbomscanner.GetGlobalScanner() if sbomScanner == nil { return nil, errors.New("failed to get global SBOM scanner") @@ -78,6 +79,7 @@ func newProcessor(workloadmetaStore workloadmeta.Component, sender sender.Sender sender.EventPlatformEvent(encoded, eventplatform.EventTypeContainerSBOM) }), workloadmetaStore: workloadmetaStore, + tagger: tagger, imageRepoDigests: make(map[string]string), imageUsers: make(map[string]map[string]struct{}), sbomScanner: sbomScanner, @@ -243,7 +245,7 @@ func (p *processor) processImageSBOM(img *workloadmeta.ContainerImageMetadata) { } entityID := types.NewEntityID(types.ContainerImageMetadata, img.ID) - ddTags, err := tagger.Tag(entityID, types.HighCardinality) + ddTags, err := p.tagger.Tag(entityID, types.HighCardinality) if err != nil { log.Errorf("Could not retrieve tags for container image %s: %v", img.ID, err) } diff --git a/pkg/collector/corechecks/sbom/processor_test.go b/pkg/collector/corechecks/sbom/processor_test.go index ac96503f82048..03c721b136194 100644 --- a/pkg/collector/corechecks/sbom/processor_test.go +++ b/pkg/collector/corechecks/sbom/processor_test.go @@ -27,6 +27,7 @@ import ( configcomp "github.com/DataDog/datadog-agent/comp/core/config" log "github.com/DataDog/datadog-agent/comp/core/log/def" logmock "github.com/DataDog/datadog-agent/comp/core/log/mock" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" workloadmetamock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/mock" @@ -625,9 +626,11 @@ func TestProcessEvents(t *testing.T) { SBOMsSent.Inc() }) + fakeTagger := taggerimpl.SetupFakeTagger(t) + // Define a max size of 1 for the queue. With a size > 1, it's difficult to // control the number of events sent on each call. - p, err := newProcessor(workloadmetaStore, sender, 1, 50*time.Millisecond, false, time.Second) + p, err := newProcessor(workloadmetaStore, sender, fakeTagger, 1, 50*time.Millisecond, false, time.Second) if err != nil { t.Fatal(err) } diff --git a/pkg/collector/corechecks/servicediscovery/apm/detect.go b/pkg/collector/corechecks/servicediscovery/apm/detect.go index 5c71ed5d08f11..f90a16448e48c 100644 --- a/pkg/collector/corechecks/servicediscovery/apm/detect.go +++ b/pkg/collector/corechecks/servicediscovery/apm/detect.go @@ -200,6 +200,8 @@ func nodeDetector(ctx usm.DetectionContext) Instrumentation { return None } +var javaAgentRegex = regexp.MustCompile(`-javaagent:.*(?:datadog|dd-java-agent|dd-trace-agent)\S*\.jar`) + func javaDetector(ctx usm.DetectionContext) Instrumentation { ignoreArgs := map[string]bool{ "-version": true, @@ -213,7 +215,7 @@ func javaDetector(ctx usm.DetectionContext) Instrumentation { return None } // don't instrument if javaagent is already there on the command line - if strings.HasPrefix(v, "-javaagent:") && strings.Contains(v, "dd-java-agent.jar") { + if javaAgentRegex.MatchString(v) { return Provided } } @@ -231,7 +233,7 @@ func javaDetector(ctx usm.DetectionContext) Instrumentation { } for _, name := range toolOptionEnvs { if val, ok := ctx.Envs.Get(name); ok { - if strings.Contains(val, "-javaagent:") && strings.Contains(val, "dd-java-agent.jar") { + if javaAgentRegex.MatchString(val) { return Provided } } diff --git a/pkg/collector/corechecks/servicediscovery/apm/detect_nix_test.go b/pkg/collector/corechecks/servicediscovery/apm/detect_nix_test.go index 578e7bd59a7cb..602aa88b841e9 100644 --- a/pkg/collector/corechecks/servicediscovery/apm/detect_nix_test.go +++ b/pkg/collector/corechecks/servicediscovery/apm/detect_nix_test.go @@ -79,10 +79,30 @@ func Test_javaDetector(t *testing.T) { result: None, }, { - name: "cmdline", + name: "cmdline - dd-java-agent.jar", args: []string{"java", "-foo", "-javaagent:/path/to/data dog/dd-java-agent.jar", "-Ddd.profiling.enabled=true"}, result: Provided, }, + { + name: "cmdline - dd-trace-agent.jar", + args: []string{"java", "-foo", "-javaagent:/path/to/data dog/dd-trace-agent.jar", "-Ddd.profiling.enabled=true"}, + result: Provided, + }, + { + name: "cmdline - datadog.jar", + args: []string{"java", "-foo", "-javaagent:/path/to/data dog/datadog.jar", "-Ddd.profiling.enabled=true"}, + result: Provided, + }, + { + name: "cmdline - datadog only in does not match", + args: []string{"java", "-foo", "path/to/data dog/datadog", "-Ddd.profiling.enabled=true"}, + result: None, + }, + { + name: "cmdline - jar only in does not match", + args: []string{"java", "-foo", "path/to/data dog/datadog.jar", "-Ddd.profiling.enabled=true"}, + result: None, + }, { name: "CATALINA_OPTS", args: []string{"java"}, diff --git a/pkg/collector/corechecks/servicediscovery/events.go b/pkg/collector/corechecks/servicediscovery/events.go index 55ff2d382680d..5cba3f89243ac 100644 --- a/pkg/collector/corechecks/servicediscovery/events.go +++ b/pkg/collector/corechecks/servicediscovery/events.go @@ -35,6 +35,7 @@ type eventPayload struct { ServiceLanguage string `json:"service_language"` ServiceType string `json:"service_type"` StartTime int64 `json:"start_time"` + StartTimeMilli int64 `json:"start_time_milli"` LastSeen int64 `json:"last_seen"` APMInstrumentation string `json:"apm_instrumentation"` ServiceNameSource string `json:"service_name_source,omitempty"` @@ -81,7 +82,8 @@ func (ts *telemetrySender) newEvent(t eventType, svc serviceInfo) *event { Env: env, ServiceLanguage: svc.meta.Language, ServiceType: svc.meta.Type, - StartTime: int64(svc.service.StartTimeSecs), + StartTime: int64(svc.service.StartTimeMilli / 1000), + StartTimeMilli: int64(svc.service.StartTimeMilli), LastSeen: svc.LastHeartbeat.Unix(), APMInstrumentation: svc.meta.APMInstrumentation, ServiceNameSource: nameSource, diff --git a/pkg/collector/corechecks/servicediscovery/events_test.go b/pkg/collector/corechecks/servicediscovery/events_test.go index 13d9ef013931e..6974ae4c138a8 100644 --- a/pkg/collector/corechecks/servicediscovery/events_test.go +++ b/pkg/collector/corechecks/servicediscovery/events_test.go @@ -59,7 +59,7 @@ func Test_telemetrySender(t *testing.T) { PID: 99, CommandLine: []string{"test-service", "--args"}, Ports: []uint16{80, 8080}, - StartTimeSecs: uint64(now.Add(-20 * time.Minute).Unix()), + StartTimeMilli: uint64(now.Add(-20 * time.Minute).UnixMilli()), RSS: 500 * 1024 * 1024, GeneratedName: "generated-name", DDService: "dd-service", @@ -95,6 +95,7 @@ func Test_telemetrySender(t *testing.T) { ServiceLanguage: "jvm", ServiceType: "web_service", StartTime: 1715557200, + StartTimeMilli: 1715557200 * 1000, LastSeen: 1715558400, APMInstrumentation: "injected", Ports: []uint16{80, 8080}, @@ -119,6 +120,7 @@ func Test_telemetrySender(t *testing.T) { ServiceLanguage: "jvm", ServiceType: "web_service", StartTime: 1715557200, + StartTimeMilli: 1715557200 * 1000, LastSeen: 1715558400, APMInstrumentation: "injected", Ports: []uint16{80, 8080}, @@ -143,6 +145,7 @@ func Test_telemetrySender(t *testing.T) { ServiceLanguage: "jvm", ServiceType: "web_service", StartTime: 1715557200, + StartTimeMilli: 1715557200 * 1000, LastSeen: 1715558400, APMInstrumentation: "injected", Ports: []uint16{80, 8080}, @@ -181,12 +184,12 @@ func Test_telemetrySender_name_provided(t *testing.T) { svc := serviceInfo{ service: model.Service{ - PID: 55, - CommandLine: []string{"foo", "--option"}, - StartTimeSecs: uint64(now.Add(-20 * time.Minute).Unix()), - GeneratedName: "generated-name2", - DDService: "dd-service-provided", - ContainerID: "abcd", + PID: 55, + CommandLine: []string{"foo", "--option"}, + StartTimeMilli: uint64(now.Add(-20 * time.Minute).UnixMilli()), + GeneratedName: "generated-name2", + DDService: "dd-service-provided", + ContainerID: "abcd", }, meta: ServiceMetadata{ Name: "test-service", @@ -216,6 +219,7 @@ func Test_telemetrySender_name_provided(t *testing.T) { ServiceLanguage: "jvm", ServiceType: "web_service", StartTime: 1715557200, + StartTimeMilli: 1715557200 * 1000, LastSeen: 1715558400, APMInstrumentation: "injected", PID: 55, @@ -237,6 +241,7 @@ func Test_telemetrySender_name_provided(t *testing.T) { ServiceLanguage: "jvm", ServiceType: "web_service", StartTime: 1715557200, + StartTimeMilli: 1715557200 * 1000, LastSeen: 1715558400, APMInstrumentation: "injected", PID: 55, @@ -258,6 +263,7 @@ func Test_telemetrySender_name_provided(t *testing.T) { ServiceLanguage: "jvm", ServiceType: "web_service", StartTime: 1715557200, + StartTimeMilli: 1715557200 * 1000, LastSeen: 1715558400, APMInstrumentation: "injected", PID: 55, diff --git a/pkg/collector/corechecks/servicediscovery/impl_linux_test.go b/pkg/collector/corechecks/servicediscovery/impl_linux_test.go index 91bbc71c59458..762f5dcb264ee 100644 --- a/pkg/collector/corechecks/servicediscovery/impl_linux_test.go +++ b/pkg/collector/corechecks/servicediscovery/impl_linux_test.go @@ -33,11 +33,9 @@ type testProc struct { } var ( - bootTimeSeconds = uint64(time.Date(2000, 01, 01, 0, 0, 0, 0, time.UTC).Unix()) - // procLaunched is number of clicks (100 per second) since bootTime when the process started - // assume it's 12 hours later - procLaunchedSeconds = bootTimeSeconds + uint64((12 * time.Hour).Seconds()) - pythonCommandLine = []string{"python", "-m", "foobar.main"} + bootTimeMilli = uint64(time.Date(2000, 01, 01, 0, 0, 0, 0, time.UTC).UnixMilli()) + procLaunchedMilli = bootTimeMilli + uint64((12 * time.Hour).Milliseconds()) + pythonCommandLine = []string{"python", "-m", "foobar.main"} ) var ( @@ -80,7 +78,7 @@ var ( RSS: 100 * 1024 * 1024, CPUCores: 1.5, CommandLine: []string{"test-service-1"}, - StartTimeSecs: procLaunchedSeconds, + StartTimeMilli: procLaunchedMilli, } portTCP8080UpdatedRSS = model.Service{ PID: procTestService1.pid, @@ -92,7 +90,7 @@ var ( RSS: 200 * 1024 * 1024, CPUCores: 1.5, CommandLine: []string{"test-service-1"}, - StartTimeSecs: procLaunchedSeconds, + StartTimeMilli: procLaunchedMilli, } portTCP8080DifferentPID = model.Service{ PID: procTestService1DifferentPID.pid, @@ -103,36 +101,36 @@ var ( Ports: []uint16{8080}, APMInstrumentation: string(apm.Injected), CommandLine: []string{"test-service-1"}, - StartTimeSecs: procLaunchedSeconds, + StartTimeMilli: procLaunchedMilli, } portTCP8081 = model.Service{ - PID: procIgnoreService1.pid, - Name: "ignore-1", - GeneratedName: "ignore-1", - Ports: []uint16{8081}, - StartTimeSecs: procLaunchedSeconds, + PID: procIgnoreService1.pid, + Name: "ignore-1", + GeneratedName: "ignore-1", + Ports: []uint16{8081}, + StartTimeMilli: procLaunchedMilli, } portTCP5000 = model.Service{ - PID: procPythonService.pid, - Name: "python-service", - GeneratedName: "python-service", - Language: "python", - Ports: []uint16{5000}, - CommandLine: pythonCommandLine, - StartTimeSecs: procLaunchedSeconds, + PID: procPythonService.pid, + Name: "python-service", + GeneratedName: "python-service", + Language: "python", + Ports: []uint16{5000}, + CommandLine: pythonCommandLine, + StartTimeMilli: procLaunchedMilli, } portTCP5432 = model.Service{ - PID: procTestService1Repeat.pid, - Name: "test-service-1", - GeneratedName: "test-service-1", - Ports: []uint16{5432}, - CommandLine: []string{"test-service-1"}, - StartTimeSecs: procLaunchedSeconds, + PID: procTestService1Repeat.pid, + Name: "test-service-1", + GeneratedName: "test-service-1", + Ports: []uint16{5432}, + CommandLine: []string{"test-service-1"}, + StartTimeMilli: procLaunchedMilli, } ) func calcTime(additionalTime time.Duration) time.Time { - unix := time.Unix(int64(procLaunchedSeconds), 0) + unix := time.UnixMilli(int64(procLaunchedMilli)) return unix.Add(additionalTime) } @@ -237,6 +235,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(1 * time.Minute).Unix(), Ports: []uint16{8080}, PID: 99, @@ -260,6 +259,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(20 * time.Minute).Unix(), Ports: []uint16{8080}, PID: 99, @@ -283,6 +283,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(20 * time.Minute).Unix(), Ports: []uint16{8080}, PID: 99, @@ -304,6 +305,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(1 * time.Minute).Unix(), Ports: []uint16{5000}, PID: 500, @@ -323,6 +325,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(20 * time.Minute).Unix(), Ports: []uint16{5000}, PID: 500, @@ -379,6 +382,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(1 * time.Minute).Unix(), Ports: []uint16{5432}, PID: 101, @@ -399,6 +403,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(1 * time.Minute).Unix(), Ports: []uint16{8080}, PID: 99, @@ -420,6 +425,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(20 * time.Minute).Unix(), Ports: []uint16{5432}, PID: 101, @@ -438,6 +444,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(20 * time.Minute).Unix(), Ports: []uint16{5432}, PID: 101, @@ -458,6 +465,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(20 * time.Minute).Unix(), Ports: []uint16{8080}, PID: 99, @@ -516,6 +524,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(1 * time.Minute).Unix(), Ports: []uint16{8080}, PID: 99, @@ -539,6 +548,7 @@ func Test_linuxImpl(t *testing.T) { HostName: host, Env: "", StartTime: calcTime(0).Unix(), + StartTimeMilli: calcTime(0).UnixMilli(), LastSeen: calcTime(22 * time.Minute).Unix(), Ports: []uint16{8080}, PID: 102, diff --git a/pkg/collector/corechecks/servicediscovery/model/model.go b/pkg/collector/corechecks/servicediscovery/model/model.go index 98a610f7ff304..df67422cb089e 100644 --- a/pkg/collector/corechecks/servicediscovery/model/model.go +++ b/pkg/collector/corechecks/servicediscovery/model/model.go @@ -18,7 +18,7 @@ type Service struct { Language string `json:"language"` RSS uint64 `json:"rss"` CommandLine []string `json:"cmdline"` - StartTimeSecs uint64 `json:"start_time"` + StartTimeMilli uint64 `json:"start_time"` CPUCores float64 `json:"cpu_cores"` ContainerID string `json:"container_id"` } diff --git a/pkg/collector/corechecks/servicediscovery/module/cmdline.go b/pkg/collector/corechecks/servicediscovery/module/cmdline.go index 2e54c714a8e61..f1afb65fce0c6 100644 --- a/pkg/collector/corechecks/servicediscovery/module/cmdline.go +++ b/pkg/collector/corechecks/servicediscovery/module/cmdline.go @@ -10,7 +10,7 @@ package module import "github.com/DataDog/datadog-agent/pkg/process/procutil" const ( - maxCommandLine = 200 + maxCommandLine = 5000 ) // countAndAddElements is a helper for truncateCmdline used to be able to diff --git a/pkg/collector/corechecks/servicediscovery/module/comm.go b/pkg/collector/corechecks/servicediscovery/module/comm.go index 3e878da448a03..7b513080aef18 100644 --- a/pkg/collector/corechecks/servicediscovery/module/comm.go +++ b/pkg/collector/corechecks/servicediscovery/module/comm.go @@ -16,23 +16,19 @@ import ( "github.com/shirou/gopsutil/v3/process" "github.com/DataDog/datadog-agent/pkg/util/kernel" + ddsync "github.com/DataDog/datadog-agent/pkg/util/sync" ) -// ignoreComms is a list of process names that should not be reported as a service. -var ignoreComms = map[string]struct{}{ - "systemd": {}, // manages system and service components - "dhclient": {}, // utility that uses the DHCP to configure network interfaces - "local-volume-pr": {}, // 'local-volume-provisioner' manages the lifecycle of Persistent Volumes - "sshd": {}, // a daemon that handles secure communication - "cilium-agent": {}, // accepts configuration for networking, load balancing etc. (like cilium-agent) - "kubelet": {}, // Kubernetes agent - "chronyd": {}, // a daemon that implements the Network Time Protocol (NTP) - "containerd": {}, // engine to run containers - "dockerd": {}, // engine to run containers and 'docker-proxy' - "livenessprobe": {}, // Kubernetes tool that monitors a container's health -} +const ( + // maxCommLen is maximum command name length to process when checking for non-reportable commands, + // is one byte less (excludes end of line) than the maximum of /proc//comm + // defined in https://man7.org/linux/man-pages/man5/proc.5.html. + maxCommLen = 15 + poolCapacity = 100 +) -// ignoreFamily list of commands that should not be reported as a service. +// ignoreFamily list of processes with hyphens in their names, +// matching up to the hyphen excludes process from reporting. var ignoreFamily = map[string]struct{}{ "systemd": {}, // 'systemd-networkd', 'systemd-resolved' etc "datadog": {}, // datadog processes @@ -40,24 +36,39 @@ var ignoreFamily = map[string]struct{}{ "docker": {}, // 'docker-proxy' } +var ( + procCommBufferPool = ddsync.NewSlicePool[byte](maxCommLen, poolCapacity) +) + // shouldIgnoreComm returns true if process should be ignored -func shouldIgnoreComm(proc *process.Process) bool { +func (s *discovery) shouldIgnoreComm(proc *process.Process) bool { + if s.config.ignoreComms == nil { + return false + } commPath := kernel.HostProc(strconv.Itoa(int(proc.Pid)), "comm") - contents, err := os.ReadFile(commPath) + file, err := os.Open(commPath) if err != nil { return true } + defer file.Close() - dash := bytes.IndexByte(contents, '-') + buf := procCommBufferPool.Get() + defer procCommBufferPool.Put(buf) + + n, err := file.Read(*buf) + if err != nil { + return true + } + dash := bytes.IndexByte((*buf)[:n], '-') if dash > 0 { - _, found := ignoreFamily[string(contents[:dash])] + _, found := ignoreFamily[string((*buf)[:dash])] if found { return true } } - comm := strings.TrimSuffix(string(contents), "\n") - _, found := ignoreComms[comm] + comm := strings.TrimSuffix(string((*buf)[:n]), "\n") + _, found := s.config.ignoreComms[comm] return found } diff --git a/pkg/collector/corechecks/servicediscovery/module/comm_test.go b/pkg/collector/corechecks/servicediscovery/module/comm_test.go index 568aa71ebf1ec..5aab786449896 100644 --- a/pkg/collector/corechecks/servicediscovery/module/comm_test.go +++ b/pkg/collector/corechecks/servicediscovery/module/comm_test.go @@ -15,6 +15,7 @@ import ( "testing" "time" + "github.com/shirou/gopsutil/v3/process" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -57,8 +58,12 @@ func TestIgnoreComm(t *testing.T) { // TestIgnoreCommsLengths checks that the map contains names no longer than 15 bytes. func TestIgnoreCommsLengths(t *testing.T) { - for comm := range ignoreComms { - assert.LessOrEqual(t, len(comm), 15, "Process name %q too big", comm) + discovery := newDiscovery() + require.NotEmpty(t, discovery) + require.Equal(t, len(discovery.config.ignoreComms), 10) + + for comm := range discovery.config.ignoreComms { + assert.LessOrEqual(t, len(comm), maxCommLen, "Process name %q too big", comm) } } @@ -109,6 +114,10 @@ func TestShouldIgnoreComm(t *testing.T) { serverBin := buildTestBin(t) serverDir := filepath.Dir(serverBin) + discovery := newDiscovery() + require.NotEmpty(t, discovery) + require.NotEmpty(t, discovery.config.ignoreComms) + require.Equal(t, len(discovery.config.ignoreComms), 10) for _, test := range testCases { t.Run(test.name, func(t *testing.T) { @@ -116,17 +125,27 @@ func TestShouldIgnoreComm(t *testing.T) { t.Cleanup(func() { cancel() }) makeAlias(t, test.comm, serverBin) + t.Cleanup(func() { + os.Remove(test.comm) + }) bin := filepath.Join(serverDir, test.comm) cmd := exec.CommandContext(ctx, bin) err := cmd.Start() require.NoError(t, err) + t.Cleanup(func() { + _ = cmd.Process.Kill() + }) + + var proc *process.Process + require.EventuallyWithT(t, func(collect *assert.CollectT) { + proc, err = customNewProcess(int32(cmd.Process.Pid)) + assert.NoError(collect, err) + }, 2*time.Second, 100*time.Millisecond) require.EventuallyWithT(t, func(collect *assert.CollectT) { - proc, err := customNewProcess(int32(cmd.Process.Pid)) - require.NoError(t, err) - ignore := shouldIgnoreComm(proc) - require.Equal(t, test.ignore, ignore) - }, 30*time.Second, 100*time.Millisecond) + ignore := discovery.shouldIgnoreComm(proc) + assert.Equal(collect, test.ignore, ignore) + }, 500*time.Millisecond, 100*time.Millisecond) }) } } @@ -189,6 +208,7 @@ func BenchmarkProcName(b *testing.B) { // BenchmarkShouldIgnoreComm benchmarks reading of command name from /proc//comm. func BenchmarkShouldIgnoreComm(b *testing.B) { + discovery := newDiscovery() cmd := startProcessLongComm(b) b.ResetTimer() @@ -199,9 +219,43 @@ func BenchmarkShouldIgnoreComm(b *testing.B) { if err != nil { b.Fatal(err) } - ok := shouldIgnoreComm(proc) + ok := discovery.shouldIgnoreComm(proc) if ok { b.Fatalf("process should not have been ignored") } } } + +// BenchmarkProcCommReadFile reads content of /proc//comm with default buffer allocation. +func BenchmarkProcCommReadFile(b *testing.B) { + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + _, err := os.ReadFile("/proc/1/comm") + if err != nil { + b.Fatal(err) + } + } +} + +// BenchmarkProcCommReadFile reads content of /proc//comm using pre-allocated pool of buffers. +func BenchmarkProcCommReadLen(b *testing.B) { + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + file, err := os.Open("/proc/1/comm") + if err != nil { + b.Fatal(err) + } + buf := procCommBufferPool.Get() + + _, err = file.Read(*buf) + if err != nil { + b.Fatal(err) + } + file.Close() + procCommBufferPool.Put(buf) + } +} diff --git a/pkg/collector/corechecks/servicediscovery/module/config.go b/pkg/collector/corechecks/servicediscovery/module/config.go index 1cf73abf465fd..85ace99dd8b04 100644 --- a/pkg/collector/corechecks/servicediscovery/module/config.go +++ b/pkg/collector/corechecks/servicediscovery/module/config.go @@ -13,21 +13,45 @@ import ( sysconfig "github.com/DataDog/datadog-agent/cmd/system-probe/config" ddconfig "github.com/DataDog/datadog-agent/pkg/config/setup" + "github.com/DataDog/datadog-agent/pkg/util/log" ) const discoveryNS = "discovery" type discoveryConfig struct { cpuUsageUpdateDelay time.Duration + ignoreComms map[string]struct{} } func newConfig() *discoveryConfig { cfg := ddconfig.SystemProbe() sysconfig.Adjust(cfg) - return &discoveryConfig{ + conf := &discoveryConfig{ cpuUsageUpdateDelay: cfg.GetDuration(join(discoveryNS, "cpu_usage_update_delay")), } + + conf.loadIgnoredComms(cfg.GetStringSlice(join(discoveryNS, "ignored_command_names"))) + + return conf +} + +// loadIgnoredComms read process names that should not be reported as a service from input string +func (config *discoveryConfig) loadIgnoredComms(comms []string) { + if len(comms) == 0 { + log.Warn("loading ignored commands found empty commands list") + return + } + config.ignoreComms = make(map[string]struct{}, len(comms)) + + for _, comm := range comms { + if len(comm) > maxCommLen { + config.ignoreComms[comm[:maxCommLen]] = struct{}{} + log.Warnf("truncating command name %q has %d bytes to %d", comm, len(comm), maxCommLen) + } else if len(comm) > 0 { + config.ignoreComms[comm] = struct{}{} + } + } } func join(pieces ...string) string { diff --git a/pkg/collector/corechecks/servicediscovery/module/config_test.go b/pkg/collector/corechecks/servicediscovery/module/config_test.go new file mode 100644 index 0000000000000..8f9e443c1fb26 --- /dev/null +++ b/pkg/collector/corechecks/servicediscovery/module/config_test.go @@ -0,0 +1,95 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024-present Datadog, Inc. + +//go:build linux_bpf + +package module + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/DataDog/datadog-agent/pkg/config/mock" +) + +func TestConfigIgnoredComms(t *testing.T) { + tests := []struct { + name string // The name of the test. + comms []string // list of command names to test + }{ + { + name: "empty list of commands", + comms: []string{}, + }, + { + name: "short commands in config list", + comms: []string{ + "cron", + "polkitd", + "rsyslogd", + "bash", + "sshd", + }, + }, + { + name: "long commands in config list", + comms: []string{ + "containerd-shim-runc-v2", + "calico-node", + "unattended-upgrade-shutdown", + "bash", + "kube-controller-manager", + }, + }, + } + + // test with custom command names of different lengths + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + mockSystemProbe := mock.NewSystemProbe(t) + require.NotEmpty(t, mockSystemProbe) + + commsStr := strings.Join(test.comms, " ") // intentionally multiple spaces for sensitivity testing + mockSystemProbe.SetWithoutSource("discovery.ignored_command_names", commsStr) + + discovery := newDiscovery() + require.NotEmpty(t, discovery) + + require.Equal(t, len(discovery.config.ignoreComms), len(test.comms)) + + for _, cmd := range test.comms { + if len(cmd) > maxCommLen { + cmd = cmd[:maxCommLen] + } + _, found := discovery.config.ignoreComms[cmd] + assert.True(t, found) + } + }) + } + + t.Run("check default config length", func(t *testing.T) { + mock.NewSystemProbe(t) + discovery := newDiscovery() + require.NotEmpty(t, discovery) + + assert.Equal(t, len(discovery.config.ignoreComms), 10) + }) + + t.Run("check command names in env variable", func(t *testing.T) { + mock.NewSystemProbe(t) + t.Setenv("DD_DISCOVERY_IGNORED_COMMAND_NAMES", "dummy1 dummy2") + + discovery := newDiscovery() + require.NotEmpty(t, discovery) + + _, found := discovery.config.ignoreComms["dummy1"] + assert.True(t, found) + _, found = discovery.config.ignoreComms["dummy2"] + assert.True(t, found) + }) +} diff --git a/pkg/collector/corechecks/servicediscovery/module/impl_linux.go b/pkg/collector/corechecks/servicediscovery/module/impl_linux.go index 35706621fce6c..2f43a65ea4e90 100644 --- a/pkg/collector/corechecks/servicediscovery/module/impl_linux.go +++ b/pkg/collector/corechecks/servicediscovery/module/impl_linux.go @@ -53,7 +53,7 @@ type serviceInfo struct { language language.Language apmInstrumentation apm.Instrumentation cmdLine []string - startTimeSecs uint64 + startTimeMilli uint64 cpuTime uint64 cpuUsage float64 } @@ -80,15 +80,19 @@ type discovery struct { lastCPUTimeUpdate time.Time } -// NewDiscoveryModule creates a new discovery system probe module. -func NewDiscoveryModule(*sysconfigtypes.Config, module.FactoryDependencies) (module.Module, error) { +func newDiscovery() *discovery { return &discovery{ config: newConfig(), mux: &sync.RWMutex{}, cache: make(map[int32]*serviceInfo), privilegedDetector: privileged.NewLanguageDetector(), scrubber: procutil.NewDefaultDataScrubber(), - }, nil + } +} + +// NewDiscoveryModule creates a new discovery system probe module. +func NewDiscoveryModule(*sysconfigtypes.Config, module.FactoryDependencies) (module.Module, error) { + return newDiscovery(), nil } // GetStats returns the stats of the discovery module. @@ -370,7 +374,7 @@ func (s *discovery) getServiceInfo(proc *process.Process) (*serviceInfo, error) apmInstrumentation: apmInstrumentation, ddServiceInjected: nameMeta.DDServiceInjected, cmdLine: sanitizeCmdLine(s.scrubber, cmdline), - startTimeSecs: uint64(createTime / 1000), + startTimeMilli: uint64(createTime), }, nil } @@ -402,7 +406,7 @@ func (s *discovery) getService(context parsingContext, pid int32) *model.Service return nil } - if shouldIgnoreComm(proc) { + if s.shouldIgnoreComm(proc) { return nil } @@ -499,7 +503,7 @@ func (s *discovery) getService(context parsingContext, pid int32) *model.Service Language: string(info.language), RSS: rss, CommandLine: info.cmdLine, - StartTimeSecs: info.startTimeSecs, + StartTimeMilli: info.startTimeMilli, CPUCores: info.cpuUsage, } } diff --git a/pkg/collector/corechecks/servicediscovery/module/impl_linux_test.go b/pkg/collector/corechecks/servicediscovery/module/impl_linux_test.go index 652205ab061fd..fdcbc61a78794 100644 --- a/pkg/collector/corechecks/servicediscovery/module/impl_linux_test.go +++ b/pkg/collector/corechecks/servicediscovery/module/impl_linux_test.go @@ -509,10 +509,14 @@ func TestAPMInstrumentationProvided(t *testing.T) { "CORECLR_ENABLE_PROFILING=1", }, }, - "java": { + "java - dd-java-agent.jar": { commandline: []string{"java", "-javaagent:/path/to/dd-java-agent.jar", "-jar", "foo.jar"}, language: language.Java, }, + "java - datadog.jar": { + commandline: []string{"java", "-javaagent:/path/to/datadog-java-agent.jar", "-jar", "foo.jar"}, + language: language.Java, + }, "node": { commandline: []string{"node", filepath.Join(curDir, "testdata", "server.js")}, language: language.Node, @@ -579,7 +583,7 @@ func assertStat(t assert.TestingT, svc model.Service) { // in theory an unbounded amount of time between the read of /proc/uptime // and the retrieval of the current time. Allow a 10 second diff as a // reasonable value. - assert.InDelta(t, uint64(createTimeMs/1000), svc.StartTimeSecs, 10) + assert.InDelta(t, uint64(createTimeMs), svc.StartTimeMilli, 10000) } func assertCPU(t *testing.T, url string, pid int) { diff --git a/pkg/collector/corechecks/servicediscovery/servicediscovery.go b/pkg/collector/corechecks/servicediscovery/servicediscovery.go index 9abc7ad4dd45b..5400e33272bd2 100644 --- a/pkg/collector/corechecks/servicediscovery/servicediscovery.go +++ b/pkg/collector/corechecks/servicediscovery/servicediscovery.go @@ -15,7 +15,6 @@ import ( "gopkg.in/yaml.v2" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" - workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" "github.com/DataDog/datadog-agent/pkg/collector/corechecks" @@ -85,14 +84,21 @@ type Check struct { } // Factory creates a new check factory -func Factory(store workloadmeta.Component) optional.Option[func() check.Check] { +func Factory() optional.Option[func() check.Check] { // Since service_discovery is enabled by default, we want to prevent returning an error in Configure() for platforms // where the check is not implemented. Instead of that, we return an empty check. if newOSImpl == nil { return optional.NewNoneOption[func() check.Check]() } + + sharedContainerProvider, err := proccontainers.GetSharedContainerProvider() + + if err != nil { + return optional.NewNoneOption[func() check.Check]() + } + return optional.NewOption(func() check.Check { - return newCheck(proccontainers.GetSharedContainerProvider(store)) + return newCheck(sharedContainerProvider) }) } diff --git a/pkg/collector/corechecks/snmp/integration_profile_bundle_test.go b/pkg/collector/corechecks/snmp/integration_profile_bundle_test.go index ad5dd0e5d0909..519e8a5ee8e7f 100644 --- a/pkg/collector/corechecks/snmp/integration_profile_bundle_test.go +++ b/pkg/collector/corechecks/snmp/integration_profile_bundle_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/pkg/aggregator" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -24,7 +25,7 @@ import ( func TestProfileBundleJsonZip(t *testing.T) { timeNow = common.MockTimeNow - aggregator.NewBufferedAggregator(nil, nil, "", 1*time.Hour) + aggregator.NewBufferedAggregator(nil, nil, nooptagger.NewTaggerClient(), "", 1*time.Hour) invalidPath, _ := filepath.Abs(filepath.Join("internal", "test", "zipprofiles.d")) pkgconfigsetup.Datadog().SetWithoutSource("confd_path", invalidPath) diff --git a/pkg/collector/corechecks/snmp/integration_profile_metadata_test.go b/pkg/collector/corechecks/snmp/integration_profile_metadata_test.go index c73e5a06b3561..22cb6e3f26c88 100644 --- a/pkg/collector/corechecks/snmp/integration_profile_metadata_test.go +++ b/pkg/collector/corechecks/snmp/integration_profile_metadata_test.go @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/pkg/aggregator" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -31,7 +32,7 @@ import ( func TestProfileMetadata_f5(t *testing.T) { timeNow = common.MockTimeNow - aggregator.NewBufferedAggregator(nil, nil, "", 1*time.Hour) + aggregator.NewBufferedAggregator(nil, nil, nooptagger.NewTaggerClient(), "", 1*time.Hour) invalidPath, _ := filepath.Abs(filepath.Join("internal", "test", "metadata.d")) pkgconfigsetup.Datadog().SetWithoutSource("confd_path", invalidPath) diff --git a/pkg/collector/corechecks/snmp/integration_topology_test.go b/pkg/collector/corechecks/snmp/integration_topology_test.go index 1945a8362cad1..65915af08a005 100644 --- a/pkg/collector/corechecks/snmp/integration_topology_test.go +++ b/pkg/collector/corechecks/snmp/integration_topology_test.go @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/pkg/aggregator" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -31,7 +32,7 @@ import ( func TestTopologyPayload_LLDP(t *testing.T) { timeNow = common.MockTimeNow - aggregator.NewBufferedAggregator(nil, nil, "", 1*time.Hour) + aggregator.NewBufferedAggregator(nil, nil, nooptagger.NewTaggerClient(), "", 1*time.Hour) invalidPath, _ := filepath.Abs(filepath.Join("internal", "test", "metadata.d")) pkgconfigsetup.Datadog().SetWithoutSource("confd_path", invalidPath) @@ -733,7 +734,7 @@ profiles: func TestTopologyPayload_CDP(t *testing.T) { timeNow = common.MockTimeNow - aggregator.NewBufferedAggregator(nil, nil, "", 1*time.Hour) + aggregator.NewBufferedAggregator(nil, nil, nooptagger.NewTaggerClient(), "", 1*time.Hour) invalidPath, _ := filepath.Abs(filepath.Join("internal", "test", "metadata.d")) pkgconfigsetup.Datadog().SetWithoutSource("confd_path", invalidPath) @@ -1426,7 +1427,7 @@ profiles: // we have different data for LLDP and CDP to test that we're only using LLDP to build the links func TestTopologyPayload_LLDP_CDP(t *testing.T) { timeNow = common.MockTimeNow - aggregator.NewBufferedAggregator(nil, nil, "", 1*time.Hour) + aggregator.NewBufferedAggregator(nil, nil, nooptagger.NewTaggerClient(), "", 1*time.Hour) invalidPath, _ := filepath.Abs(filepath.Join("internal", "test", "metadata.d")) pkgconfigsetup.Datadog().SetWithoutSource("confd_path", invalidPath) diff --git a/pkg/collector/corechecks/snmp/internal/checkconfig/config_test.go b/pkg/collector/corechecks/snmp/internal/checkconfig/config_test.go index 49bfd183f77a0..cffed1f43f099 100644 --- a/pkg/collector/corechecks/snmp/internal/checkconfig/config_test.go +++ b/pkg/collector/corechecks/snmp/internal/checkconfig/config_test.go @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/pkg/aggregator" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -24,7 +25,7 @@ import ( func TestConfigurations(t *testing.T) { profile.SetConfdPathAndCleanProfiles() - aggregator.NewBufferedAggregator(nil, nil, "", 1*time.Hour) + aggregator.NewBufferedAggregator(nil, nil, nooptagger.NewTaggerClient(), "", 1*time.Hour) // language=yaml rawInstanceConfig := []byte(` @@ -325,7 +326,7 @@ profiles: func TestInlineProfileConfiguration(t *testing.T) { profile.SetConfdPathAndCleanProfiles() - aggregator.NewBufferedAggregator(nil, nil, "", 1*time.Hour) + aggregator.NewBufferedAggregator(nil, nil, nooptagger.NewTaggerClient(), "", 1*time.Hour) // language=yaml rawInstanceConfig := []byte(` diff --git a/pkg/collector/corechecks/systemd/systemd_test.go b/pkg/collector/corechecks/systemd/systemd_test.go index eec5bbf3372de..e473b47a8875a 100644 --- a/pkg/collector/corechecks/systemd/systemd_test.go +++ b/pkg/collector/corechecks/systemd/systemd_test.go @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" "github.com/DataDog/datadog-agent/comp/metadata/inventorychecks/inventorychecksimpl" "github.com/DataDog/datadog-agent/pkg/aggregator" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" @@ -1086,7 +1087,7 @@ unit_names: func TestCheckID(t *testing.T) { check1 := newCheck() check2 := newCheck() - aggregator.NewBufferedAggregator(nil, nil, "", 1*time.Hour) + aggregator.NewBufferedAggregator(nil, nil, nooptagger.NewTaggerClient(), "", 1*time.Hour) // language=yaml rawInstanceConfig1 := []byte(` diff --git a/pkg/collector/loaders/loaders.go b/pkg/collector/loaders/loaders.go index 261cb0a1ef9fd..668a7635d15c6 100644 --- a/pkg/collector/loaders/loaders.go +++ b/pkg/collector/loaders/loaders.go @@ -10,6 +10,7 @@ import ( "sort" "sync" + "github.com/DataDog/datadog-agent/comp/core/tagger" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -20,7 +21,7 @@ import ( // LoaderFactory helps to defer actual instantiation of Check Loaders, // mostly helpful with code involving calls to cgo (for example, the Python // interpreter might not be initialized when `init`ing a package) -type LoaderFactory func(sender.SenderManager, optional.Option[integrations.Component]) (check.Loader, error) +type LoaderFactory func(sender.SenderManager, optional.Option[integrations.Component], tagger.Component) (check.Loader, error) var factoryCatalog = make(map[int][]LoaderFactory) var loaderCatalog = []check.Loader{} @@ -32,7 +33,7 @@ func RegisterLoader(order int, factory LoaderFactory) { } // LoaderCatalog returns the loaders sorted by desired sequence order -func LoaderCatalog(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component]) []check.Loader { +func LoaderCatalog(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component], tagger tagger.Component) []check.Loader { // the catalog is supposed to be built only once, don't see a clear // use case to add Loaders at runtime once.Do(func() { @@ -47,7 +48,7 @@ func LoaderCatalog(senderManager sender.SenderManager, logReceiver optional.Opti // the final slice of loaders for _, k := range keys { for _, factory := range factoryCatalog[k] { - loader, err := factory(senderManager, logReceiver) + loader, err := factory(senderManager, logReceiver, tagger) if err != nil { log.Infof("Failed to instantiate %s: %v", loader, err) continue diff --git a/pkg/collector/loaders/loaders_test.go b/pkg/collector/loaders/loaders_test.go index 1d12c7a683035..3f98d7e6b0f85 100644 --- a/pkg/collector/loaders/loaders_test.go +++ b/pkg/collector/loaders/loaders_test.go @@ -13,6 +13,8 @@ import ( "github.com/stretchr/testify/require" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" @@ -58,15 +60,15 @@ func (lt *LoaderThree) Load(_ sender.SenderManager, _ integration.Config, _ inte func TestLoaderCatalog(t *testing.T) { l1 := LoaderOne{} - factory1 := func(sender.SenderManager, optional.Option[integrations.Component]) (check.Loader, error) { + factory1 := func(sender.SenderManager, optional.Option[integrations.Component], tagger.Component) (check.Loader, error) { return l1, nil } l2 := LoaderTwo{} - factory2 := func(sender.SenderManager, optional.Option[integrations.Component]) (check.Loader, error) { + factory2 := func(sender.SenderManager, optional.Option[integrations.Component], tagger.Component) (check.Loader, error) { return l2, nil } var l3 *LoaderThree - factory3 := func(sender.SenderManager, optional.Option[integrations.Component]) (check.Loader, error) { + factory3 := func(sender.SenderManager, optional.Option[integrations.Component], tagger.Component) (check.Loader, error) { return l3, errors.New("error") } @@ -75,7 +77,8 @@ func TestLoaderCatalog(t *testing.T) { RegisterLoader(30, factory3) senderManager := mocksender.CreateDefaultDemultiplexer() logReceiver := optional.NewNoneOption[integrations.Component]() - require.Len(t, LoaderCatalog(senderManager, logReceiver), 2) - assert.Equal(t, l1, LoaderCatalog(senderManager, logReceiver)[1]) - assert.Equal(t, l2, LoaderCatalog(senderManager, logReceiver)[0]) + tagger := nooptagger.NewTaggerClient() + require.Len(t, LoaderCatalog(senderManager, logReceiver, tagger), 2) + assert.Equal(t, l1, LoaderCatalog(senderManager, logReceiver, tagger)[1]) + assert.Equal(t, l2, LoaderCatalog(senderManager, logReceiver, tagger)[0]) } diff --git a/pkg/collector/python/check_context.go b/pkg/collector/python/check_context.go index 097b5e162a18a..f2353de933eb1 100644 --- a/pkg/collector/python/check_context.go +++ b/pkg/collector/python/check_context.go @@ -11,6 +11,7 @@ import ( "errors" "sync" + "github.com/DataDog/datadog-agent/comp/core/tagger" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/util/log" @@ -27,6 +28,7 @@ var checkContextMutex = sync.Mutex{} type checkContext struct { senderManager sender.SenderManager logReceiver optional.Option[integrations.Component] + tagger tagger.Component } func getCheckContext() (*checkContext, error) { @@ -39,12 +41,13 @@ func getCheckContext() (*checkContext, error) { return checkCtx, nil } -func initializeCheckContext(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component]) { +func initializeCheckContext(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component], tagger tagger.Component) { checkContextMutex.Lock() if checkCtx == nil { checkCtx = &checkContext{ senderManager: senderManager, logReceiver: logReceiver, + tagger: tagger, } if _, ok := logReceiver.Get(); !ok { diff --git a/pkg/collector/python/loader.go b/pkg/collector/python/loader.go index 66df21aaf6944..4d72ccb7d3b54 100644 --- a/pkg/collector/python/loader.go +++ b/pkg/collector/python/loader.go @@ -18,6 +18,7 @@ import ( "github.com/mohae/deepcopy" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" "github.com/DataDog/datadog-agent/pkg/aggregator" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" @@ -59,8 +60,8 @@ const ( ) func init() { - factory := func(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component]) (check.Loader, error) { - return NewPythonCheckLoader(senderManager, logReceiver) + factory := func(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component], tagger tagger.Component) (check.Loader, error) { + return NewPythonCheckLoader(senderManager, logReceiver, tagger) } loaders.RegisterLoader(20, factory) @@ -89,8 +90,8 @@ type PythonCheckLoader struct { } // NewPythonCheckLoader creates an instance of the Python checks loader -func NewPythonCheckLoader(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component]) (*PythonCheckLoader, error) { - initializeCheckContext(senderManager, logReceiver) +func NewPythonCheckLoader(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component], tagger tagger.Component) (*PythonCheckLoader, error) { + initializeCheckContext(senderManager, logReceiver, tagger) return &PythonCheckLoader{ logReceiver: logReceiver, }, nil diff --git a/pkg/collector/python/tagger.go b/pkg/collector/python/tagger.go index 0638963dea642..20515b556d8e6 100644 --- a/pkg/collector/python/tagger.go +++ b/pkg/collector/python/tagger.go @@ -10,7 +10,6 @@ package python import ( "unsafe" - "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/types" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -24,19 +23,20 @@ import ( */ import "C" -// for testing purposes -var ( - tagsFunc = tagger.LegacyTag -) - // Tags bridges towards tagger.Tag to retrieve container tags // //export Tags func Tags(id *C.char, cardinality C.int) **C.char { + checkContext, err := getCheckContext() + if err != nil { + log.Errorf("Python check context: %v", err) + return nil + } + goID := C.GoString(id) var tags []string - tags, _ = tagsFunc(goID, types.TagCardinality(cardinality)) + tags, _ = checkContext.tagger.LegacyTag(goID, types.TagCardinality(cardinality)) length := len(tags) if length == 0 { diff --git a/pkg/collector/python/test_aggregator.go b/pkg/collector/python/test_aggregator.go index d9b0b07402089..3864b5e1ee579 100644 --- a/pkg/collector/python/test_aggregator.go +++ b/pkg/collector/python/test_aggregator.go @@ -10,6 +10,8 @@ package python import ( "testing" + "github.com/DataDog/datadog-agent/comp/core/tagger" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" @@ -25,7 +27,8 @@ import "C" func testSubmitMetric(t *testing.T) { sender := mocksender.NewMockSender(checkid.ID("testID")) logReceiver := optional.NewNoneOption[integrations.Component]() - release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver) + tagger := nooptagger.NewTaggerClient() + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) defer release() sender.SetupAcceptAll() @@ -101,7 +104,8 @@ func testSubmitMetric(t *testing.T) { func testSubmitMetricEmptyTags(t *testing.T) { sender := mocksender.NewMockSender(checkid.ID("testID")) logReceiver := optional.NewNoneOption[integrations.Component]() - release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver) + tagger := nooptagger.NewTaggerClient() + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) defer release() sender.SetupAcceptAll() @@ -121,7 +125,8 @@ func testSubmitMetricEmptyTags(t *testing.T) { func testSubmitMetricEmptyHostname(t *testing.T) { sender := mocksender.NewMockSender(checkid.ID("testID")) logReceiver := optional.NewNoneOption[integrations.Component]() - release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver) + tagger := nooptagger.NewTaggerClient() + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) defer release() sender.SetupAcceptAll() @@ -141,7 +146,8 @@ func testSubmitMetricEmptyHostname(t *testing.T) { func testSubmitServiceCheck(t *testing.T) { sender := mocksender.NewMockSender(checkid.ID("testID")) logReceiver := optional.NewNoneOption[integrations.Component]() - release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver) + tagger := nooptagger.NewTaggerClient() + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) defer release() sender.SetupAcceptAll() @@ -160,7 +166,8 @@ func testSubmitServiceCheck(t *testing.T) { func testSubmitServiceCheckEmptyTag(t *testing.T) { sender := mocksender.NewMockSender(checkid.ID("testID")) logReceiver := optional.NewNoneOption[integrations.Component]() - release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver) + tagger := nooptagger.NewTaggerClient() + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) defer release() sender.SetupAcceptAll() @@ -179,7 +186,8 @@ func testSubmitServiceCheckEmptyTag(t *testing.T) { func testSubmitServiceCheckEmptyHostame(t *testing.T) { sender := mocksender.NewMockSender(checkid.ID("testID")) logReceiver := optional.NewNoneOption[integrations.Component]() - release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver) + tagger := nooptagger.NewTaggerClient() + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) defer release() sender.SetupAcceptAll() @@ -198,7 +206,8 @@ func testSubmitServiceCheckEmptyHostame(t *testing.T) { func testSubmitEvent(t *testing.T) { sender := mocksender.NewMockSender(checkid.ID("testID")) logReceiver := optional.NewNoneOption[integrations.Component]() - release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver) + tagger := nooptagger.NewTaggerClient() + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) defer release() sender.SetupAcceptAll() @@ -235,7 +244,8 @@ func testSubmitEvent(t *testing.T) { func testSubmitHistogramBucket(t *testing.T) { sender := mocksender.NewMockSender(checkid.ID("testID")) logReceiver := optional.NewNoneOption[integrations.Component]() - release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver) + tagger := nooptagger.NewTaggerClient() + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) defer release() sender.SetupAcceptAll() @@ -259,7 +269,8 @@ func testSubmitHistogramBucket(t *testing.T) { func testSubmitEventPlatformEvent(t *testing.T) { sender := mocksender.NewMockSender("testID") logReceiver := optional.NewNoneOption[integrations.Component]() - release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver) + tagger := nooptagger.NewTaggerClient() + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) defer release() sender.SetupAcceptAll() @@ -273,7 +284,9 @@ func testSubmitEventPlatformEvent(t *testing.T) { sender.AssertEventPlatformEvent(t, []byte("raw-event"), "dbm-sample") } -func scopeInitCheckContext(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component]) func() { - initializeCheckContext(senderManager, logReceiver) +func scopeInitCheckContext(senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component], taggerComp tagger.Component) func() { + // Ensure the check context is released before initializing a new one + releaseCheckContext() + initializeCheckContext(senderManager, logReceiver, taggerComp) return releaseCheckContext } diff --git a/pkg/collector/python/test_loader.go b/pkg/collector/python/test_loader.go index b0af8775925e4..2c349f91dc26b 100644 --- a/pkg/collector/python/test_loader.go +++ b/pkg/collector/python/test_loader.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -142,7 +143,8 @@ func testLoadCustomCheck(t *testing.T) { defer func() { rtloader = nil }() senderManager := mocksender.CreateDefaultDemultiplexer() logReceiver := optional.NewNoneOption[integrations.Component]() - loader, err := NewPythonCheckLoader(senderManager, logReceiver) + tagger := nooptagger.NewTaggerClient() + loader, err := NewPythonCheckLoader(senderManager, logReceiver, tagger) assert.Nil(t, err) // testing loading custom checks @@ -180,7 +182,8 @@ func testLoadWheelCheck(t *testing.T) { senderManager := mocksender.CreateDefaultDemultiplexer() logReceiver := optional.NewNoneOption[integrations.Component]() - loader, err := NewPythonCheckLoader(senderManager, logReceiver) + tagger := nooptagger.NewTaggerClient() + loader, err := NewPythonCheckLoader(senderManager, logReceiver, tagger) assert.Nil(t, err) // testing loading dd wheels diff --git a/pkg/collector/python/test_tagger.go b/pkg/collector/python/test_tagger.go index bbeff9e0dfd7e..4c320e63201c3 100644 --- a/pkg/collector/python/test_tagger.go +++ b/pkg/collector/python/test_tagger.go @@ -14,8 +14,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/DataDog/datadog-agent/comp/core/tagger" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/comp/core/tagger/types" + integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" + "github.com/DataDog/datadog-agent/pkg/aggregator/mocksender" + checkid "github.com/DataDog/datadog-agent/pkg/collector/check/id" + "github.com/DataDog/datadog-agent/pkg/util/optional" ) /* @@ -35,23 +39,15 @@ int arraylen(char **array, int max_len) { */ import "C" -func tagsMock(string, types.TagCardinality) ([]string, error) { - return []string{"tag1", "tag2", "tag3"}, nil -} - -func tagsMockNull(string, types.TagCardinality) ([]string, error) { - return nil, nil -} - -func tagsMockEmpty(string, types.TagCardinality) ([]string, error) { - return []string{}, nil -} - func testTags(t *testing.T) { - tagsFunc = tagsMock - defer func() { tagsFunc = tagger.LegacyTag }() - - id := C.CString("test") + sender := mocksender.NewMockSender(checkid.ID("testID")) + logReceiver := optional.NewNoneOption[integrations.Component]() + tagger := taggerimpl.SetupFakeTagger(t) + tagger.SetTags(types.NewEntityID(types.ContainerID, "test"), "foo", []string{"tag1", "tag2", "tag3"}, nil, nil, nil) + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) + defer release() + + id := C.CString("container_id://test") defer C.free(unsafe.Pointer(id)) res := Tags(id, 0) @@ -67,10 +63,14 @@ func testTags(t *testing.T) { } func testTagsNull(t *testing.T) { - tagsFunc = tagsMockNull - defer func() { tagsFunc = tagger.LegacyTag }() - - id := C.CString("test") + sender := mocksender.NewMockSender(checkid.ID("testID")) + logReceiver := optional.NewNoneOption[integrations.Component]() + tagger := taggerimpl.SetupFakeTagger(t) + tagger.SetTags(types.NewEntityID(types.ContainerID, "test"), "foo", nil, nil, nil, nil) + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) + defer release() + + id := C.CString("container_id://test") defer C.free(unsafe.Pointer(id)) res := Tags(id, 0) @@ -78,10 +78,14 @@ func testTagsNull(t *testing.T) { } func testTagsEmpty(t *testing.T) { - tagsFunc = tagsMockEmpty - defer func() { tagsFunc = tagger.LegacyTag }() - - id := C.CString("test") + sender := mocksender.NewMockSender(checkid.ID("testID")) + logReceiver := optional.NewNoneOption[integrations.Component]() + tagger := taggerimpl.SetupFakeTagger(t) + tagger.SetTags(types.NewEntityID(types.ContainerID, "test"), "foo", []string{}, nil, nil, nil) + release := scopeInitCheckContext(sender.GetSenderManager(), logReceiver, tagger) + defer release() + + id := C.CString("container_id://test") defer C.free(unsafe.Pointer(id)) res := Tags(id, 0) diff --git a/pkg/collector/scheduler.go b/pkg/collector/scheduler.go index f53954dafebd9..724bffe0e722c 100644 --- a/pkg/collector/scheduler.go +++ b/pkg/collector/scheduler.go @@ -17,6 +17,7 @@ import ( "github.com/DataDog/datadog-agent/comp/collector/collector" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" + "github.com/DataDog/datadog-agent/comp/core/tagger" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" "github.com/DataDog/datadog-agent/pkg/aggregator/sender" "github.com/DataDog/datadog-agent/pkg/collector/check" @@ -63,15 +64,15 @@ type CheckScheduler struct { } // InitCheckScheduler creates and returns a check scheduler -func InitCheckScheduler(collector optional.Option[collector.Component], senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component]) *CheckScheduler { +func InitCheckScheduler(collector optional.Option[collector.Component], senderManager sender.SenderManager, logReceiver optional.Option[integrations.Component], tagger tagger.Component) *CheckScheduler { checkScheduler = &CheckScheduler{ collector: collector, senderManager: senderManager, configToChecks: make(map[string][]checkid.ID), - loaders: make([]check.Loader, 0, len(loaders.LoaderCatalog(senderManager, logReceiver))), + loaders: make([]check.Loader, 0, len(loaders.LoaderCatalog(senderManager, logReceiver, tagger))), } // add the check loaders - for _, loader := range loaders.LoaderCatalog(senderManager, logReceiver) { + for _, loader := range loaders.LoaderCatalog(senderManager, logReceiver, tagger) { checkScheduler.AddLoader(loader) log.Debugf("Added %s to Check Scheduler", loader) } diff --git a/pkg/commonchecks/corechecks.go b/pkg/commonchecks/corechecks.go index f4719c58ba0e6..dbd67603cbb5b 100644 --- a/pkg/commonchecks/corechecks.go +++ b/pkg/commonchecks/corechecks.go @@ -66,21 +66,21 @@ func RegisterChecks(store workloadmeta.Component, tagger tagger.Component, cfg c corecheckLoader.RegisterCheck(networkpath.CheckName, networkpath.Factory(telemetry)) corecheckLoader.RegisterCheck(io.CheckName, io.Factory()) corecheckLoader.RegisterCheck(filehandles.CheckName, filehandles.Factory()) - corecheckLoader.RegisterCheck(containerimage.CheckName, containerimage.Factory(store)) + corecheckLoader.RegisterCheck(containerimage.CheckName, containerimage.Factory(store, tagger)) corecheckLoader.RegisterCheck(containerlifecycle.CheckName, containerlifecycle.Factory(store)) - corecheckLoader.RegisterCheck(generic.CheckName, generic.Factory(store)) + corecheckLoader.RegisterCheck(generic.CheckName, generic.Factory(store, tagger)) // Flavor specific checks corecheckLoader.RegisterCheck(load.CheckName, load.Factory()) corecheckLoader.RegisterCheck(kubernetesapiserver.CheckName, kubernetesapiserver.Factory(tagger)) corecheckLoader.RegisterCheck(ksm.CheckName, ksm.Factory()) corecheckLoader.RegisterCheck(helm.CheckName, helm.Factory()) - corecheckLoader.RegisterCheck(pod.CheckName, pod.Factory(store, cfg)) + corecheckLoader.RegisterCheck(pod.CheckName, pod.Factory(store, cfg, tagger)) corecheckLoader.RegisterCheck(ebpf.CheckName, ebpf.Factory()) corecheckLoader.RegisterCheck(gpu.CheckName, gpu.Factory()) - corecheckLoader.RegisterCheck(ecs.CheckName, ecs.Factory(store)) - corecheckLoader.RegisterCheck(oomkill.CheckName, oomkill.Factory()) - corecheckLoader.RegisterCheck(tcpqueuelength.CheckName, tcpqueuelength.Factory()) + corecheckLoader.RegisterCheck(ecs.CheckName, ecs.Factory(store, tagger)) + corecheckLoader.RegisterCheck(oomkill.CheckName, oomkill.Factory(tagger)) + corecheckLoader.RegisterCheck(tcpqueuelength.CheckName, tcpqueuelength.Factory(tagger)) corecheckLoader.RegisterCheck(apm.CheckName, apm.Factory()) corecheckLoader.RegisterCheck(process.CheckName, process.Factory()) corecheckLoader.RegisterCheck(network.CheckName, network.Factory()) @@ -92,12 +92,12 @@ func RegisterChecks(store workloadmeta.Component, tagger tagger.Component, cfg c corecheckLoader.RegisterCheck(winkmem.CheckName, winkmem.Factory()) corecheckLoader.RegisterCheck(winproc.CheckName, winproc.Factory()) corecheckLoader.RegisterCheck(systemd.CheckName, systemd.Factory()) - corecheckLoader.RegisterCheck(orchestrator.CheckName, orchestrator.Factory(store, cfg)) - corecheckLoader.RegisterCheck(docker.CheckName, docker.Factory(store)) - corecheckLoader.RegisterCheck(sbom.CheckName, sbom.Factory(store, cfg)) - corecheckLoader.RegisterCheck(kubelet.CheckName, kubelet.Factory(store)) - corecheckLoader.RegisterCheck(containerd.CheckName, containerd.Factory(store)) - corecheckLoader.RegisterCheck(cri.CheckName, cri.Factory(store)) + corecheckLoader.RegisterCheck(orchestrator.CheckName, orchestrator.Factory(store, cfg, tagger)) + corecheckLoader.RegisterCheck(docker.CheckName, docker.Factory(store, tagger)) + corecheckLoader.RegisterCheck(sbom.CheckName, sbom.Factory(store, cfg, tagger)) + corecheckLoader.RegisterCheck(kubelet.CheckName, kubelet.Factory(store, tagger)) + corecheckLoader.RegisterCheck(containerd.CheckName, containerd.Factory(store, tagger)) + corecheckLoader.RegisterCheck(cri.CheckName, cri.Factory(store, tagger)) corecheckLoader.RegisterCheck(ciscosdwan.CheckName, ciscosdwan.Factory()) - corecheckLoader.RegisterCheck(servicediscovery.CheckName, servicediscovery.Factory(store)) + corecheckLoader.RegisterCheck(servicediscovery.CheckName, servicediscovery.Factory()) } diff --git a/pkg/config/autodiscovery/autodiscovery_test.go b/pkg/config/autodiscovery/autodiscovery_test.go index 811a72de9edf5..24c32edca5273 100644 --- a/pkg/config/autodiscovery/autodiscovery_test.go +++ b/pkg/config/autodiscovery/autodiscovery_test.go @@ -6,57 +6,53 @@ package autodiscovery import ( - "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + configmock "github.com/DataDog/datadog-agent/pkg/config/mock" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" ) func TestDiscoverComponentsFromConfigForSnmp(t *testing.T) { pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: configs: - network: 127.0.0.1/30 -`)) - assert.NoError(t, err) +`) _, configListeners := DiscoverComponentsFromConfig() require.Len(t, configListeners, 1) assert.Equal(t, "snmp", configListeners[0].Name) - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: configs: -`)) - assert.NoError(t, err) +`) _, configListeners = DiscoverComponentsFromConfig() assert.Empty(t, len(configListeners)) - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` snmp_listener: configs: - network: 127.0.0.1/30 -`)) - assert.NoError(t, err) +`) _, configListeners = DiscoverComponentsFromConfig() require.Len(t, configListeners, 1) assert.Equal(t, "snmp", configListeners[0].Name) - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: configs: - network_address: 127.0.0.1/30 ignored_ip_addresses: - 127.0.0.3 -`)) - assert.NoError(t, err) +`) _, configListeners = DiscoverComponentsFromConfig() require.Len(t, configListeners, 1) assert.Equal(t, "snmp", configListeners[0].Name) diff --git a/pkg/config/config_template.yaml b/pkg/config/config_template.yaml index 2589f17e8d9a9..cd09ac919bb8b 100644 --- a/pkg/config/config_template.yaml +++ b/pkg/config/config_template.yaml @@ -1330,23 +1330,23 @@ api_key: # # connection_limit: 2000 - ## @param compute_stats_by_span_kind - bool - default: false - ## @env DD_APM_COMPUTE_STATS_BY_SPAN_KIND - bool - default: false - ## [BETA] Enables an additional stats computation check on spans to see they have an eligible `span.kind` (server, consumer, client, producer). + ## @param compute_stats_by_span_kind - bool - default: true + ## @env DD_APM_COMPUTE_STATS_BY_SPAN_KIND - bool - default: true + ## Enables an additional stats computation check on spans to see they have an eligible `span.kind` (server, consumer, client, producer). ## If enabled, a span with an eligible `span.kind` will have stats computed. If disabled, only top-level and measured spans will have stats computed. ## NOTE: For stats computed from OTel traces, only top-level spans are considered when this option is off. ## If you are sending OTel traces and want stats on non-top-level spans, this flag will need to be enabled. ## If you are sending OTel traces and do not want stats computed by span kind, you need to disable this flag and remove the "enable_otlp_compute_top_level_by_span_kind" APM feature if present. - # compute_stats_by_span_kind: false + # compute_stats_by_span_kind: true - ## @param peer_service_aggregation - bool - default: false - ## @env DD_APM_PEER_SERVICE_AGGREGATION - bool - default: false + ## @param peer_service_aggregation - bool - default: true + ## @env DD_APM_PEER_SERVICE_AGGREGATION - bool - default: true ## DEPRECATED - please use `peer_tags_aggregation` instead. - # peer_service_aggregation: false + # peer_service_aggregation: true - ## @param peer_tags_aggregation - bool - default: false - ## @env DD_APM_PEER_TAGS_AGGREGATION - bool - default: false - ## [BETA] Enables aggregation of peer related tags (e.g., `peer.service`, `db.instance`, etc.) in the Agent. + ## @param peer_tags_aggregation - bool - default: true + ## @env DD_APM_PEER_TAGS_AGGREGATION - bool - default: true + ## Enables aggregation of peer related tags (e.g., `peer.service`, `db.instance`, etc.) in the Agent. ## If disabled, aggregated trace stats will not include these tags as dimensions on trace metrics. ## For the best experience with peer tags, Datadog also recommends enabling `compute_stats_by_span_kind`. ## If you are using an OTel tracer, it's best to have both enabled because client/producer spans with relevant peer tags @@ -1355,11 +1355,11 @@ api_key: ## A high cardinality of peer tags or APM resources can also contribute to higher CPU and memory consumption. ## You can check for the cardinality of these fields by making trace search queries in the Datadog UI. ## The default list of peer tags can be found in pkg/trace/stats/concentrator.go. - # peer_tags_aggregation: false + # peer_tags_aggregation: true ## @param peer_tags - list of strings - optional ## @env DD_APM_PEER_TAGS - list of strings - optional - ## [BETA] Optional list of supplementary peer tags that go beyond the defaults. The Datadog backend validates all tags + ## Optional list of supplementary peer tags that go beyond the defaults. The Datadog backend validates all tags ## and will drop ones that are unapproved. # peer_tags: [] @@ -3108,13 +3108,13 @@ api_key: ## @param cpu - string - optional ## @env DD_ADMISSION_CONTROLLER_AUTO_INSTRUMENTATION_INIT_RESOURCES_CPU - string - optional - ## Configures the CPU request and limit for the init containers. + ## Configures the CPU request that will be applied for the init container's CPU request and limit. # # cpu: ## @param memory - string - optional ## @env DD_ADMISSION_CONTROLLER_AUTO_INSTRUMENTATION_INIT_RESOURCES_MEMORY - string - optional - ## Configures the memory request and limit for the init containers. + ## Configures the memory request that will be applied for the init container's memory request and limit. # # memory: diff --git a/pkg/config/model/types.go b/pkg/config/model/types.go index 1d3de47a8952f..b6822bd2d97cb 100644 --- a/pkg/config/model/types.go +++ b/pkg/config/model/types.go @@ -103,6 +103,9 @@ type ReaderWriter interface { type Setup interface { // API implemented by viper.Viper + // BuildSchema should be called when Setup is done, it builds the schema making the config ready for use + BuildSchema() + SetDefault(key string, value interface{}) SetEnvPrefix(in string) diff --git a/pkg/config/model/viper.go b/pkg/config/model/viper.go index 126c5fe782ad9..0fbcbd4b6db4b 100644 --- a/pkg/config/model/viper.go +++ b/pkg/config/model/viper.go @@ -91,9 +91,9 @@ type ValueWithSource struct { Value interface{} } -// IsGreaterThan returns true if the current source is of higher priority than the one given as a parameter -func (s Source) IsGreaterThan(x Source) bool { - return sourcesPriority[s] > sourcesPriority[x] +// IsGreaterOrEqualThan returns true if the current source is of higher priority than the one given as a parameter +func (s Source) IsGreaterOrEqualThan(x Source) bool { + return sourcesPriority[s] >= sourcesPriority[x] } // String casts Source into a string @@ -267,6 +267,11 @@ func (c *safeConfig) GetKnownKeysLowercased() map[string]interface{} { return c.Viper.GetKnownKeys() } +// BuildSchema is a no-op for the viper based config +func (c *safeConfig) BuildSchema() { + // pass +} + // ParseEnvAsStringSlice registers a transformer function to parse an an environment variables as a []string. func (c *safeConfig) ParseEnvAsStringSlice(key string, fn func(string) []string) { c.Lock() diff --git a/pkg/config/nodetreemodel/array_node.go b/pkg/config/nodetreemodel/array_node.go new file mode 100644 index 0000000000000..41f2791aafc3a --- /dev/null +++ b/pkg/config/nodetreemodel/array_node.go @@ -0,0 +1,90 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package nodetreemodel + +import ( + "fmt" + + "github.com/DataDog/datadog-agent/pkg/config/model" +) + +// ArrayNode represents a node with ordered, numerically indexed set of children +type ArrayNode interface { + Size() int + Index(int) (Node, error) +} + +type arrayNodeImpl struct { + nodes []Node + source model.Source +} + +var _ ArrayNode = (*arrayNodeImpl)(nil) +var _ Node = (*arrayNodeImpl)(nil) + +func newArrayNodeImpl(v []interface{}, source model.Source) (Node, error) { + nodes := make([]Node, 0, len(v)) + for _, it := range v { + if n, ok := it.(Node); ok { + nodes = append(nodes, n) + continue + } + n, err := NewNode(it, source) + if err != nil { + return nil, err + } + nodes = append(nodes, n) + } + return &arrayNodeImpl{nodes: nodes}, nil +} + +// GetChild returns an error because array node does not have children accessible by name +func (n *arrayNodeImpl) GetChild(string) (Node, error) { + return nil, fmt.Errorf("arrayNodeImpl.GetChild not implemented") +} + +// Clone clones a LeafNode +func (n *arrayNodeImpl) Clone() Node { + clone := &arrayNodeImpl{nodes: make([]Node, len(n.nodes)), source: n.source} + for idx, n := range n.nodes { + clone.nodes[idx] = n.Clone() + } + return clone +} + +// SourceGreaterOrEqual returns true if the source of the current node is greater or equal to the one given as a +// parameter +func (n *arrayNodeImpl) SourceGreaterOrEqual(source model.Source) bool { + return n.source.IsGreaterOrEqualThan(source) +} + +// ChildrenKeys returns an error because array node does not have children accessible by name +func (n *arrayNodeImpl) ChildrenKeys() ([]string, error) { + return nil, fmt.Errorf("arrayNodeImpl.ChildrenKeys not implemented") +} + +// Size returns number of children in the list +func (n *arrayNodeImpl) Size() int { + return len(n.nodes) +} + +// Index returns the kth element of the list +func (n *arrayNodeImpl) Index(k int) (Node, error) { + if k < 0 || k >= len(n.nodes) { + return nil, ErrNotFound + } + return n.nodes[k], nil +} + +// Source returns the source for this leaf +func (n *arrayNodeImpl) Source() model.Source { + return n.source +} + +// Set is not implemented for an array node +func (n *arrayNodeImpl) Set([]string, interface{}, model.Source) (bool, error) { + return false, fmt.Errorf("not implemented") +} diff --git a/pkg/config/nodetreemodel/config.go b/pkg/config/nodetreemodel/config.go index 4194c4f115006..58c9f3cce7b6f 100644 --- a/pkg/config/nodetreemodel/config.go +++ b/pkg/config/nodetreemodel/config.go @@ -22,6 +22,7 @@ import ( "github.com/DataDog/viper" "github.com/mohae/deepcopy" "github.com/spf13/afero" + "go.uber.org/atomic" "golang.org/x/exp/slices" "github.com/DataDog/datadog-agent/pkg/config/model" @@ -47,9 +48,17 @@ var sources = []model.Source{ // - contains metadata about known keys, env var support type ntmConfig struct { sync.RWMutex - root Node noimpl notImplementedMethods + // ready is whether the schema has been built, which marks the config as ready for use + ready *atomic.Bool + // defaults contains the settings with a default value + defaults InnerNode + // file contains the settings pulled from YAML files + file InnerNode + // root contains the final configuration, it's the result of merging all other tree by ordre of priority + root InnerNode + envPrefix string envKeyReplacer *strings.Replacer @@ -75,6 +84,16 @@ type ntmConfig struct { // extraConfigFilePaths represents additional configuration file paths that will be merged into the main configuration when ReadInConfig() is called. extraConfigFilePaths []string + + // yamlWarnings contains a list of warnings about loaded YAML file. + // TODO: remove 'findUnknownKeys' function from pkg/config/setup in favor of those warnings. We should return + // them from ReadConfig and ReadInConfig. + warnings []string +} + +// NodeTreeConfig is an interface that gives access to nodes +type NodeTreeConfig interface { + GetNode(string) (Node, error) } // OnUpdate adds a callback to the list of receivers to be called each time a value is changed in the configuration @@ -91,29 +110,51 @@ func (c *ntmConfig) getValue(key string) (interface{}, error) { return c.leafAtPath(key).GetAny() } -func (c *ntmConfig) setValueSource(key string, newValue interface{}, source model.Source) { +func (c *ntmConfig) setValueSource(key string, newValue interface{}, source model.Source) { // nolint: unused // TODO fix err := c.leafAtPath(key).SetWithSource(newValue, source) if err != nil { log.Errorf("%s", err) } } +func (c *ntmConfig) set(key string, value interface{}, tree InnerNode, source model.Source) (bool, error) { + parts := strings.Split(strings.ToLower(key), ",") + return tree.SetAt(parts, value, source) +} + +func (c *ntmConfig) setDefault(key string, value interface{}) { + parts := strings.Split(strings.ToLower(key), ",") + // TODO: Ensure that for default tree, setting nil to a node will not override + // an existing value + _, _ = c.defaults.SetAt(parts, value, model.SourceDefault) +} + // Set assigns the newValue to the given key and marks it as originating from the given source func (c *ntmConfig) Set(key string, newValue interface{}, source model.Source) { - if source == model.SourceDefault { - c.SetDefault(key, newValue) - return + var tree InnerNode + + // TODO: have a dedicated mapping in ntmConfig instead of a switch case + // TODO: Default and File source should use SetDefault or ReadConfig instead. Once the defaults are handle we + // should remove those two tree from here and consider this a bug. + switch source { + case model.SourceDefault: + tree = c.defaults + case model.SourceFile: + tree = c.file } - // modify the config then release the lock to avoid deadlocks while notifying - var receivers []model.NotificationReceiver c.Lock() + previousValue, _ := c.getValue(key) - c.setValueSource(key, newValue, source) - if !reflect.DeepEqual(previousValue, newValue) { - // if the value has not changed, do not duplicate the slice so that no callback is called - receivers = slices.Clone(c.notificationReceivers) + _, _ = c.set(key, newValue, tree, source) + updated, _ := c.set(key, newValue, c.root, source) + + // if no value has changed we don't notify + if !updated || reflect.DeepEqual(previousValue, newValue) { + return } + + receivers := slices.Clone(c.notificationReceivers) c.Unlock() // notifying all receiver about the updated setting @@ -129,7 +170,15 @@ func (c *ntmConfig) SetWithoutSource(key string, value interface{}) { // SetDefault assigns the value to the given key using source Default func (c *ntmConfig) SetDefault(key string, value interface{}) { - c.Set(key, value, model.SourceDefault) + c.Lock() + defer c.Unlock() + + if c.isReady() { + panic("cannot SetDefault() once the config has been marked as ready for use") + } + key = strings.ToLower(key) + c.knownKeys[key] = struct{}{} + c.setDefault(key, value) } // UnsetForSource unsets a config entry for a given source @@ -143,8 +192,12 @@ func (c *ntmConfig) UnsetForSource(_key string, _source model.Source) { func (c *ntmConfig) SetKnown(key string) { c.Lock() defer c.Unlock() + if c.isReady() { + panic("cannot SetKnown() once the config has been marked as ready for use") + } key = strings.ToLower(key) c.knownKeys[key] = struct{}{} + c.setDefault(key, nil) } // IsKnown returns whether a key is known @@ -190,6 +243,20 @@ func (c *ntmConfig) GetKnownKeysLowercased() map[string]interface{} { return ret } +// BuildSchema is called when Setup is complete, and the config is ready to be used +func (c *ntmConfig) BuildSchema() { + c.Lock() + defer c.Unlock() + c.ready.Store(true) + // TODO: Build the environment variable tree + // TODO: Instead of assigning defaultSource to root, merge the trees + c.root = c.defaults +} + +func (c *ntmConfig) isReady() bool { + return c.ready.Load() +} + // ParseEnvAsStringSlice registers a transform function to parse an environment variable as a []string. func (c *ntmConfig) ParseEnvAsStringSlice(key string, fn func(string) []string) { c.Lock() @@ -240,19 +307,41 @@ func (c *ntmConfig) AllKeysLowercased() []string { } func (c *ntmConfig) leafAtPath(key string) LeafNode { - pathParts := strings.Split(key, ".") - curr := c.root + if !c.isReady() { + log.Errorf("attempt to read key before config is constructed: %s", key) + return missingLeaf + } + + pathParts := strings.Split(strings.ToLower(key), ".") + var curr Node = c.root for _, part := range pathParts { next, err := curr.GetChild(part) if err != nil { - return &missingLeaf + return missingLeaf } curr = next } if leaf, ok := curr.(LeafNode); ok { return leaf } - return &missingLeaf + return missingLeaf +} + +// GetNode returns a Node for the given key +func (c *ntmConfig) GetNode(key string) (Node, error) { + if !c.isReady() { + return nil, log.Errorf("attempt to read key before config is constructed: %s", key) + } + pathParts := strings.Split(key, ".") + var curr Node = c.root + for _, part := range pathParts { + next, err := curr.GetChild(part) + if err != nil { + return nil, err + } + curr = next + } + return curr, nil } // Get returns a copy of the value for the given key @@ -490,25 +579,29 @@ func (c *ntmConfig) mergeWithEnvPrefix(key string) string { func (c *ntmConfig) BindEnv(key string, envvars ...string) { c.Lock() defer c.Unlock() - var envKeys []string - // If one input is given, viper derives an env key from it; otherwise, all inputs after - // the first are literal env vars. + if c.isReady() { + panic("cannot BindEnv() once the config has been marked as ready for use") + } + key = strings.ToLower(key) + + // If only a key was given, with no associated envvars, then derive + // an envvar from the key name if len(envvars) == 0 { - envKeys = []string{c.mergeWithEnvPrefix(key)} - } else { - envKeys = envvars + envvars = []string{c.mergeWithEnvPrefix(key)} } - for _, key := range envKeys { + for _, envvar := range envvars { // apply EnvKeyReplacer to each key if c.envKeyReplacer != nil { - key = c.envKeyReplacer.Replace(key) + envvar = c.envKeyReplacer.Replace(envvar) } - c.configEnvVars[key] = struct{}{} + // TODO: Use envvar to build the envvar source tree + c.configEnvVars[envvar] = struct{}{} } - c.logErrorNotImplemented("BindEnv") + c.knownKeys[key] = struct{}{} + c.setDefault(key, nil) } // SetEnvKeyReplacer binds a replacer function for keys @@ -697,10 +790,13 @@ func (c *ntmConfig) Object() model.Reader { // NewConfig returns a new Config object. func NewConfig(name string, envPrefix string, envKeyReplacer *strings.Replacer) model.Config { config := ntmConfig{ + ready: atomic.NewBool(false), noimpl: ¬ImplMethodsImpl{}, configEnvVars: map[string]struct{}{}, knownKeys: map[string]struct{}{}, unknownKeys: map[string]struct{}{}, + defaults: newInnerNodeImpl(), + file: newInnerNodeImpl(), } config.SetTypeByDefaultValue(true) diff --git a/pkg/config/nodetreemodel/config_test.go b/pkg/config/nodetreemodel/config_test.go new file mode 100644 index 0000000000000..caff3e69eef4b --- /dev/null +++ b/pkg/config/nodetreemodel/config_test.go @@ -0,0 +1,30 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package nodetreemodel + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +// The current implementation uses NewNode to build the tree, but it treats leafs with +// map data as though those maps should also become nodes. +func TestBuildDefaultMakesTooManyNodes(t *testing.T) { + t.Skip("test fails because the tree builder is too aggressive in making nodes") + + cfg := NewConfig("test", "", nil) + cfg.BindEnvAndSetDefault("kubernetes_node_annotations_as_tags", map[string]string{"cluster.k8s.io/machine": "kube_machine"}) + cfg.BuildSchema() + // Ensure the config is node based + nodeTreeConfig, ok := cfg.(NodeTreeConfig) + require.Equal(t, ok, true) + // Assert that the key is a leaf node, since it was directly added by BindEnvAndSetDefault + n, err := nodeTreeConfig.GetNode("kubernetes_node_annotations_as_tags") + require.NoError(t, err) + _, ok = n.(LeafNode) + require.Equal(t, ok, true) +} diff --git a/pkg/config/nodetreemodel/go.mod b/pkg/config/nodetreemodel/go.mod index 68a7ed4848cb1..0d13296f2f8c5 100644 --- a/pkg/config/nodetreemodel/go.mod +++ b/pkg/config/nodetreemodel/go.mod @@ -15,6 +15,7 @@ require ( github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 github.com/spf13/afero v1.11.0 github.com/stretchr/testify v1.9.0 + go.uber.org/atomic v1.11.0 golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 gopkg.in/yaml.v2 v2.4.0 ) @@ -32,7 +33,6 @@ require ( github.com/spf13/cast v1.3.0 // indirect github.com/spf13/jwalterweatherman v1.0.0 // indirect github.com/spf13/pflag v1.0.3 // indirect - go.uber.org/atomic v1.11.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/text v0.19.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/pkg/config/nodetreemodel/inner_node.go b/pkg/config/nodetreemodel/inner_node.go new file mode 100644 index 0000000000000..b4048eb5c1fe3 --- /dev/null +++ b/pkg/config/nodetreemodel/inner_node.go @@ -0,0 +1,175 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package nodetreemodel + +import ( + "fmt" + "slices" + "strings" + + "github.com/DataDog/datadog-agent/pkg/config/model" + "golang.org/x/exp/maps" +) + +// innerNode represents an non-leaf node of the config +type innerNode struct { + val map[string]Node + // remapCase maps each lower-case key to the original case. This + // enables GetChild to retrieve values using case-insensitive keys + remapCase map[string]string +} + +func newInnerNodeImpl() *innerNode { + return &innerNode{val: map[string]Node{}, remapCase: map[string]string{}} +} + +func newInnerNodeImplWithData(v map[string]interface{}, source model.Source) (*innerNode, error) { + children := map[string]Node{} + for name, value := range v { + n, err := NewNode(value, source) + if err != nil { + return nil, err + } + children[name] = n + } + in := &innerNode{val: children} + in.makeRemapCase() + return in, nil +} + +var _ Node = (*innerNode)(nil) + +// Clone clones a InnerNode and all its children +func (n *innerNode) Clone() Node { + clone := newInnerNodeImpl() + + for k, node := range n.val { + clone.val[k] = node.Clone() + } + clone.makeRemapCase() + return clone +} + +// makeRemapCase creates a map that converts keys from their lower-cased version to their original case +func (n *innerNode) makeRemapCase() { + remap := make(map[string]string) + for k := range n.val { + remap[strings.ToLower(k)] = k + } + n.remapCase = remap +} + +// GetChild returns the child node at the given case-insensitive key, or an error if not found +func (n *innerNode) GetChild(key string) (Node, error) { + mkey := n.remapCase[strings.ToLower(key)] + child, found := n.val[mkey] + if !found { + return nil, ErrNotFound + } + return child, nil +} + +// HasChild returns true if the node has a child for that given key +func (n *innerNode) HasChild(key string) bool { + _, ok := n.val[key] + return ok +} + +// Merge mergs src node within current tree +func (n *innerNode) Merge(src InnerNode) error { + defer n.makeRemapCase() + + for _, name := range src.ChildrenKeys() { + srcChild, _ := src.GetChild(name) + + if !n.HasChild(name) { + n.val[name] = srcChild.Clone() + } else { + // We alredy have child with the same name + + dstChild, _ := n.GetChild(name) + + dstLeaf, dstIsLeaf := dstChild.(LeafNode) + srcLeaf, srcIsLeaf := srcChild.(LeafNode) + if srcIsLeaf != dstIsLeaf { + return fmt.Errorf("tree conflict, can't merge inner and leaf nodes for '%s'", name) + } + + if srcIsLeaf { + if srcLeaf.SourceGreaterOrEqual(dstLeaf.Source()) { + n.val[name] = srcLeaf.Clone() + } + } else { + dstInner, _ := dstChild.(InnerNode) + childInner, _ := srcChild.(InnerNode) + if err := dstInner.Merge(childInner); err != nil { + return err + } + } + } + } + return nil +} + +// ChildrenKeys returns the list of keys of the children of the given node, if it is a map +func (n *innerNode) ChildrenKeys() []string { + mapkeys := maps.Keys(n.val) + // map keys are iterated non-deterministically, sort them + slices.Sort(mapkeys) + return mapkeys +} + +// SetAt sets a value in the tree by either creating a leaf node or updating one if the priority is equal or higher than +// the existing one. The function returns true if an update was done or false if nothing was changed. +// +// The key parts should already be lowercased. +func (n *innerNode) SetAt(key []string, value interface{}, source model.Source) (bool, error) { + keyLen := len(key) + if keyLen == 0 { + return false, fmt.Errorf("empty key given to Set") + } + + defer n.makeRemapCase() + + part := key[0] + if keyLen == 1 { + node, ok := n.val[part] + if !ok { + n.val[part] = newLeafNodeImpl(value, source) + return true, nil + } + + if leaf, ok := node.(LeafNode); ok { + if leaf.Source().IsGreaterOrEqualThan(source) { + n.val[part] = newLeafNodeImpl(value, source) + return true, nil + } + return false, nil + } + return false, fmt.Errorf("can't overrides inner node with a leaf node") + } + + // new node case + if _, ok := n.val[part]; !ok { + newNode := newInnerNodeImpl() + n.val[part] = newNode + return newNode.SetAt(key[1:keyLen], value, source) + } + + // update node case + child, err := n.GetChild(part) + node, ok := child.(InnerNode) + if err != nil || !ok { + return false, fmt.Errorf("can't update a leaf node into a inner node") + } + return node.SetAt(key[1:keyLen], value, source) +} + +// InsertChildNode sets a node in the current node +func (n *innerNode) InsertChildNode(name string, node Node) { + n.val[name] = node + n.makeRemapCase() +} diff --git a/pkg/config/nodetreemodel/inner_node_test.go b/pkg/config/nodetreemodel/inner_node_test.go new file mode 100644 index 0000000000000..5e87583712fc1 --- /dev/null +++ b/pkg/config/nodetreemodel/inner_node_test.go @@ -0,0 +1,149 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package nodetreemodel + +import ( + "testing" + + "github.com/DataDog/datadog-agent/pkg/config/model" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMergeToEmpty(t *testing.T) { + obj := map[string]interface{}{ + "a": "apple", + "b": 123, + "c": map[string]interface{}{ + "d": true, + "e": map[string]interface{}{ + "f": 456, + }, + }, + } + + node, err := NewNode(obj, model.SourceFile) + require.NoError(t, err) + src, ok := node.(InnerNode) + require.True(t, ok) + + dst := newInnerNodeImpl() + + err = dst.Merge(src) + require.NoError(t, err) + + expected := &innerNode{ + remapCase: map[string]string{"a": "a", "b": "b", "c": "c"}, + val: map[string]Node{ + "a": &leafNodeImpl{val: "apple", source: model.SourceFile}, + "b": &leafNodeImpl{val: 123, source: model.SourceFile}, + "c": &innerNode{ + remapCase: map[string]string{"d": "d", "e": "e"}, + val: map[string]Node{ + "d": &leafNodeImpl{val: true, source: model.SourceFile}, + "e": &innerNode{ + remapCase: map[string]string{"f": "f"}, + val: map[string]Node{ + "f": &leafNodeImpl{val: 456, source: model.SourceFile}, + }, + }, + }, + }, + }, + } + assert.Equal(t, expected, dst) +} + +func TestMergeTwoTree(t *testing.T) { + obj := map[string]interface{}{ + "a": "apple", + "b": 123, + "c": map[string]interface{}{ + "d": true, + "e": map[string]interface{}{ + "f": 456, + }, + }, + } + + obj2 := map[string]interface{}{ + "a": "orange", + "z": 987, + "c": map[string]interface{}{ + "d": false, + "e": map[string]interface{}{ + "f": 456, + "g": "kiwi", + }, + }, + } + + node, err := NewNode(obj, model.SourceFile) + require.NoError(t, err) + base, ok := node.(InnerNode) + require.True(t, ok) + + node, err = NewNode(obj2, model.SourceEnvVar) + require.NoError(t, err) + overwrite, ok := node.(InnerNode) + require.True(t, ok) + + err = base.Merge(overwrite) + require.NoError(t, err) + + expected := &innerNode{ + remapCase: map[string]string{"a": "a", "b": "b", "z": "z", "c": "c"}, + val: map[string]Node{ + "a": &leafNodeImpl{val: "orange", source: model.SourceEnvVar}, + "b": &leafNodeImpl{val: 123, source: model.SourceFile}, + "z": &leafNodeImpl{val: 987, source: model.SourceEnvVar}, + "c": &innerNode{ + remapCase: map[string]string{"d": "d", "e": "e"}, + val: map[string]Node{ + "d": &leafNodeImpl{val: false, source: model.SourceEnvVar}, + "e": &innerNode{ + remapCase: map[string]string{"f": "f", "g": "g"}, + val: map[string]Node{ + "f": &leafNodeImpl{val: 456, source: model.SourceEnvVar}, + "g": &leafNodeImpl{val: "kiwi", source: model.SourceEnvVar}, + }, + }, + }, + }, + }, + } + assert.Equal(t, expected, base) +} + +func TestMergeErrorLeafToNode(t *testing.T) { + obj := map[string]interface{}{ + "a": "apple", + } + + obj2 := map[string]interface{}{ + "a": map[string]interface{}{}, + } + + node, err := NewNode(obj, model.SourceFile) + require.NoError(t, err) + base, ok := node.(InnerNode) + require.True(t, ok) + + node, err = NewNode(obj2, model.SourceEnvVar) + require.NoError(t, err) + overwrite, ok := node.(InnerNode) + require.True(t, ok) + + // checking leaf to node + err = base.Merge(overwrite) + require.Error(t, err) + assert.Equal(t, "tree conflict, can't merge inner and leaf nodes for 'a'", err.Error()) + + // checking node to leaf + err = overwrite.Merge(base) + require.Error(t, err) + assert.Equal(t, "tree conflict, can't merge inner and leaf nodes for 'a'", err.Error()) +} diff --git a/pkg/config/nodetreemodel/leaf.go b/pkg/config/nodetreemodel/leaf_node.go similarity index 52% rename from pkg/config/nodetreemodel/leaf.go rename to pkg/config/nodetreemodel/leaf_node.go index a3a4290c8ca68..5e8943cba5a94 100644 --- a/pkg/config/nodetreemodel/leaf.go +++ b/pkg/config/nodetreemodel/leaf_node.go @@ -12,89 +12,51 @@ import ( "github.com/DataDog/datadog-agent/pkg/config/model" ) -// ArrayNode represents a node with ordered, numerically indexed set of children -type ArrayNode interface { - Size() int - Index(int) (Node, error) -} - -type arrayNodeImpl struct { - nodes []Node -} - -func newArrayNodeImpl(v []interface{}, source model.Source) (Node, error) { - nodes := make([]Node, 0, len(v)) - for _, it := range v { - if n, ok := it.(Node); ok { - nodes = append(nodes, n) - continue - } - n, err := NewNode(it, source) - if err != nil { - return nil, err - } - nodes = append(nodes, n) - } - return &arrayNodeImpl{nodes: nodes}, nil -} - -// GetChild returns an error because array node does not have children accessible by name -func (n *arrayNodeImpl) GetChild(string) (Node, error) { - return nil, fmt.Errorf("arrayNodeImpl.GetChild not implemented") -} - -// ChildrenKeys returns an error because array node does not have children accessible by name -func (n *arrayNodeImpl) ChildrenKeys() ([]string, error) { - return nil, fmt.Errorf("arrayNodeImpl.ChildrenKeys not implemented") +type leafNodeImpl struct { + // val must be a scalar kind + val interface{} + source model.Source } -// Size returns number of children in the list -func (n *arrayNodeImpl) Size() int { - return len(n.nodes) -} +var _ LeafNode = (*leafNodeImpl)(nil) +var _ Node = (*leafNodeImpl)(nil) -// Index returns the kth element of the list -func (n *arrayNodeImpl) Index(k int) (Node, error) { - if k < 0 || k >= len(n.nodes) { - return nil, ErrNotFound +func isScalar(v interface{}) bool { + switch v.(type) { + case int, int8, int16, int32, int64: + return true + case uint, uint8, uint16, uint32, uint64: + return true + case bool, string, float32, float64, time.Time, time.Duration: + return true + default: + return false } - return n.nodes[k], nil } -var _ ArrayNode = (*arrayNodeImpl)(nil) -var _ Node = (*arrayNodeImpl)(nil) - -// leafNode represents a leaf with a scalar value - -type leafNodeImpl struct { - // val must be a scalar kind - val interface{} - source model.Source +func newLeafNodeImpl(v interface{}, source model.Source) Node { + return &leafNodeImpl{val: v, source: source} } -func newLeafNodeImpl(v interface{}, source model.Source) (Node, error) { - if isScalar(v) { - return &leafNodeImpl{val: v, source: source}, nil - } - return nil, fmt.Errorf("cannot create leaf node from %v of type %T", v, v) +// Clone clones a LeafNode +func (n *leafNodeImpl) Clone() Node { + return newLeafNodeImpl(n.val, n.source) } -var _ LeafNode = (*leafNodeImpl)(nil) -var _ Node = (*leafNodeImpl)(nil) +// SourceGreaterOrEqual returns true if the source of the current node is greater or equal to the one given as a +// parameter +func (n *leafNodeImpl) SourceGreaterOrEqual(source model.Source) bool { + return n.source.IsGreaterOrEqualThan(source) +} // GetChild returns an error because a leaf has no children func (n *leafNodeImpl) GetChild(key string) (Node, error) { return nil, fmt.Errorf("can't GetChild(%s) of a leaf node", key) } -// ChildrenKeys returns an error because a leaf has no children -func (n *leafNodeImpl) ChildrenKeys() ([]string, error) { - return nil, fmt.Errorf("can't get ChildrenKeys of a leaf node") -} - // GetAny returns the scalar as an interface func (n *leafNodeImpl) GetAny() (interface{}, error) { - return n, nil + return n.val, nil } // GetBool returns the scalar as a bool, or an error otherwise @@ -127,7 +89,7 @@ func (n *leafNodeImpl) GetDuration() (time.Duration, error) { return time.Duration(0), fmt.Errorf("not implemented") } -// Set assigns a value in the config, for the given source +// SetWithSource assigns a value in the config, for the given source func (n *leafNodeImpl) SetWithSource(newValue interface{}, source model.Source) error { // TODO: enforce type-checking, return an error if type changes n.val = newValue @@ -135,3 +97,13 @@ func (n *leafNodeImpl) SetWithSource(newValue interface{}, source model.Source) // TODO: Record previous value and source return nil } + +// Source returns the source for this leaf +func (n *leafNodeImpl) Source() model.Source { + return n.source +} + +// Set is not implemented for a leaf node +func (n *leafNodeImpl) Set([]string, interface{}, model.Source) (bool, error) { + return false, fmt.Errorf("not implemented") +} diff --git a/pkg/config/nodetreemodel/missing.go b/pkg/config/nodetreemodel/missing_node.go similarity index 76% rename from pkg/config/nodetreemodel/missing.go rename to pkg/config/nodetreemodel/missing_node.go index 79d470b702a3f..1e001dfcbabaf 100644 --- a/pkg/config/nodetreemodel/missing.go +++ b/pkg/config/nodetreemodel/missing_node.go @@ -15,7 +15,13 @@ import ( // missingLeafImpl is a none-object representing when a child node is missing type missingLeafImpl struct{} -var missingLeaf missingLeafImpl +var _ Node = (*missingLeafImpl)(nil) + +var missingLeaf = &missingLeafImpl{} + +func (m *missingLeafImpl) GetChild(string) (Node, error) { + return nil, fmt.Errorf("GetChild(): missing") +} func (m *missingLeafImpl) GetAny() (any, error) { return nil, fmt.Errorf("GetAny(): missing") @@ -48,3 +54,15 @@ func (m *missingLeafImpl) GetDuration() (time.Duration, error) { func (m *missingLeafImpl) SetWithSource(interface{}, model.Source) error { return fmt.Errorf("SetWithSource(): missing") } + +func (m *missingLeafImpl) Source() model.Source { + return model.SourceUnknown +} + +func (m *missingLeafImpl) Clone() Node { + return m +} + +func (m *missingLeafImpl) SourceGreaterOrEqual(model.Source) bool { + return false +} diff --git a/pkg/config/nodetreemodel/node.go b/pkg/config/nodetreemodel/node.go index e13580041fcbe..3e73528bf0f01 100644 --- a/pkg/config/nodetreemodel/node.go +++ b/pkg/config/nodetreemodel/node.go @@ -7,12 +7,9 @@ package nodetreemodel import ( "fmt" - "slices" - "strings" "time" "github.com/DataDog/datadog-agent/pkg/config/model" - "golang.org/x/exp/maps" ) // ErrNotFound is an error for when a key is not found @@ -22,14 +19,14 @@ var ErrNotFound = fmt.Errorf("not found") func NewNode(v interface{}, source model.Source) (Node, error) { switch it := v.(type) { case map[interface{}]interface{}: - return newMapNodeImpl(mapInterfaceToMapString(it), source) + return newInnerNodeImplWithData(mapInterfaceToMapString(it), source) case map[string]interface{}: - return newMapNodeImpl(it, source) + return newInnerNodeImplWithData(it, source) case []interface{}: return newArrayNodeImpl(it, source) } if isScalar(v) { - return newLeafNodeImpl(v, source) + return newLeafNodeImpl(v, source), nil } // Finally, try determining node type using reflection, should only be needed for unit tests that // supply data that isn't one of the "plain" types produced by parsing json, yaml, etc @@ -40,14 +37,38 @@ func NewNode(v interface{}, source model.Source) (Node, error) { return node, err } -// Node represents an arbitrary node +// NodeType represents node types in the tree (ie: inner or leaf) +type NodeType int + +const ( + // InnerType is a inner node in the config + InnerType NodeType = iota + // LeafType is a leaf node in the config + LeafType + // MissingType is a none-object representing when a child node is missing + MissingType +) + +// Node represents a arbitrary node type Node interface { + Clone() Node GetChild(string) (Node, error) - ChildrenKeys() ([]string, error) +} + +// InnerNode represents an inner node in the config +type InnerNode interface { + Node + HasChild(string) bool + ChildrenKeys() []string + Merge(InnerNode) error + SetAt([]string, interface{}, model.Source) (bool, error) + InsertChildNode(string, Node) + makeRemapCase() } // LeafNode represents a leaf node of the config type LeafNode interface { + Node GetAny() (interface{}, error) GetBool() (bool, error) GetInt() (int, error) @@ -56,125 +77,6 @@ type LeafNode interface { GetTime() (time.Time, error) GetDuration() (time.Duration, error) SetWithSource(interface{}, model.Source) error -} - -// innerNode represents an non-leaf node of the config -type innerNode struct { - val map[string]Node - // remapCase maps each lower-case key to the original case. This - // enables GetChild to retrieve values using case-insensitive keys - remapCase map[string]string -} - -func newMapNodeImpl(v map[string]interface{}, source model.Source) (*innerNode, error) { - children := map[string]Node{} - for name, value := range v { - n, err := NewNode(value, source) - if err != nil { - return nil, err - } - children[name] = n - } - return &innerNode{val: children, remapCase: makeRemapCase(children)}, nil -} - -var _ Node = (*innerNode)(nil) - -/////// - -func isScalar(v interface{}) bool { - switch v.(type) { - case int, int8, int16, int32, int64: - return true - case uint, uint8, uint16, uint32, uint64: - return true - case bool, string, float32, float64, time.Time, time.Duration: - return true - default: - return false - } -} - -// creates a map that converts keys from their lower-cased version to their original case -func makeRemapCase(m map[string]Node) map[string]string { - remap := make(map[string]string) - for k := range m { - remap[strings.ToLower(k)] = k - } - return remap -} - -///// - -// GetChild returns the child node at the given case-insensitive key, or an error if not found -func (n *innerNode) GetChild(key string) (Node, error) { - mkey := n.remapCase[strings.ToLower(key)] - child, found := n.val[mkey] - if !found { - return nil, ErrNotFound - } - return child, nil -} - -// Merge mergs src node within current tree -func (n *innerNode) Merge(srcNode Node) error { - src, ok := srcNode.(*innerNode) - if !ok { - return fmt.Errorf("can't merge leaf into a node") - } - - childrenNames := maps.Keys(src.val) - // map keys are iterated non-deterministically, sort them - slices.Sort(childrenNames) - - for _, name := range childrenNames { - child := src.val[name] - srcLeaf, srcIsLeaf := child.(*leafNodeImpl) - - if _, ok := n.val[name]; !ok { - // child from src is unknown, we must create a new node - if srcIsLeaf { - n.val[name] = &leafNodeImpl{ - val: srcLeaf.val, - source: srcLeaf.source, - } - } else { - newNode := &innerNode{ - val: map[string]Node{}, - remapCase: map[string]string{}, - } - if err := newNode.Merge(src.val[name]); err != nil { - return err - } - n.val[name] = newNode - } - } else { - // We alredy have child with the same name: update our child - dstLeaf, dstIsLeaf := n.val[name].(*leafNodeImpl) - if srcIsLeaf != dstIsLeaf { - return fmt.Errorf("tree conflict, can't merge lead and non leaf nodes for '%s'", name) - } - - if srcIsLeaf { - if srcLeaf.source.IsGreaterThan(dstLeaf.source) { - dstLeaf.val = srcLeaf.val - dstLeaf.source = srcLeaf.source - } - } else { - if err := n.val[name].(*innerNode).Merge(child); err != nil { - return err - } - } - } - } - n.remapCase = makeRemapCase(n.val) - return nil -} - -// ChildrenKeys returns the list of keys of the children of the given node, if it is a map -func (n *innerNode) ChildrenKeys() ([]string, error) { - mapkeys := maps.Keys(n.val) - // map keys are iterated non-deterministically, sort them - slices.Sort(mapkeys) - return mapkeys, nil + Source() model.Source + SourceGreaterOrEqual(model.Source) bool } diff --git a/pkg/config/nodetreemodel/node_test.go b/pkg/config/nodetreemodel/node_test.go index 450464f3eb525..5588795f3d96e 100644 --- a/pkg/config/nodetreemodel/node_test.go +++ b/pkg/config/nodetreemodel/node_test.go @@ -10,7 +10,6 @@ import ( "github.com/DataDog/datadog-agent/pkg/config/model" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestNewNodeAndNodeMethods(t *testing.T) { @@ -23,11 +22,13 @@ func TestNewNodeAndNodeMethods(t *testing.T) { }, } - n, err := NewNode(obj, model.SourceDefault) + node, err := NewNode(obj, model.SourceDefault) assert.NoError(t, err) - keys, err := n.ChildrenKeys() - assert.NoError(t, err) + n, ok := node.(InnerNode) + assert.True(t, ok) + + keys := n.ChildrenKeys() assert.Equal(t, keys, []string{"a", "b", "c"}) first, err := n.GetChild("a") @@ -46,13 +47,11 @@ func TestNewNodeAndNodeMethods(t *testing.T) { assert.NoError(t, err) assert.Equal(t, num, 123) - third, err := n.GetChild("c") + child, err := n.GetChild("c") assert.NoError(t, err) - _, ok := third.(LeafNode) - assert.Equal(t, ok, false) + third := child.(InnerNode) - keys, err = third.ChildrenKeys() - assert.NoError(t, err) + keys = third.ChildrenKeys() assert.Equal(t, keys, []string{"d", "e"}) fourth, err := third.GetChild("d") @@ -66,141 +65,3 @@ func TestNewNodeAndNodeMethods(t *testing.T) { _, err = third.GetChild("e") assert.NoError(t, err) } - -func TestMergeToEmpty(t *testing.T) { - obj := map[string]interface{}{ - "a": "apple", - "b": 123, - "c": map[string]interface{}{ - "d": true, - "e": map[string]interface{}{ - "f": 456, - }, - }, - } - - src, err := NewNode(obj, model.SourceFile) - require.NoError(t, err) - - dst, err := newMapNodeImpl(nil, model.SourceDefault) - require.NoError(t, err) - - err = dst.Merge(src) - require.NoError(t, err) - - expected := &innerNode{ - remapCase: map[string]string{"a": "a", "b": "b", "c": "c"}, - val: map[string]Node{ - "a": &leafNodeImpl{val: "apple", source: model.SourceFile}, - "b": &leafNodeImpl{val: 123, source: model.SourceFile}, - "c": &innerNode{ - remapCase: map[string]string{"d": "d", "e": "e"}, - val: map[string]Node{ - "d": &leafNodeImpl{val: true, source: model.SourceFile}, - "e": &innerNode{ - remapCase: map[string]string{"f": "f"}, - val: map[string]Node{ - "f": &leafNodeImpl{val: 456, source: model.SourceFile}, - }, - }, - }, - }, - }, - } - assert.Equal(t, expected, dst) -} - -func TestMergeTwoTree(t *testing.T) { - obj := map[string]interface{}{ - "a": "apple", - "b": 123, - "c": map[string]interface{}{ - "d": true, - "e": map[string]interface{}{ - "f": 456, - }, - }, - } - - obj2 := map[string]interface{}{ - "a": "orange", - "z": 987, - "c": map[string]interface{}{ - "d": false, - "e": map[string]interface{}{ - "f": 456, - "g": "kiwi", - }, - }, - } - - base, err := NewNode(obj, model.SourceFile) - require.NoError(t, err) - - overwrite, err := NewNode(obj2, model.SourceEnvVar) - require.NoError(t, err) - - err = base.(*innerNode).Merge(overwrite) - require.NoError(t, err) - - expected := &innerNode{ - remapCase: map[string]string{"a": "a", "b": "b", "z": "z", "c": "c"}, - val: map[string]Node{ - "a": &leafNodeImpl{val: "orange", source: model.SourceEnvVar}, - "b": &leafNodeImpl{val: 123, source: model.SourceFile}, - "z": &leafNodeImpl{val: 987, source: model.SourceEnvVar}, - "c": &innerNode{ - remapCase: map[string]string{"d": "d", "e": "e"}, - val: map[string]Node{ - "d": &leafNodeImpl{val: false, source: model.SourceEnvVar}, - "e": &innerNode{ - remapCase: map[string]string{"f": "f", "g": "g"}, - val: map[string]Node{ - "f": &leafNodeImpl{val: 456, source: model.SourceEnvVar}, - "g": &leafNodeImpl{val: "kiwi", source: model.SourceEnvVar}, - }, - }, - }, - }, - }, - } - assert.Equal(t, expected, base) -} - -func TestMergeErrorLeafToNode(t *testing.T) { - obj := map[string]interface{}{ - "a": "apple", - } - - obj2 := map[string]interface{}{ - "a": map[string]interface{}{}, - } - - base, err := NewNode(obj, model.SourceFile) - require.NoError(t, err) - - overwrite, err := NewNode(obj2, model.SourceEnvVar) - require.NoError(t, err) - - // checking leaf to node - err = base.(*innerNode).Merge(overwrite) - require.Error(t, err) - assert.Equal(t, "tree conflict, can't merge lead and non leaf nodes for 'a'", err.Error()) - - // checking node to leaf - err = overwrite.(*innerNode).Merge(base) - require.Error(t, err) - assert.Equal(t, "tree conflict, can't merge lead and non leaf nodes for 'a'", err.Error()) -} - -func TestMergeErrorLeaf(t *testing.T) { - base, err := newMapNodeImpl(nil, model.SourceDefault) - require.NoError(t, err) - - leaf, err := newLeafNodeImpl(123, model.SourceDefault) - require.NoError(t, err) - - err = base.Merge(leaf) - require.Error(t, err) - assert.Equal(t, "can't merge leaf into a node", err.Error()) -} diff --git a/pkg/config/nodetreemodel/read_config_file.go b/pkg/config/nodetreemodel/read_config_file.go index eb246958b621b..942062c9fb536 100644 --- a/pkg/config/nodetreemodel/read_config_file.go +++ b/pkg/config/nodetreemodel/read_config_file.go @@ -6,13 +6,36 @@ package nodetreemodel import ( + "fmt" "io" "os" + "reflect" + "strings" "github.com/DataDog/datadog-agent/pkg/config/model" "gopkg.in/yaml.v2" ) +func (c *ntmConfig) mergeAllLayers() error { + root := newInnerNodeImpl() + + treeList := []InnerNode{ + c.defaults, + c.file, + } + + // TODO: handle all configuration sources + for _, tree := range treeList { + err := root.Merge(tree) + if err != nil { + return err + } + } + + c.root = root + return nil +} + func (c *ntmConfig) getConfigFile() string { if c.configFile == "" { return "datadog.yaml" @@ -24,55 +47,138 @@ func (c *ntmConfig) getConfigFile() string { func (c *ntmConfig) ReadInConfig() error { c.Lock() defer c.Unlock() - // ReadInConfig reset configuration with the main config file - err := c.readInConfig() - if err != nil { - return err - } - // Read extra config files - // TODO: handle c.extraConfigFilePaths, read and merge files - return nil -} - -func (c *ntmConfig) readInConfig() error { - filename := c.getConfigFile() - content, err := os.ReadFile(filename) + err := c.readInConfig(c.getConfigFile()) if err != nil { return err } - root, err := c.readConfigurationContent(content) - if err != nil { - return err + + for _, f := range c.extraConfigFilePaths { + err = c.readInConfig(f) + if err != nil { + return err + } } - c.root = root - return nil + return c.mergeAllLayers() } // ReadConfig wraps Viper for concurrent access func (c *ntmConfig) ReadConfig(in io.Reader) error { c.Lock() defer c.Unlock() + content, err := io.ReadAll(in) if err != nil { return err } - root, err := c.readConfigurationContent(content) + if err := c.readConfigurationContent(content); err != nil { + return err + } + return c.mergeAllLayers() +} + +func (c *ntmConfig) readInConfig(filePath string) error { + content, err := os.ReadFile(filePath) if err != nil { return err } - c.root = root - return nil + return c.readConfigurationContent(content) } -func (c *ntmConfig) readConfigurationContent(content []byte) (Node, error) { +func (c *ntmConfig) readConfigurationContent(content []byte) error { var obj map[string]interface{} if err := yaml.Unmarshal(content, &obj); err != nil { - return nil, err + return err } - root, err := NewNode(obj, model.SourceFile) - if err != nil { - return nil, err + c.warnings = append(c.warnings, loadYamlInto(c.defaults, c.file, obj, "")...) + // Mark the config as ready + c.ready.Store(true) + return nil +} + +// toMapStringInterface convert any type of map into a map[string]interface{} +func toMapStringInterface(data any, path string) (map[string]interface{}, error) { + if res, ok := data.(map[string]interface{}); ok { + return res, nil + } + + v := reflect.ValueOf(data) + switch v.Kind() { + case reflect.Map: + convert := map[string]interface{}{} + iter := v.MapRange() + for iter.Next() { + key := iter.Key() + switch k := key.Interface().(type) { + case string: + convert[k] = iter.Value().Interface() + default: + return nil, fmt.Errorf("error non-string key type for map for '%s'", path) + } + } + return convert, nil + } + return nil, fmt.Errorf("invalid type from configuration for key '%s'", path) +} + +// loadYamlInto fetch the value for known setings and set them in a tree. The function returns a list of warning about +// unknown settings or invalid types from the YAML. +// +// The function traverses a object loaded from YAML, checking if each node is known within the configuration. +// If known, the value from the YAML blob is imported into the 'dest' tree. If unknown, a warning will be created. +func loadYamlInto(defaults InnerNode, dest InnerNode, data map[string]interface{}, path string) []string { + if path != "" { + path = path + "." + } + + warnings := []string{} + for key, value := range data { + key = strings.ToLower(key) + curPath := path + key + + // check if the key is know in the defaults + defaultNode, err := defaults.GetChild(key) + if err != nil { + warnings = append(warnings, fmt.Sprintf("unknown key from YAML: %s", curPath)) + continue + } + + // if the default is a leaf we create a new leaf in dest + if _, isLeaf := defaultNode.(LeafNode); isLeaf { + // check that dest don't have a inner leaf under that name + c, _ := dest.GetChild(key) + if _, ok := c.(InnerNode); ok { + // Both default and dest have a child but they conflict in type. This should never happen. + warnings = append(warnings, "invalid tree: default and dest tree don't have the same layout") + } else { + dest.InsertChildNode(key, newLeafNodeImpl(value, model.SourceFile)) + } + continue + } + + mapString, err := toMapStringInterface(value, curPath) + if err != nil { + warnings = append(warnings, err.Error()) + } + + // by now we know defaultNode is an InnerNode + defaultNext, _ := defaultNode.(InnerNode) + + if !dest.HasChild(key) { + destInner := newInnerNodeImpl() + warnings = append(warnings, loadYamlInto(defaultNext, destInner, mapString, curPath)...) + dest.InsertChildNode(key, destInner) + continue + } + + child, _ := dest.GetChild(key) + destChildInner, ok := child.(InnerNode) + if !ok { + // Both default and dest have a child but they conflict in type. This should never happen. + warnings = append(warnings, "invalid tree: default and dest tree don't have the same layout") + continue + } + warnings = append(warnings, loadYamlInto(defaultNext, destChildInner, mapString, curPath)...) } - return root, nil + return warnings } diff --git a/pkg/config/nodetreemodel/read_config_file_test.go b/pkg/config/nodetreemodel/read_config_file_test.go index 65a88192254a1..ac8288e7b904f 100644 --- a/pkg/config/nodetreemodel/read_config_file_test.go +++ b/pkg/config/nodetreemodel/read_config_file_test.go @@ -6,10 +6,15 @@ package nodetreemodel import ( + "os" + "path/filepath" "strings" "testing" + "github.com/DataDog/datadog-agent/pkg/config/model" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v2" ) var confYaml = ` @@ -17,39 +22,359 @@ network_devices: snmp_traps: enabled: true port: 1234 - community_strings: ["a","b","c"] - users: - - user: alice - authKey: hunter2 - authProtocol: MD5 - privKey: pswd - privProtocol: AE5 - - user: bob - authKey: "123456" - authProtocol: MD5 - privKey: secret - privProtocol: AE5 bind_host: ok stop_timeout: 4 namespace: abc ` -func TestReadConfigAndGetValues(t *testing.T) { +var confYaml2 = ` +network_devices: + snmp_traps: + port: 9876 + bind_host: ko +` + +func setupDefault(t *testing.T, cfg model.Config) *ntmConfig { + // TODO: we manually create an empty tree until we can create one from the defaults settings. Once remove + // 'SetDefault' should replace those. This entire block should be remove then. + obj := map[string]interface{}{ + "network_devices": map[string]interface{}{ + "snmp_traps": map[string]interface{}{ + "enabled": 0, + "port": 0, + "bind_host": 0, + "stop_timeout": 0, + "namespace": 0, + }, + }, + } + newNode, err := NewNode(obj, model.SourceDefault) + require.NoError(t, err) + defaults, ok := newNode.(InnerNode) + require.True(t, ok) + ntm := cfg.(*ntmConfig) + ntm.defaults = defaults + return ntm +} + +func writeTempFile(t *testing.T, name string, data string) string { + dir := t.TempDir() + confPath := filepath.Join(dir, name) + err := os.WriteFile(confPath, []byte(data), 0600) + require.NoError(t, err) + return confPath +} + +func TestReadConfig(t *testing.T) { cfg := NewConfig("datadog", "DD", nil) + setupDefault(t, cfg) + err := cfg.ReadConfig(strings.NewReader(confYaml)) - if err != nil { - panic(err) + require.NoError(t, err) + + assert.Equal(t, true, cfg.GetBool("network_devices.snmp_traps.enabled")) + assert.Equal(t, 1234, cfg.GetInt("network_devices.snmp_traps.port")) + assert.Equal(t, "ok", cfg.GetString("network_devices.snmp_traps.bind_host")) + assert.Equal(t, 4, cfg.GetInt("network_devices.snmp_traps.stop_timeout")) + assert.Equal(t, "abc", cfg.GetString("network_devices.snmp_traps.namespace")) + + err = cfg.ReadConfig(strings.NewReader(confYaml2)) + require.NoError(t, err) + + assert.Equal(t, true, cfg.GetBool("network_devices.snmp_traps.enabled")) + assert.Equal(t, 9876, cfg.GetInt("network_devices.snmp_traps.port")) + assert.Equal(t, "ko", cfg.GetString("network_devices.snmp_traps.bind_host")) + assert.Equal(t, 4, cfg.GetInt("network_devices.snmp_traps.stop_timeout")) + assert.Equal(t, "abc", cfg.GetString("network_devices.snmp_traps.namespace")) +} + +func TestReadSingleFile(t *testing.T) { + confPath := writeTempFile(t, "datadog.yaml", confYaml) + + cfg := NewConfig("datadog", "DD", nil) + cfg.SetConfigFile(confPath) + setupDefault(t, cfg) + + err := cfg.ReadInConfig() + require.NoError(t, err) + + assert.Equal(t, true, cfg.GetBool("network_devices.snmp_traps.enabled")) + assert.Equal(t, 1234, cfg.GetInt("network_devices.snmp_traps.port")) + assert.Equal(t, "ok", cfg.GetString("network_devices.snmp_traps.bind_host")) + assert.Equal(t, 4, cfg.GetInt("network_devices.snmp_traps.stop_timeout")) + assert.Equal(t, "abc", cfg.GetString("network_devices.snmp_traps.namespace")) +} + +func TestReadFilePathError(t *testing.T) { + cfg := NewConfig("datadog", "DD", nil) + cfg.SetConfigFile("does_not_exist.yaml") + + err := cfg.ReadInConfig() + require.Error(t, err) + + confPath := writeTempFile(t, "datadog.yaml", confYaml) + cfg.SetConfigFile(confPath) + cfg.AddExtraConfigPaths([]string{"does_not_exist.yaml"}) + + err = cfg.ReadInConfig() + require.Error(t, err) +} + +func TestReadInvalidYAML(t *testing.T) { + confPath := writeTempFile(t, "datadog.yaml", "some invalid YAML") + + cfg := NewConfig("datadog", "DD", nil) + cfg.SetConfigFile(confPath) + + err := cfg.ReadInConfig() + require.Error(t, err) + + cfg = NewConfig("datadog", "DD", nil) + err = cfg.ReadConfig(strings.NewReader("some invalid YAML")) + require.Error(t, err) +} + +func TestReadExtraFile(t *testing.T) { + confPath := writeTempFile(t, "datadog.yaml", confYaml) + confPath2 := writeTempFile(t, "datadog_second.yaml", confYaml2) + + cfg := NewConfig("datadog", "DD", nil) + cfg.SetConfigFile(confPath) + cfg.AddExtraConfigPaths([]string{confPath2}) + setupDefault(t, cfg) + + err := cfg.ReadInConfig() + require.NoError(t, err) + + assert.Equal(t, true, cfg.GetBool("network_devices.snmp_traps.enabled")) + assert.Equal(t, 9876, cfg.GetInt("network_devices.snmp_traps.port")) + assert.Equal(t, "ko", cfg.GetString("network_devices.snmp_traps.bind_host")) + assert.Equal(t, 4, cfg.GetInt("network_devices.snmp_traps.stop_timeout")) + assert.Equal(t, "abc", cfg.GetString("network_devices.snmp_traps.namespace")) +} + +func TestYAMLLoad(t *testing.T) { + var yamlPayload = ` +a: orange +c: + d: 1234 +` + yamlData := map[string]interface{}{} + err := yaml.Unmarshal([]byte(yamlPayload), &yamlData) + require.NoError(t, err) + + // TODO: we manually create an empty tree until we can create one from the defaults settings + obj := map[string]interface{}{ + "a": "apple", + "b": 123, + "c": map[string]interface{}{ + "d": true, + "e": map[string]interface{}{ + "f": 456, + }, + }, + } + newNode, err := NewNode(obj, model.SourceDefault) + require.NoError(t, err) + defaults, ok := newNode.(InnerNode) + require.True(t, ok) + + tree := newInnerNodeImpl() + + warnings := loadYamlInto(defaults, tree, yamlData, "") + + assert.Empty(t, warnings) + + expected := &innerNode{ + remapCase: map[string]string{"a": "a", "c": "c"}, + val: map[string]Node{ + "a": &leafNodeImpl{val: "orange", source: model.SourceFile}, + "c": &innerNode{ + remapCase: map[string]string{"d": "d"}, + val: map[string]Node{ + "d": &leafNodeImpl{val: 1234, source: model.SourceFile}, + }, + }, + }, + } + assert.Equal(t, expected, tree) +} + +func TestWarningUnknownKey(t *testing.T) { + var yamlPayload = ` +a: orange +c: + d: 1234 + unknown: key +` + yamlData := map[string]interface{}{} + err := yaml.Unmarshal([]byte(yamlPayload), &yamlData) + require.NoError(t, err) + + // TODO: we manually create an empty tree until we can create one from the defaults settings + obj := map[string]interface{}{ + "a": "apple", + "c": map[string]interface{}{ + "d": true, + }, + } + newNode, err := NewNode(obj, model.SourceDefault) + require.NoError(t, err) + defaults, ok := newNode.(InnerNode) + require.True(t, ok) + + tree := newInnerNodeImpl() + + warnings := loadYamlInto(defaults, tree, yamlData, "") + + require.Len(t, warnings, 1) + assert.Equal(t, "unknown key from YAML: c.unknown", warnings[0]) + + expected := &innerNode{ + remapCase: map[string]string{"a": "a", "c": "c"}, + val: map[string]Node{ + "a": &leafNodeImpl{val: "orange", source: model.SourceFile}, + "c": &innerNode{ + remapCase: map[string]string{"d": "d"}, + val: map[string]Node{ + "d": &leafNodeImpl{val: 1234, source: model.SourceFile}, + }, + }, + }, } + assert.Equal(t, expected, tree) +} + +func TestWarningConflictDataType(t *testing.T) { + var yamlPayload = ` +a: orange +c: 1234 +` + yamlData := map[string]interface{}{} + err := yaml.Unmarshal([]byte(yamlPayload), &yamlData) + require.NoError(t, err) + + // TODO: we manually create an empty tree until we can create one from the defaults settings + obj := map[string]interface{}{ + "a": "apple", + "c": map[string]interface{}{ + "d": true, + }, + } + newNode, err := NewNode(obj, model.SourceDefault) + require.NoError(t, err) + defaults, ok := newNode.(InnerNode) + require.True(t, ok) + + tree := newInnerNodeImpl() + + warnings := loadYamlInto(defaults, tree, yamlData, "") + + require.Len(t, warnings, 1) + assert.Equal(t, "invalid type from configuration for key 'c'", warnings[0]) + + expected := &innerNode{ + remapCase: map[string]string{"a": "a", "c": "c"}, + val: map[string]Node{ + "a": &leafNodeImpl{val: "orange", source: model.SourceFile}, + "c": &innerNode{ + remapCase: map[string]string{}, + val: map[string]Node{}, + }, + }, + } + assert.Equal(t, expected, tree) +} + +func TestWarningConflictNodeTypeInnerToLeaf(t *testing.T) { + var yamlPayload = ` +a: + b: + c: 1234 +` + yamlData := map[string]interface{}{} + err := yaml.Unmarshal([]byte(yamlPayload), &yamlData) + require.NoError(t, err) + + // TODO: we manually create an empty tree until we can create one from the defaults settings + obj := map[string]interface{}{ + "a": map[string]interface{}{ + "b": true, + }, + } + newNode, err := NewNode(obj, model.SourceDefault) + require.NoError(t, err) + defaults, ok := newNode.(InnerNode) + require.True(t, ok) + + tree := newInnerNodeImpl() + tree.SetAt([]string{"a", "b", "c"}, 9876, model.SourceFile) + + warnings := loadYamlInto(defaults, tree, yamlData, "") + + require.Len(t, warnings, 1) + assert.Equal(t, "invalid tree: default and dest tree don't have the same layout", warnings[0]) +} + +func TestWarningConflictNodeTypeLeafToInner(t *testing.T) { + var yamlPayload = ` +a: + b: + c: 1234 +` + yamlData := map[string]interface{}{} + err := yaml.Unmarshal([]byte(yamlPayload), &yamlData) + require.NoError(t, err) + + // TODO: we manually create an empty tree until we can create one from the defaults settings + obj := map[string]interface{}{ + "a": map[string]interface{}{ + "b": map[string]interface{}{ + "c": 1324, + }, + }, + } + newNode, err := NewNode(obj, model.SourceDefault) + require.NoError(t, err) + defaults, ok := newNode.(InnerNode) + require.True(t, ok) + + tree := newInnerNodeImpl() + tree.SetAt([]string{"a", "b"}, 9876, model.SourceFile) + + warnings := loadYamlInto(defaults, tree, yamlData, "") + + require.Len(t, warnings, 1) + assert.Equal(t, "invalid tree: default and dest tree don't have the same layout", warnings[0]) +} + +func TestToMapStringInterface(t *testing.T) { + _, err := toMapStringInterface(nil, "key") + assert.Error(t, err) + _, err = toMapStringInterface(1, "key") + assert.Error(t, err) + _, err = toMapStringInterface("test", "key") + assert.Error(t, err) + _, err = toMapStringInterface(map[int]string{1: "test"}, "key") + assert.Error(t, err) + _, err = toMapStringInterface(map[interface{}]string{1: "test"}, "key") + assert.Error(t, err) + _, err = toMapStringInterface(map[interface{}]string{1: "test", "test2": "test2"}, "key") + assert.Error(t, err) + + data, err := toMapStringInterface(map[string]string{"test": "test"}, "key") + assert.NoError(t, err) + assert.Equal(t, map[string]interface{}{"test": "test"}, data) + + data, err = toMapStringInterface(map[string]interface{}{"test": "test"}, "key") + assert.NoError(t, err) + assert.Equal(t, map[string]interface{}{"test": "test"}, data) - enabled := cfg.GetBool("network_devices.snmp_traps.enabled") - port := cfg.GetInt("network_devices.snmp_traps.port") - bindHost := cfg.GetString("network_devices.snmp_traps.bind_host") - stopTimeout := cfg.GetInt("network_devices.snmp_traps.stop_timeout") - namespace := cfg.GetString("network_devices.snmp_traps.namespace") + data, err = toMapStringInterface(map[interface{}]interface{}{"test": "test"}, "key") + assert.NoError(t, err) + assert.Equal(t, map[string]interface{}{"test": "test"}, data) - assert.Equal(t, enabled, true) - assert.Equal(t, port, 1234) - assert.Equal(t, bindHost, "ok") - assert.Equal(t, stopTimeout, 4) - assert.Equal(t, namespace, "abc") + data, err = toMapStringInterface(map[interface{}]string{"test": "test"}, "key") + assert.NoError(t, err) + assert.Equal(t, map[string]interface{}{"test": "test"}, data) } diff --git a/pkg/config/nodetreemodel/reflection_node.go b/pkg/config/nodetreemodel/reflection_node.go index 5d359f2d1b505..aeb25e5dd6e1b 100644 --- a/pkg/config/nodetreemodel/reflection_node.go +++ b/pkg/config/nodetreemodel/reflection_node.go @@ -8,9 +8,6 @@ package nodetreemodel import ( "fmt" "reflect" - "strings" - "unicode" - "unicode/utf8" "github.com/DataDog/datadog-agent/pkg/config/model" ) @@ -55,87 +52,7 @@ func asReflectionNode(v interface{}) (Node, error) { } res[kstr] = rv.MapIndex(mk).Interface() } - return newMapNodeImpl(res, model.SourceDefault) + return newInnerNodeImplWithData(res, model.SourceDefault) } return nil, errUnknownConversion } - -type structNodeImpl struct { - // val must be a struct - val reflect.Value -} - -// GetChild returns the child node at the given case-insensitive key, or an error if not found -func (n *structNodeImpl) GetChild(key string) (Node, error) { - findex := findFieldMatch(n.val, key) - if findex == -1 { - return nil, ErrNotFound - } - inner := n.val.Field(findex) - if inner.Kind() == reflect.Interface { - inner = inner.Elem() - } - return NewNode(inner.Interface(), model.SourceDefault) -} - -// ChildrenKeys returns the list of keys of the children of the given node, if it is a map -func (n *structNodeImpl) ChildrenKeys() ([]string, error) { - structType := n.val.Type() - keys := make([]string, 0, n.val.NumField()) - for i := 0; i < structType.NumField(); i++ { - f := structType.Field(i) - ch, _ := utf8.DecodeRuneInString(f.Name) - if unicode.IsLower(ch) { - continue - } - fieldKey, _ := fieldNameToKey(f) - keys = append(keys, fieldKey) - } - return keys, nil -} - -type specifierSet map[string]struct{} - -// fieldNameToKey returns the lower-cased field name, for case insensitive comparisons, -// with struct tag rename applied, as well as the set of specifiers from struct tags -// struct tags are handled in order of yaml, then json, then mapstructure -func fieldNameToKey(field reflect.StructField) (string, specifierSet) { - name := field.Name - - tagtext := "" - if val := field.Tag.Get("yaml"); val != "" { - tagtext = val - } else if val := field.Tag.Get("json"); val != "" { - tagtext = val - } else if val := field.Tag.Get("mapstructure"); val != "" { - tagtext = val - } - - // skip any additional specifiers such as ",omitempty" or ",squash" - // TODO: support multiple specifiers - var specifiers map[string]struct{} - if commaPos := strings.IndexRune(tagtext, ','); commaPos != -1 { - specifiers = make(map[string]struct{}) - val := tagtext[:commaPos] - specifiers[tagtext[commaPos+1:]] = struct{}{} - if val != "" { - name = val - } - } else if tagtext != "" { - name = tagtext - } - return strings.ToLower(name), specifiers -} - -func findFieldMatch(val reflect.Value, key string) int { - // case-insensitive match for struct names - key = strings.ToLower(key) - schema := val.Type() - for i := 0; i < schema.NumField(); i++ { - fieldKey, _ := fieldNameToKey(schema.Field(i)) - if key == fieldKey { - return i - } - } - return -1 -} diff --git a/pkg/config/nodetreemodel/reflection_node_test.go b/pkg/config/nodetreemodel/reflection_node_test.go index 6fa8746684d70..eb3a40392ff68 100644 --- a/pkg/config/nodetreemodel/reflection_node_test.go +++ b/pkg/config/nodetreemodel/reflection_node_test.go @@ -10,6 +10,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/config/model" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type Object struct { @@ -18,14 +19,16 @@ type Object struct { } func TestNewReflectionNode(t *testing.T) { - n, err := NewNode(Object{ + node, err := NewNode(Object{ Name: "test", Num: 7, }, model.SourceDefault) assert.NoError(t, err) - keys, err := n.ChildrenKeys() - assert.NoError(t, err) + n, ok := node.(InnerNode) + require.True(t, ok) + + keys := n.ChildrenKeys() assert.Equal(t, keys, []string{"name", "num"}) first, err := n.GetChild("name") diff --git a/pkg/config/nodetreemodel/struct_node.go b/pkg/config/nodetreemodel/struct_node.go new file mode 100644 index 0000000000000..1b9eea58961ef --- /dev/null +++ b/pkg/config/nodetreemodel/struct_node.go @@ -0,0 +1,179 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package nodetreemodel + +import ( + "fmt" + "reflect" + "strings" + "time" + "unicode" + "unicode/utf8" + + "github.com/DataDog/datadog-agent/pkg/config/model" +) + +type structNodeImpl struct { + // val must be a struct + val reflect.Value +} + +var _ Node = (*structNodeImpl)(nil) + +// GetChild returns the child node at the given case-insensitive key, or an error if not found +func (n *structNodeImpl) GetChild(key string) (Node, error) { + findex := findFieldMatch(n.val, key) + if findex == -1 { + return nil, ErrNotFound + } + inner := n.val.Field(findex) + if inner.Kind() == reflect.Interface { + inner = inner.Elem() + } + return NewNode(inner.Interface(), model.SourceDefault) +} + +func (n *structNodeImpl) HasChild(name string) bool { + names := n.ChildrenKeys() + for _, n := range names { + if n == name { + return true + } + } + return false +} + +func (n *structNodeImpl) Merge(InnerNode) error { + return fmt.Errorf("not implemented") +} + +// ChildrenKeys returns the list of keys of the children of the given node, if it is a map +func (n *structNodeImpl) ChildrenKeys() []string { + structType := n.val.Type() + keys := make([]string, 0, n.val.NumField()) + for i := 0; i < structType.NumField(); i++ { + f := structType.Field(i) + ch, _ := utf8.DecodeRuneInString(f.Name) + if unicode.IsLower(ch) { + continue + } + fieldKey, _ := fieldNameToKey(f) + keys = append(keys, fieldKey) + } + return keys +} + +// SetAt is not implemented for a leaf node +func (n *structNodeImpl) SetAt([]string, interface{}, model.Source) (bool, error) { + return false, fmt.Errorf("not implemented") +} + +// InsertChildNode is not implemented for a leaf node +func (n *structNodeImpl) InsertChildNode(string, Node) {} + +// makeRemapCase not implemented +func (n *structNodeImpl) makeRemapCase() {} + +// Clone clones a LeafNode +func (n *structNodeImpl) Clone() Node { + return &structNodeImpl{val: n.val} +} + +// SourceGreaterOrEqual returns true if the source of the current node is greater or equal to the one given as a +// parameter +func (n *structNodeImpl) SourceGreaterOrEqual(model.Source) bool { + return false +} + +func (n *structNodeImpl) GetAny() (interface{}, error) { + return nil, fmt.Errorf("not implemented") +} + +// GetBool returns the scalar as a bool, or an error otherwise +func (n *structNodeImpl) GetBool() (bool, error) { + return false, fmt.Errorf("not implemented") +} + +// GetInt returns the scalar as a int, or an error otherwise +func (n *structNodeImpl) GetInt() (int, error) { + return 0, fmt.Errorf("not implemented") +} + +// GetFloat returns the scalar as a float64, or an error otherwise +func (n *structNodeImpl) GetFloat() (float64, error) { + return 0, fmt.Errorf("not implemented") +} + +// GetString returns the scalar as a string, or an error otherwise +func (n *structNodeImpl) GetString() (string, error) { + return "", fmt.Errorf("not implemented") +} + +// GetTime returns the scalar as a time, or an error otherwise, not implemented +func (n *structNodeImpl) GetTime() (time.Time, error) { + return time.Time{}, fmt.Errorf("not implemented") +} + +// GetDuration returns the scalar as a duration, or an error otherwise, not implemented +func (n *structNodeImpl) GetDuration() (time.Duration, error) { + return time.Duration(0), fmt.Errorf("not implemented") +} + +// SetWithSource assigns a value in the config, for the given source +func (n *structNodeImpl) SetWithSource(interface{}, model.Source) error { + return fmt.Errorf("not implemented") +} + +// Source returns the source for this leaf +func (n *structNodeImpl) Source() model.Source { + return model.SourceUnknown +} + +type specifierSet map[string]struct{} + +// fieldNameToKey returns the lower-cased field name, for case insensitive comparisons, +// with struct tag rename applied, as well as the set of specifiers from struct tags +// struct tags are handled in order of yaml, then json, then mapstructure +func fieldNameToKey(field reflect.StructField) (string, specifierSet) { + name := field.Name + + tagtext := "" + if val := field.Tag.Get("yaml"); val != "" { + tagtext = val + } else if val := field.Tag.Get("json"); val != "" { + tagtext = val + } else if val := field.Tag.Get("mapstructure"); val != "" { + tagtext = val + } + + // skip any additional specifiers such as ",omitempty" or ",squash" + // TODO: support multiple specifiers + var specifiers map[string]struct{} + if commaPos := strings.IndexRune(tagtext, ','); commaPos != -1 { + specifiers = make(map[string]struct{}) + val := tagtext[:commaPos] + specifiers[tagtext[commaPos+1:]] = struct{}{} + if val != "" { + name = val + } + } else if tagtext != "" { + name = tagtext + } + return strings.ToLower(name), specifiers +} + +func findFieldMatch(val reflect.Value, key string) int { + // case-insensitive match for struct names + key = strings.ToLower(key) + schema := val.Type() + for i := 0; i < schema.NumField(); i++ { + fieldKey, _ := fieldNameToKey(schema.Field(i)) + if key == fieldKey { + return i + } + } + return -1 +} diff --git a/pkg/config/settings/runtime_setting_profiling.go b/pkg/config/settings/runtime_setting_profiling.go index 6086640275352..9ec310a64d660 100644 --- a/pkg/config/settings/runtime_setting_profiling.go +++ b/pkg/config/settings/runtime_setting_profiling.go @@ -85,10 +85,9 @@ func (l *ProfilingRuntimeSetting) Set(config config.Component, v interface{}, so // Note that we must derive a new profiling.Settings on every // invocation, as many of these settings may have changed at runtime. - v, _ := version.Agent() tags := config.GetStringSlice(l.ConfigPrefix + "internal_profiling.extra_tags") - tags = append(tags, fmt.Sprintf("version:%v", v)) + tags = append(tags, fmt.Sprintf("version:%v", version.AgentVersion)) settings := profiling.Settings{ ProfilingURL: site, diff --git a/pkg/config/setup/apm.go b/pkg/config/setup/apm.go index 251af766fc0af..370bdcae39ff9 100644 --- a/pkg/config/setup/apm.go +++ b/pkg/config/setup/apm.go @@ -77,9 +77,9 @@ func setupAPM(config pkgconfigmodel.Setup) { config.BindEnvAndSetDefault("apm_config.windows_pipe_buffer_size", 1_000_000, "DD_APM_WINDOWS_PIPE_BUFFER_SIZE") //nolint:errcheck config.BindEnvAndSetDefault("apm_config.windows_pipe_security_descriptor", "D:AI(A;;GA;;;WD)", "DD_APM_WINDOWS_PIPE_SECURITY_DESCRIPTOR") //nolint:errcheck config.BindEnvAndSetDefault("apm_config.remote_tagger", true, "DD_APM_REMOTE_TAGGER") //nolint:errcheck - config.BindEnvAndSetDefault("apm_config.peer_service_aggregation", false, "DD_APM_PEER_SERVICE_AGGREGATION") //nolint:errcheck - config.BindEnvAndSetDefault("apm_config.peer_tags_aggregation", false, "DD_APM_PEER_TAGS_AGGREGATION") //nolint:errcheck - config.BindEnvAndSetDefault("apm_config.compute_stats_by_span_kind", false, "DD_APM_COMPUTE_STATS_BY_SPAN_KIND") //nolint:errcheck + config.BindEnvAndSetDefault("apm_config.peer_service_aggregation", true, "DD_APM_PEER_SERVICE_AGGREGATION") //nolint:errcheck + config.BindEnvAndSetDefault("apm_config.peer_tags_aggregation", true, "DD_APM_PEER_TAGS_AGGREGATION") //nolint:errcheck + config.BindEnvAndSetDefault("apm_config.compute_stats_by_span_kind", true, "DD_APM_COMPUTE_STATS_BY_SPAN_KIND") //nolint:errcheck config.BindEnvAndSetDefault("apm_config.instrumentation.enabled", false, "DD_APM_INSTRUMENTATION_ENABLED") config.BindEnvAndSetDefault("apm_config.instrumentation.enabled_namespaces", []string{}, "DD_APM_INSTRUMENTATION_ENABLED_NAMESPACES") config.BindEnvAndSetDefault("apm_config.instrumentation.disabled_namespaces", []string{}, "DD_APM_INSTRUMENTATION_DISABLED_NAMESPACES") diff --git a/pkg/config/setup/config.go b/pkg/config/setup/config.go index bbc05125f08a7..af4d9a95ef993 100644 --- a/pkg/config/setup/config.go +++ b/pkg/config/setup/config.go @@ -244,14 +244,16 @@ func init() { osinit() // Configure Datadog global configuration - envvar, found := os.LookupEnv("DD_CONF_NODETREEMODEL") + envvar := os.Getenv("DD_CONF_NODETREEMODEL") // Possible values for DD_CONF_NODETREEMODEL: - // - "enable": Use the nodetreemodel for the config, instead of viper - // - "tee": Construct both viper and nodetreemodel. Write to both, only read from viper - // - other: Use viper for the config - if found && envvar == "enable" { + // - "enable": Use the nodetreemodel for the config, instead of viper + // - "tee": Construct both viper and nodetreemodel. Write to both, only read from viper + // - "unmarshal": Use viper for the config but the reflection based version of UnmarshalKey which used some of + // nodetreemodel internals + // - other: Use viper for the config + if envvar == "enable" { datadog = nodetreemodel.NewConfig("datadog", "DD", strings.NewReplacer(".", "_")) // nolint: forbidigo // legit use case - } else if found && envvar == "tee" { + } else if envvar == "tee" { var viperConfig = pkgconfigmodel.NewConfig("datadog", "DD", strings.NewReplacer(".", "_")) // nolint: forbidigo // legit use case var nodetreeConfig = nodetreemodel.NewConfig("datadog", "DD", strings.NewReplacer(".", "_")) // nolint: forbidigo // legit use case datadog = teeconfig.NewTeeConfig(viperConfig, nodetreeConfig) @@ -263,6 +265,7 @@ func init() { // Configuration defaults initConfig() + datadog.BuildSchema() } // initCommonWithServerless initializes configs that are common to all agents, in particular serverless. @@ -469,6 +472,8 @@ func InitConfig(config pkgconfigmodel.Setup) { config.BindEnvAndSetDefault("network_path.collector.pathtest_ttl", "15m") config.BindEnvAndSetDefault("network_path.collector.pathtest_interval", "5m") config.BindEnvAndSetDefault("network_path.collector.flush_interval", "10s") + config.BindEnvAndSetDefault("network_path.collector.reverse_dns_enrichment.enabled", true) + config.BindEnvAndSetDefault("network_path.collector.reverse_dns_enrichment.timeout", 5000) bindEnvAndSetLogsConfigKeys(config, "network_path.forwarder.") // Kube ApiServer @@ -560,6 +565,7 @@ func InitConfig(config pkgconfigmodel.Setup) { config.BindEnvAndSetDefault("collect_ec2_tags", false) config.BindEnvAndSetDefault("collect_ec2_tags_use_imds", false) config.BindEnvAndSetDefault("exclude_ec2_tags", []string{}) + config.BindEnvAndSetDefault("ec2_imdsv2_transition_payload_enabled", false) // ECS config.BindEnvAndSetDefault("ecs_agent_url", "") // Will be autodetected @@ -672,6 +678,8 @@ func InitConfig(config pkgconfigmodel.Setup) { // Autoscaling product config.BindEnvAndSetDefault("autoscaling.workload.enabled", false) + config.BindEnvAndSetDefault("autoscaling.failover.enabled", false) + config.BindEnv("autoscaling.failover.metrics") config.BindEnvAndSetDefault("hpa_watcher_polling_freq", 10) config.BindEnvAndSetDefault("hpa_watcher_gc_period", 60*5) // 5 minutes diff --git a/pkg/config/setup/config_test.go b/pkg/config/setup/config_test.go index 35116152a322b..058eb7d7b107a 100644 --- a/pkg/config/setup/config_test.go +++ b/pkg/config/setup/config_test.go @@ -673,6 +673,8 @@ func TestNetworkPathDefaults(t *testing.T) { assert.Equal(t, 15*time.Minute, config.GetDuration("network_path.collector.pathtest_ttl")) assert.Equal(t, 5*time.Minute, config.GetDuration("network_path.collector.pathtest_interval")) assert.Equal(t, 10*time.Second, config.GetDuration("network_path.collector.flush_interval")) + assert.Equal(t, true, config.GetBool("network_path.collector.reverse_dns_enrichment.enabled")) + assert.Equal(t, 5000, config.GetInt("network_path.collector.reverse_dns_enrichment.timeout")) } func TestUsePodmanLogsAndDockerPathOverride(t *testing.T) { @@ -929,21 +931,31 @@ func TestEnablePeerServiceStatsAggregationEnv(t *testing.T) { } func TestEnablePeerTagsAggregationEnv(t *testing.T) { - t.Setenv("DD_APM_PEER_TAGS_AGGREGATION", "true") testConfig := newTestConf() require.True(t, testConfig.GetBool("apm_config.peer_tags_aggregation")) + + t.Setenv("DD_APM_PEER_TAGS_AGGREGATION", "true") + testConfig = newTestConf() + require.True(t, testConfig.GetBool("apm_config.peer_tags_aggregation")) + t.Setenv("DD_APM_PEER_TAGS_AGGREGATION", "false") testConfig = newTestConf() require.False(t, testConfig.GetBool("apm_config.peer_tags_aggregation")) } func TestEnableStatsComputationBySpanKindYAML(t *testing.T) { - datadogYaml := ` + datadogYaml := "" + testConfig := confFromYAML(t, datadogYaml) + err := setupFipsEndpoints(testConfig) + require.NoError(t, err) + require.True(t, testConfig.GetBool("apm_config.compute_stats_by_span_kind")) + + datadogYaml = ` apm_config: compute_stats_by_span_kind: false ` - testConfig := confFromYAML(t, datadogYaml) - err := setupFipsEndpoints(testConfig) + testConfig = confFromYAML(t, datadogYaml) + err = setupFipsEndpoints(testConfig) require.NoError(t, err) require.False(t, testConfig.GetBool("apm_config.compute_stats_by_span_kind")) @@ -958,9 +970,13 @@ apm_config: } func TestComputeStatsBySpanKindEnv(t *testing.T) { - t.Setenv("DD_APM_COMPUTE_STATS_BY_SPAN_KIND", "false") testConfig := newTestConf() + require.True(t, testConfig.GetBool("apm_config.compute_stats_by_span_kind")) + + t.Setenv("DD_APM_COMPUTE_STATS_BY_SPAN_KIND", "false") + testConfig = newTestConf() require.False(t, testConfig.GetBool("apm_config.compute_stats_by_span_kind")) + t.Setenv("DD_APM_COMPUTE_STATS_BY_SPAN_KIND", "true") testConfig = newTestConf() require.True(t, testConfig.GetBool("apm_config.compute_stats_by_span_kind")) diff --git a/pkg/config/setup/system_probe.go b/pkg/config/setup/system_probe.go index d5f283c8899a5..9414bcda99cf1 100644 --- a/pkg/config/setup/system_probe.go +++ b/pkg/config/setup/system_probe.go @@ -155,7 +155,9 @@ func InitSystemProbeConfig(cfg pkgconfigmodel.Config) { cfg.BindEnvAndSetDefault(join(spNS, "enable_co_re"), true, "DD_ENABLE_CO_RE") cfg.BindEnvAndSetDefault(join(spNS, "btf_path"), "", "DD_SYSTEM_PROBE_BTF_PATH") cfg.BindEnv(join(spNS, "enable_runtime_compiler"), "DD_ENABLE_RUNTIME_COMPILER") - cfg.BindEnvAndSetDefault(join(spNS, "allow_precompiled_fallback"), true, "DD_ALLOW_PRECOMPILED_FALLBACK") + // deprecated in favor of allow_prebuilt_fallback below + cfg.BindEnv(join(spNS, "allow_precompiled_fallback"), "DD_ALLOW_PRECOMPILED_FALLBACK") + cfg.BindEnv(join(spNS, "allow_prebuilt_fallback"), "DD_ALLOW_PREBUILT_FALLBACK") cfg.BindEnvAndSetDefault(join(spNS, "allow_runtime_compiled_fallback"), true, "DD_ALLOW_RUNTIME_COMPILED_FALLBACK") cfg.BindEnvAndSetDefault(join(spNS, "runtime_compiler_output_dir"), defaultRuntimeCompilerOutputDir, "DD_RUNTIME_COMPILER_OUTPUT_DIR") cfg.BindEnv(join(spNS, "enable_kernel_header_download"), "DD_ENABLE_KERNEL_HEADER_DOWNLOAD") @@ -403,6 +405,7 @@ func InitSystemProbeConfig(cfg pkgconfigmodel.Config) { // Discovery config cfg.BindEnvAndSetDefault(join(discoveryNS, "enabled"), false) cfg.BindEnvAndSetDefault(join(discoveryNS, "cpu_usage_update_delay"), "60s") + cfg.BindEnvAndSetDefault(join(discoveryNS, "ignored_command_names"), []string{"chronyd", "cilium-agent", "containerd", "dhclient", "dockerd", "kubelet", "livenessprobe", "local-volume-pr", "sshd", "systemd"}) // Fleet policies cfg.BindEnv("fleet_policies_dir") diff --git a/pkg/config/setup/system_probe_cws.go b/pkg/config/setup/system_probe_cws.go index 4e9c952809cb3..8ae5f0a9734a9 100644 --- a/pkg/config/setup/system_probe_cws.go +++ b/pkg/config/setup/system_probe_cws.go @@ -40,6 +40,7 @@ func initCWSSystemProbeConfig(cfg pkgconfigmodel.Config) { cfg.BindEnvAndSetDefault("runtime_security_config.compliance_module.enabled", false) cfg.BindEnvAndSetDefault("runtime_security_config.on_demand.enabled", false) cfg.BindEnvAndSetDefault("runtime_security_config.on_demand.rate_limiter.enabled", true) + cfg.BindEnvAndSetDefault("runtime_security_config.reduced_proc_pid_cache_size", false) cfg.SetDefault("runtime_security_config.windows_filename_cache_max", 16384) cfg.SetDefault("runtime_security_config.windows_registry_cache_max", 4096) diff --git a/pkg/config/structure/unmarshal.go b/pkg/config/structure/unmarshal.go index 2f5596ecddea5..460ed9b973bc6 100644 --- a/pkg/config/structure/unmarshal.go +++ b/pkg/config/structure/unmarshal.go @@ -8,6 +8,7 @@ package structure import ( "fmt" + "os" "reflect" "strings" "unicode" @@ -38,10 +39,21 @@ var ConvertEmptyStringToNil UnmarshalKeyOption = func(fs *featureSet) { } // UnmarshalKey retrieves data from the config at the given key and deserializes it -// to be stored on the target struct. It is implemented entirely using reflection, and -// does not depend upon details of the data model of the config. -// Target struct can use of struct tag of "yaml", "json", or "mapstructure" to rename fields +// to be stored on the target struct. +// +// When DD_CONF_NODETREEMODEL is enabled we use the implementation using reflection, and do not depend upon details of +// the data model of the config. Target struct can use of struct tag of "yaml", "json", or "mapstructure" to rename fields +// +// Else the viper/legacy version is used. func UnmarshalKey(cfg model.Reader, key string, target interface{}, opts ...UnmarshalKeyOption) error { + nodetreemodel := os.Getenv("DD_CONF_NODETREEMODEL") + if nodetreemodel == "enabled" || nodetreemodel == "unmarshal" { + return unmarshalKeyReflection(cfg, key, target, opts...) + } + return cfg.UnmarshalKey(key, target) +} + +func unmarshalKeyReflection(cfg model.Reader, key string, target interface{}, opts ...UnmarshalKeyOption) error { fs := &featureSet{} for _, o := range opts { o(fs) @@ -154,12 +166,12 @@ func copyMap(target reflect.Value, source nodetreemodel.Node, _ *featureSet) err mtype := reflect.MapOf(ktype, vtype) results := reflect.MakeMap(mtype) - mapKeys, err := source.ChildrenKeys() - if err != nil { - return err + inner, ok := source.(nodetreemodel.InnerNode) + if !ok { + return fmt.Errorf("can't copy a map into a leaf") } - for _, mkey := range mapKeys { - child, err := source.GetChild(mkey) + for _, mkey := range inner.ChildrenKeys() { + child, err := inner.GetChild(mkey) if err != nil { return err } diff --git a/pkg/config/structure/unmarshal_test.go b/pkg/config/structure/unmarshal_test.go index 35b1da29c3532..255638d0d4ecf 100644 --- a/pkg/config/structure/unmarshal_test.go +++ b/pkg/config/structure/unmarshal_test.go @@ -63,7 +63,7 @@ network_devices: mockConfig := mock.NewFromYAML(t, confYaml) var trapsCfg = trapsConfig{} - err := UnmarshalKey(mockConfig, "network_devices.snmp_traps", &trapsCfg) + err := unmarshalKeyReflection(mockConfig, "network_devices.snmp_traps", &trapsCfg) assert.NoError(t, err) assert.Equal(t, trapsCfg.Enabled, true) @@ -136,7 +136,7 @@ endpoints: mockConfig.SetKnown("endpoints") var endpoints = []endpoint{} - err := UnmarshalKey(mockConfig, "endpoints", &endpoints) + err := unmarshalKeyReflection(mockConfig, "endpoints", &endpoints) assert.NoError(t, err, "%s failed to marshal: %s", tc.name, err) assert.Equal(t, len(endpoints), len(tc.want), "%s marshalled unexepected length of slices, wanted: %s got: %s", tc.name, len(tc.want), len(endpoints)) @@ -306,7 +306,7 @@ feature: mockConfig.SetKnown("feature") var feature = featureConfig{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", tc.name, err) assert.Equal(t, feature.Enabled, tc.want, "%s unexpected marshal value, want: %s got: %s", tc.name, tc.want, feature.Enabled) @@ -468,7 +468,7 @@ feature: mockConfig.SetKnown("feature") var feature = uintConfig{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", tc.name, err) if err != nil { t.FailNow() @@ -575,7 +575,7 @@ feature: mockConfig.SetKnown("feature") var feature = floatConfig{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", tc.name, err) if err != nil { t.FailNow() @@ -727,7 +727,7 @@ feature: mockConfig.SetKnown("feature") var feature = stringConfig{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", tc.name, err) if err != nil { t.FailNow() @@ -759,13 +759,13 @@ feature: mockConfig.SetKnown("feature") var feature = featureConfig{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err) assert.Equal(t, feature.Enabled, true) var diffcase = featureConfigDiffCase{} - err = UnmarshalKey(mockConfig, "feature", &diffcase) + err = unmarshalKeyReflection(mockConfig, "feature", &diffcase) assert.NoError(t, err) assert.Equal(t, diffcase.ENaBLEd, true) @@ -782,7 +782,7 @@ feature: // If the data from the config is missing, UnmarshalKey is a no-op, does // nothing, and returns no error var endpoints = []endpoint{} - err := UnmarshalKey(mockConfig, "config_providers", &endpoints) + err := unmarshalKeyReflection(mockConfig, "config_providers", &endpoints) assert.NoError(t, err) } @@ -800,7 +800,7 @@ feature: Enabled int }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "could not convert to int") }) @@ -818,7 +818,7 @@ feature: Enabled float64 }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "could not convert to float") }) @@ -836,7 +836,7 @@ feature: Enabled bool }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "could not convert to bool") }) @@ -854,7 +854,7 @@ feature: Enabled bool }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "could not convert to bool") }) @@ -872,7 +872,7 @@ feature: Enabled bool }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "could not convert to bool") }) @@ -891,7 +891,7 @@ feature: Enabled uint }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "could not convert to uint") }) @@ -909,7 +909,7 @@ feature: Enabled int }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "could not convert to int") }) @@ -927,7 +927,7 @@ feature: Enabled float64 }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "could not convert to float") }) @@ -945,7 +945,7 @@ feature: Enabled string }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "could not convert to string") }) @@ -964,7 +964,7 @@ feature: Enabled string }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "can't copy into target: scalar required") }) @@ -980,7 +980,7 @@ feature: feature := make(map[string]bool) - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "only map[string]string supported currently") }) @@ -1008,7 +1008,7 @@ feature: Enabled string `json:"enabled,omitempty"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", "json omitempty flag", err) assert.Equal(t, feature.Enabled, want, "unexpected marshal value, want: %s got: %s", want, feature.Enabled) @@ -1019,7 +1019,7 @@ feature: Enabled string `yaml:"enabled,omitempty"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", "yaml omitempty flag", err) assert.Equal(t, feature.Enabled, want, "unexpected marshal value, want: %s got: %s", want, feature.Enabled) @@ -1030,7 +1030,7 @@ feature: Enabled string `yaml:"enabled,flow"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", "yaml flow flag", err) assert.Equal(t, feature.Enabled, want, "unexpected marshal value, want: %s got: %s", want, feature.Enabled) @@ -1041,7 +1041,7 @@ feature: Enabled string `yaml:"enabled,inline"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", "yaml inline flag", err) assert.Equal(t, feature.Enabled, want, "unexpected marshal value, want: %s got: %s", want, feature.Enabled) @@ -1052,7 +1052,7 @@ feature: Enabled string `yaml:"enabled,inline,flow"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", "yaml multiple flags", err) assert.Equal(t, feature.Enabled, want, "unexpected marshal value, want: %s got: %s", want, feature.Enabled) @@ -1063,7 +1063,7 @@ feature: Enabled string `mapstructure:"enabled,remain"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", "mapstructure omitempty flag", err) assert.Equal(t, feature.Enabled, want, "unexpected marshal value, want: %s got: %s", want, feature.Enabled) @@ -1074,7 +1074,7 @@ feature: Enabled string `mapstructure:"enabled,squash"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "EnableSquash") }) @@ -1084,7 +1084,7 @@ feature: Enabled string `mapstructure:"enabled,omitempty"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", "mapstructure omitempty flag", err) assert.Equal(t, feature.Enabled, want, "unexpected marshal value, want: %s got: %s", want, feature.Enabled) @@ -1095,7 +1095,7 @@ feature: Enabled string `mapstructure:"enabled,remain,omitempty"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.NoError(t, err, "%s failed to marshal: %s", "mapstructure multiple flags", err) assert.Equal(t, feature.Enabled, want, "unexpected marshal value, want: %s got: %s", want, feature.Enabled) @@ -1108,7 +1108,7 @@ feature: Enabled string `mapstructure:"enabled,remain,squash"` }{} - err := UnmarshalKey(mockConfig, "feature", &feature) + err := unmarshalKeyReflection(mockConfig, "feature", &feature) assert.Error(t, err) assert.Contains(t, err.Error(), "EnableSquash") }) @@ -1229,7 +1229,7 @@ service: var svc = squashConfig{} t.Run("squash flag succeeds with option", func(t *testing.T) { - err := UnmarshalKey(mockConfig, "service", &svc, EnableSquash) + err := unmarshalKeyReflection(mockConfig, "service", &svc, EnableSquash) assert.NoError(t, err) assert.Equal(t, svc.Host, "datad0g.com") @@ -1250,7 +1250,7 @@ service: mockConfig.SetKnown("service") var svc = make(map[string]string) - err := UnmarshalKey(mockConfig, "service", &svc) + err := unmarshalKeyReflection(mockConfig, "service", &svc) assert.NoError(t, err) assert.Equal(t, svc["host"], "datad0g.com") @@ -1274,7 +1274,7 @@ func TestMapGetChildNotFound(t *testing.T) { assert.Error(t, err) assert.Equal(t, err.Error(), "not found") - keys, err := n.ChildrenKeys() - assert.NoError(t, err) - assert.Equal(t, keys, []string{"a", "b"}) + inner, ok := n.(nodetreemodel.InnerNode) + assert.True(t, ok) + assert.Equal(t, inner.ChildrenKeys(), []string{"a", "b"}) } diff --git a/pkg/config/teeconfig/teeconfig.go b/pkg/config/teeconfig/teeconfig.go index ed490fd127fe5..6e87ba391ac14 100644 --- a/pkg/config/teeconfig/teeconfig.go +++ b/pkg/config/teeconfig/teeconfig.go @@ -77,6 +77,12 @@ func (t *teeConfig) GetKnownKeysLowercased() map[string]interface{} { return t.baseline.GetKnownKeysLowercased() } +// BuildSchema constructs the default schema and marks the config as ready for use +func (t *teeConfig) BuildSchema() { + t.baseline.BuildSchema() + t.compare.BuildSchema() +} + // ParseEnvAsStringSlice registers a transformer function to parse an an environment variables as a []string. func (t *teeConfig) ParseEnvAsStringSlice(key string, fn func(string) []string) { t.baseline.ParseEnvAsStringSlice(key, fn) diff --git a/pkg/config/utils/clusteragent.go b/pkg/config/utils/clusteragent.go new file mode 100644 index 0000000000000..3f7e09bab8890 --- /dev/null +++ b/pkg/config/utils/clusteragent.go @@ -0,0 +1,82 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package utils + +import ( + "fmt" + "net/url" + "os" + "strings" + + pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" + "github.com/DataDog/datadog-agent/pkg/util/log" +) + +// GetClusterAgentEndpoint provides a validated https endpoint from configuration keys in datadog.yaml: +// 1st. configuration key "cluster_agent.url" (or the DD_CLUSTER_AGENT_URL environment variable), +// +// add the https prefix if the scheme isn't specified +// +// 2nd. environment variables associated with "cluster_agent.kubernetes_service_name" +// +// ${dcaServiceName}_SERVICE_HOST and ${dcaServiceName}_SERVICE_PORT +func GetClusterAgentEndpoint() (string, error) { + const configDcaURL = "cluster_agent.url" + const configDcaSvcName = "cluster_agent.kubernetes_service_name" + + dcaURL := pkgconfigsetup.Datadog().GetString(configDcaURL) + if dcaURL != "" { + if strings.HasPrefix(dcaURL, "http://") { + return "", fmt.Errorf("cannot get cluster agent endpoint, not a https scheme: %s", dcaURL) + } + if !strings.Contains(dcaURL, "://") { + log.Tracef("Adding https scheme to %s: https://%s", dcaURL, dcaURL) + dcaURL = fmt.Sprintf("https://%s", dcaURL) + } + u, err := url.Parse(dcaURL) + if err != nil { + return "", err + } + if u.Scheme != "https" { + return "", fmt.Errorf("cannot get cluster agent endpoint, not a https scheme: %s", u.Scheme) + } + log.Debugf("Connecting to the configured URL for the Datadog Cluster Agent: %s", dcaURL) + return u.String(), nil + } + + // Construct the URL with the Kubernetes service environment variables + // *_SERVICE_HOST and *_SERVICE_PORT + dcaSvc := pkgconfigsetup.Datadog().GetString(configDcaSvcName) + log.Debugf("Identified service for the Datadog Cluster Agent: %s", dcaSvc) + if dcaSvc == "" { + return "", fmt.Errorf("cannot get a cluster agent endpoint, both %s and %s are empty", configDcaURL, configDcaSvcName) + } + + dcaSvc = strings.ToUpper(dcaSvc) + dcaSvc = strings.Replace(dcaSvc, "-", "_", -1) // Kubernetes replaces "-" with "_" in the service names injected in the env var. + + // host + dcaSvcHostEnv := fmt.Sprintf("%s_SERVICE_HOST", dcaSvc) + dcaSvcHost := os.Getenv(dcaSvcHostEnv) + if dcaSvcHost == "" { + return "", fmt.Errorf("cannot get a cluster agent endpoint for kubernetes service %s, env %s is empty", dcaSvc, dcaSvcHostEnv) + } + + // port + dcaSvcPort := os.Getenv(fmt.Sprintf("%s_SERVICE_PORT", dcaSvc)) + if dcaSvcPort == "" { + return "", fmt.Errorf("cannot get a cluster agent endpoint for kubernetes service %s, env %s is empty", dcaSvc, dcaSvcPort) + } + + // validate the URL + dcaURL = fmt.Sprintf("https://%s:%s", dcaSvcHost, dcaSvcPort) + u, err := url.Parse(dcaURL) + if err != nil { + return "", err + } + + return u.String(), nil +} diff --git a/pkg/config/utils/clusteragent_test.go b/pkg/config/utils/clusteragent_test.go new file mode 100644 index 0000000000000..7012285eae103 --- /dev/null +++ b/pkg/config/utils/clusteragent_test.go @@ -0,0 +1,92 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package utils + +import ( + "fmt" + "testing" + + configmock "github.com/DataDog/datadog-agent/pkg/config/mock" + pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const ( + clusterAgentServiceName = "DATADOG_CLUSTER_AGENT" + clusterAgentServiceHost = clusterAgentServiceName + "_SERVICE_HOST" + clusterAgentServicePort = clusterAgentServiceName + "_SERVICE_PORT" +) + +func TestGetClusterAgentEndpointEmpty(t *testing.T) { + configmock.New(t) + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.url", "") + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.kubernetes_service_name", "") + _, err := GetClusterAgentEndpoint() + require.NotNil(t, err) +} + +func TestGetClusterAgentEndpointFromUrl(t *testing.T) { + configmock.New(t) + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.url", "https://127.0.0.1:8080") + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.kubernetes_service_name", "") + _, err := GetClusterAgentEndpoint() + require.Nil(t, err, fmt.Sprintf("%v", err)) + + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.url", "https://127.0.0.1") + _, err = GetClusterAgentEndpoint() + require.Nil(t, err, fmt.Sprintf("%v", err)) + + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.url", "127.0.0.1") + endpoint, err := GetClusterAgentEndpoint() + require.Nil(t, err, fmt.Sprintf("%v", err)) + assert.Equal(t, "https://127.0.0.1", endpoint) + + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.url", "127.0.0.1:1234") + endpoint, err = GetClusterAgentEndpoint() + require.Nil(t, err, fmt.Sprintf("%v", err)) + assert.Equal(t, "https://127.0.0.1:1234", endpoint) +} + +func TestGetClusterAgentEndpointFromUrlInvalid(t *testing.T) { + configmock.New(t) + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.url", "http://127.0.0.1:8080") + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.kubernetes_service_name", "") + _, err := GetClusterAgentEndpoint() + require.NotNil(t, err) + + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.url", "tcp://127.0.0.1:8080") + _, err = GetClusterAgentEndpoint() + require.NotNil(t, err) +} + +func TestGetClusterAgentEndpointFromKubernetesSvc(t *testing.T) { + configmock.New(t) + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.url", "") + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.kubernetes_service_name", "datadog-cluster-agent") + t.Setenv(clusterAgentServiceHost, "127.0.0.1") + t.Setenv(clusterAgentServicePort, "443") + + endpoint, err := GetClusterAgentEndpoint() + require.Nil(t, err, fmt.Sprintf("%v", err)) + assert.Equal(t, "https://127.0.0.1:443", endpoint) +} + +func TestGetClusterAgentEndpointFromKubernetesSvcEmpty(t *testing.T) { + configmock.New(t) + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.url", "") + pkgconfigsetup.Datadog().SetWithoutSource("cluster_agent.kubernetes_service_name", "datadog-cluster-agent") + t.Setenv(clusterAgentServiceHost, "127.0.0.1") + t.Setenv(clusterAgentServicePort, "") + + _, err := GetClusterAgentEndpoint() + require.NotNil(t, err, fmt.Sprintf("%v", err)) + + t.Setenv(clusterAgentServiceHost, "") + t.Setenv(clusterAgentServicePort, "443") + _, err = GetClusterAgentEndpoint() + require.NotNil(t, err, fmt.Sprintf("%v", err)) +} diff --git a/pkg/diagnose/check.go b/pkg/diagnose/check.go index 17f2e0d016b17..a807e8fde6eeb 100644 --- a/pkg/diagnose/check.go +++ b/pkg/diagnose/check.go @@ -15,6 +15,7 @@ import ( "github.com/DataDog/datadog-agent/comp/collector/collector" "github.com/DataDog/datadog-agent/comp/core/autodiscovery" "github.com/DataDog/datadog-agent/comp/core/secrets" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" pkgcollector "github.com/DataDog/datadog-agent/pkg/collector" @@ -73,7 +74,7 @@ func diagnoseChecksInAgentProcess(collector collector.Component) []diagnosis.Dia return diagnoses } -func diagnoseChecksInCLIProcess(_ diagnosis.Config, senderManager diagnosesendermanager.Component, _ integrations.Component, secretResolver secrets.Component, wmeta optional.Option[workloadmeta.Component], ac autodiscovery.Component) []diagnosis.Diagnosis { +func diagnoseChecksInCLIProcess(_ diagnosis.Config, senderManager diagnosesendermanager.Component, _ integrations.Component, secretResolver secrets.Component, wmeta optional.Option[workloadmeta.Component], ac autodiscovery.Component, tagger tagger.Component) []diagnosis.Diagnosis { // other choices // run() github.com\DataDog\datadog-agent\pkg\cli\subcommands\check\command.go // runCheck() github.com\DataDog\datadog-agent\cmd\agent\gui\checks.go @@ -109,7 +110,7 @@ func diagnoseChecksInCLIProcess(_ diagnosis.Config, senderManager diagnosesender // Create the CheckScheduler, but do not attach it to // AutoDiscovery. - pkgcollector.InitCheckScheduler(optional.NewNoneOption[collector.Component](), senderManagerInstance, optional.NewNoneOption[integrations.Component]()) + pkgcollector.InitCheckScheduler(optional.NewNoneOption[collector.Component](), senderManagerInstance, optional.NewNoneOption[integrations.Component](), tagger) // Load matching configurations (should we use common.AC.GetAllConfigs()) waitCtx, cancelTimeout := context.WithTimeout(context.Background(), time.Duration(5*time.Second)) diff --git a/pkg/diagnose/runner.go b/pkg/diagnose/runner.go index 281860310689a..cf19e468ebd27 100644 --- a/pkg/diagnose/runner.go +++ b/pkg/diagnose/runner.go @@ -18,6 +18,7 @@ import ( "github.com/DataDog/datadog-agent/comp/collector/collector" "github.com/DataDog/datadog-agent/comp/core/autodiscovery" "github.com/DataDog/datadog-agent/comp/core/secrets" + "github.com/DataDog/datadog-agent/comp/core/tagger" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/comp/forwarder/eventplatform/eventplatformimpl" integrations "github.com/DataDog/datadog-agent/comp/logs/integrations/def" @@ -316,7 +317,7 @@ func requestDiagnosesFromAgentProcess(diagCfg diagnosis.Config) (*diagnosis.Diag func RunInCLIProcess(diagCfg diagnosis.Config, deps SuitesDepsInCLIProcess) (*diagnosis.DiagnoseResult, error) { return RunDiagnose(diagCfg, func() []diagnosis.Suite { return buildSuites(diagCfg, func() []diagnosis.Diagnosis { - return diagnoseChecksInCLIProcess(diagCfg, deps.senderManager, deps.logReceiver, deps.secretResolver, deps.wmeta, deps.AC) + return diagnoseChecksInCLIProcess(diagCfg, deps.senderManager, deps.logReceiver, deps.secretResolver, deps.wmeta, deps.AC, deps.tagger) }) }) } @@ -409,7 +410,8 @@ type SuitesDeps struct { Collector optional.Option[collector.Component] SecretResolver secrets.Component WMeta optional.Option[workloadmeta.Component] - AC optional.Option[autodiscovery.Component] + AC autodiscovery.Component + Tagger tagger.Component } // SuitesDepsInCLIProcess stores the dependencies for the diagnose suites when running the CLI Process. @@ -419,6 +421,7 @@ type SuitesDepsInCLIProcess struct { wmeta optional.Option[workloadmeta.Component] AC autodiscovery.Component logReceiver integrations.Component + tagger tagger.Component } // NewSuitesDepsInCLIProcess returns a new instance of SuitesDepsInCLIProcess. @@ -427,12 +430,14 @@ func NewSuitesDepsInCLIProcess( secretResolver secrets.Component, wmeta optional.Option[workloadmeta.Component], ac autodiscovery.Component, + tagger tagger.Component, ) SuitesDepsInCLIProcess { return SuitesDepsInCLIProcess{ senderManager: senderManager, secretResolver: secretResolver, wmeta: wmeta, AC: ac, + tagger: tagger, } } @@ -458,7 +463,8 @@ func NewSuitesDeps( senderManager sender.DiagnoseSenderManager, collector optional.Option[collector.Component], secretResolver secrets.Component, - wmeta optional.Option[workloadmeta.Component], ac optional.Option[autodiscovery.Component], + wmeta optional.Option[workloadmeta.Component], ac autodiscovery.Component, + tagger tagger.Component, ) SuitesDeps { return SuitesDeps{ SenderManager: senderManager, @@ -466,6 +472,7 @@ func NewSuitesDeps( SecretResolver: secretResolver, WMeta: wmeta, AC: ac, + Tagger: tagger, } } diff --git a/pkg/ebpf/btf.go b/pkg/ebpf/btf.go index 0173cd5d91d3a..94bd67cfbb7f9 100644 --- a/pkg/ebpf/btf.go +++ b/pkg/ebpf/btf.go @@ -94,11 +94,34 @@ type returnBTF struct { moduleLoadFunc kernelModuleBTFLoadFunc } +type BTFResultMetadata struct { + // numLoadAttempts is how many times the loader has been invoked (doesn't include cached requests) + numLoadAttempts int + // loaderUsed the name of the loader that was used to get the BTF data + loaderUsed string + // filepathUsed is the filepath it last tried to load BTF files from (only for loadUser and loadEmbedded) + filepathUsed string + // tarballUsed is the filepath for the tarball it tried to extract BTF from (only for loadEmbedded) + tarballUsed string +} + +func (d BTFResultMetadata) String() string { + res := fmt.Sprintf("numLoadAttempts: %d\nloaderUsed: %s", d.numLoadAttempts, d.loaderUsed) + if d.filepathUsed != "" { + res += fmt.Sprintf("\nfilepathUsed: %s", d.filepathUsed) + } + if d.tarballUsed != "" { + res += fmt.Sprintf("\ntarballUsed: %s", d.tarballUsed) + } + return res +} + type orderedBTFLoader struct { userBTFPath string embeddedDir string result ebpftelemetry.BTFResult + resultMetadata BTFResultMetadata loadFunc funcs.CachedFunc[returnBTF] delayedFlusher *time.Timer } @@ -132,6 +155,8 @@ func (b *orderedBTFLoader) Flush() { } func (b *orderedBTFLoader) get() (*returnBTF, error) { + b.resultMetadata.numLoadAttempts++ + loaders := []struct { result ebpftelemetry.BTFResult loader btfLoaderFunc @@ -157,6 +182,7 @@ func (b *orderedBTFLoader) get() (*returnBTF, error) { if ret != nil { log.Debugf("successfully loaded BTF from %s", l.desc) b.result = l.result + b.resultMetadata.loaderUsed = l.desc return ret, nil } } @@ -168,7 +194,11 @@ func (b *orderedBTFLoader) loadKernel() (*returnBTF, error) { if err != nil { return nil, err } - return &returnBTF{vmlinux: spec, moduleLoadFunc: nil}, nil + b.resultMetadata.filepathUsed = "" + return &returnBTF{ + vmlinux: spec, + moduleLoadFunc: nil, + }, nil } func (b *orderedBTFLoader) loadUser() (*returnBTF, error) { @@ -179,7 +209,11 @@ func (b *orderedBTFLoader) loadUser() (*returnBTF, error) { if err != nil { return nil, err } - return &returnBTF{vmlinux: spec, moduleLoadFunc: nil}, nil + b.resultMetadata.filepathUsed = b.userBTFPath + return &returnBTF{ + vmlinux: spec, + moduleLoadFunc: nil, + }, nil } func (b *orderedBTFLoader) checkForMinimizedBTF(extractDir string) (*returnBTF, error) { @@ -191,8 +225,11 @@ func (b *orderedBTFLoader) checkForMinimizedBTF(extractDir string) (*returnBTF, if err != nil { return nil, err } - // no module load function for minimized single file BTF - return &returnBTF{vmlinux: spec, moduleLoadFunc: nil}, nil + b.resultMetadata.filepathUsed = extractedBtfPath + return &returnBTF{ + vmlinux: spec, + moduleLoadFunc: nil, + }, nil } return nil, nil } @@ -210,7 +247,11 @@ func (b *orderedBTFLoader) checkForUnminimizedBTF(extractDir string) (*returnBTF if err != nil { return nil, err } - return &returnBTF{vmlinux: spec, moduleLoadFunc: modLoadFunc}, nil + b.resultMetadata.filepathUsed = extractedBtfPath + return &returnBTF{ + vmlinux: spec, + moduleLoadFunc: modLoadFunc, + }, nil } return nil, nil } @@ -252,6 +293,7 @@ func (b *orderedBTFLoader) loadEmbedded() (*returnBTF, error) { // This means that we'll need to first extract the specific BTF which we're looking for from the collection // tarball, and then unarchive it. btfTarball := filepath.Join(b.embeddedDir, btfRelativeTarballFilename) + b.resultMetadata.tarballUsed = btfTarball if _, err := os.Stat(btfTarball); errors.Is(err, fs.ErrNotExist) { collectionTarball := filepath.Join(b.embeddedDir, btfArchiveName) if err := archive.TarXZExtractFile(collectionTarball, btfRelativeTarballFilename, b.embeddedDir); err != nil { diff --git a/pkg/ebpf/co_re.go b/pkg/ebpf/co_re.go index 9742aaf7e149a..34f13e5c4ef4d 100644 --- a/pkg/ebpf/co_re.go +++ b/pkg/ebpf/co_re.go @@ -42,6 +42,18 @@ func LoadCOREAsset(filename string, startFn func(bytecode.AssetReader, manager.O return loader.loadCOREAsset(filename, startFn) } +// GetBTFLoaderInfo Returns where the ebpf BTF files were sourced from +func GetBTFLoaderInfo() (string, error) { + loader, err := coreLoader(NewConfig()) + if err != nil { + return "", err + } + + metadataStr := loader.btfLoader.resultMetadata.String() + infoStr := fmt.Sprintf("btfLoader result: %d\n%s", loader.btfLoader.result, metadataStr) + return infoStr, nil +} + func (c *coreAssetLoader) loadCOREAsset(filename string, startFn func(bytecode.AssetReader, manager.Options) error) error { var result ebpftelemetry.COREResult base := strings.TrimSuffix(filename, path.Ext(filename)) diff --git a/pkg/ebpf/co_re_unsupported.go b/pkg/ebpf/co_re_unsupported.go new file mode 100644 index 0000000000000..9e5cc6f7ad538 --- /dev/null +++ b/pkg/ebpf/co_re_unsupported.go @@ -0,0 +1,15 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024-present Datadog, Inc. + +//go:build !linux_bpf + +package ebpf + +import "errors" + +// GetBTFLoaderInfo is not supported without linux_bpf +func GetBTFLoaderInfo() (string, error) { + return "", errors.New("BTF is not supported") +} diff --git a/pkg/ebpf/config.go b/pkg/ebpf/config.go index 1f27d5ff7525a..85b6f63f14616 100644 --- a/pkg/ebpf/config.go +++ b/pkg/ebpf/config.go @@ -65,8 +65,8 @@ type Config struct { // ZypperReposDir is the path to the zypper repository directory ZypperReposDir string - // AllowPrecompiledFallback indicates whether we are allowed to fallback to the prebuilt probes if runtime compilation fails. - AllowPrecompiledFallback bool + // AllowPrebuiltFallback indicates whether we are allowed to fallback to the prebuilt probes if runtime compilation fails. + AllowPrebuiltFallback bool // AllowRuntimeCompiledFallback indicates whether we are allowed to fallback to runtime compilation if CO-RE fails. AllowRuntimeCompiledFallback bool @@ -103,7 +103,7 @@ func NewConfig() *Config { AptConfigDir: cfg.GetString(sysconfig.FullKeyPath(spNS, "apt_config_dir")), YumReposDir: cfg.GetString(sysconfig.FullKeyPath(spNS, "yum_repos_dir")), ZypperReposDir: cfg.GetString(sysconfig.FullKeyPath(spNS, "zypper_repos_dir")), - AllowPrecompiledFallback: cfg.GetBool(sysconfig.FullKeyPath(spNS, "allow_precompiled_fallback")), + AllowPrebuiltFallback: cfg.GetBool(sysconfig.FullKeyPath(spNS, "allow_prebuilt_fallback")), AllowRuntimeCompiledFallback: cfg.GetBool(sysconfig.FullKeyPath(spNS, "allow_runtime_compiled_fallback")), AttachKprobesWithKprobeEventsABI: cfg.GetBool(sysconfig.FullKeyPath(spNS, "attach_kprobes_with_kprobe_events_abi")), diff --git a/pkg/ebpf/debug_handlers.go b/pkg/ebpf/debug_handlers.go new file mode 100644 index 0000000000000..ea10d22a844c2 --- /dev/null +++ b/pkg/ebpf/debug_handlers.go @@ -0,0 +1,26 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024-present Datadog, Inc. + +package ebpf + +import ( + "io" + "net/http" + + "github.com/DataDog/datadog-agent/pkg/util/log" +) + +// HandleBTFLoaderInfo responds with where the system-probe found BTF data (and +// if it was in a pre-bundled tarball, where within that tarball it came from) +func HandleBTFLoaderInfo(w http.ResponseWriter, _ *http.Request) { + info, err := GetBTFLoaderInfo() + if err != nil { + log.Errorf("unable to get ebpf_btf_loader info: %s", err) + w.WriteHeader(500) + return + } + + io.WriteString(w, info) +} diff --git a/pkg/ebpf/ebpftest/buildmode.go b/pkg/ebpf/ebpftest/buildmode.go index 76e774f68cbbb..4b8a6f9e4766f 100644 --- a/pkg/ebpf/ebpftest/buildmode.go +++ b/pkg/ebpf/ebpftest/buildmode.go @@ -20,7 +20,7 @@ var ( ) func init() { - Prebuilt = prebuilt{} + Prebuilt = prebuiltMode{} RuntimeCompiled = runtimeCompiled{} CORE = core{} Fentry = fentry{} @@ -33,19 +33,19 @@ type BuildMode interface { Env() map[string]string } -type prebuilt struct{} +type prebuiltMode struct{} -func (p prebuilt) String() string { +func (p prebuiltMode) String() string { return "prebuilt" } -func (p prebuilt) Env() map[string]string { +func (p prebuiltMode) Env() map[string]string { return map[string]string{ "NETWORK_TRACER_FENTRY_TESTS": "false", "DD_ENABLE_RUNTIME_COMPILER": "false", "DD_ENABLE_CO_RE": "false", "DD_ALLOW_RUNTIME_COMPILED_FALLBACK": "false", - "DD_ALLOW_PRECOMPILED_FALLBACK": "false", + "DD_ALLOW_PREBUILT_FALLBACK": "false", } } @@ -61,7 +61,7 @@ func (r runtimeCompiled) Env() map[string]string { "DD_ENABLE_RUNTIME_COMPILER": "true", "DD_ENABLE_CO_RE": "false", "DD_ALLOW_RUNTIME_COMPILED_FALLBACK": "false", - "DD_ALLOW_PRECOMPILED_FALLBACK": "false", + "DD_ALLOW_PREBUILT_FALLBACK": "false", } } @@ -77,7 +77,7 @@ func (c core) Env() map[string]string { "DD_ENABLE_RUNTIME_COMPILER": "false", "DD_ENABLE_CO_RE": "true", "DD_ALLOW_RUNTIME_COMPILED_FALLBACK": "false", - "DD_ALLOW_PRECOMPILED_FALLBACK": "false", + "DD_ALLOW_PREBUILT_FALLBACK": "false", } } @@ -93,7 +93,7 @@ func (f fentry) Env() map[string]string { "DD_ENABLE_RUNTIME_COMPILER": "false", "DD_ENABLE_CO_RE": "true", "DD_ALLOW_RUNTIME_COMPILED_FALLBACK": "false", - "DD_ALLOW_PRECOMPILED_FALLBACK": "false", + "DD_ALLOW_PREBUILT_FALLBACK": "false", } } @@ -109,7 +109,7 @@ func (e ebpfless) Env() map[string]string { "DD_ENABLE_RUNTIME_COMPILER": "false", "DD_ENABLE_CO_RE": "false", "DD_ALLOW_RUNTIME_COMPILED_FALLBACK": "false", - "DD_ALLOW_PRECOMPILED_FALLBACK": "false", + "DD_ALLOW_PREBUILT_FALLBACK": "false", "DD_NETWORK_CONFIG_ENABLE_EBPFLESS": "true", } } diff --git a/pkg/ebpf/ebpftest/buildmode_linux.go b/pkg/ebpf/ebpftest/buildmode_linux.go index 0e88f0f528271..61c24edccfbd6 100644 --- a/pkg/ebpf/ebpftest/buildmode_linux.go +++ b/pkg/ebpf/ebpftest/buildmode_linux.go @@ -12,6 +12,7 @@ import ( "github.com/cilium/ebpf/rlimit" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" "github.com/DataDog/datadog-agent/pkg/util/funcs" "github.com/DataDog/datadog-agent/pkg/util/kernel" ) @@ -25,7 +26,10 @@ func init() { // SupportedBuildModes returns the build modes supported on the current host func SupportedBuildModes() []BuildMode { - modes := []BuildMode{Prebuilt, RuntimeCompiled, CORE} + modes := []BuildMode{RuntimeCompiled, CORE} + if !prebuilt.IsDeprecated() || os.Getenv("TEST_PREBUILT_OVERRIDE") == "true" { + modes = append(modes, Prebuilt) + } if os.Getenv("TEST_FENTRY_OVERRIDE") == "true" || (runtime.GOARCH == "amd64" && (hostPlatform == "amazon" || hostPlatform == "amzn") && kv.Major() == 5 && kv.Minor() == 10) { modes = append(modes, Fentry) diff --git a/pkg/ebpf/ebpftest/buildmode_test.go b/pkg/ebpf/ebpftest/buildmode_test.go index 4af61080ebff5..54e0255dd844d 100644 --- a/pkg/ebpf/ebpftest/buildmode_test.go +++ b/pkg/ebpf/ebpftest/buildmode_test.go @@ -21,7 +21,7 @@ func TestBuildModeConstants(t *testing.T) { cfg := ebpf.NewConfig() assert.False(t, cfg.EnableRuntimeCompiler) assert.False(t, cfg.EnableCORE) - assert.False(t, cfg.AllowPrecompiledFallback) + assert.False(t, cfg.AllowPrebuiltFallback) assert.False(t, cfg.AllowRuntimeCompiledFallback) assert.Equal(t, "false", os.Getenv("NETWORK_TRACER_FENTRY_TESTS")) }) @@ -29,7 +29,7 @@ func TestBuildModeConstants(t *testing.T) { cfg := ebpf.NewConfig() assert.True(t, cfg.EnableRuntimeCompiler) assert.False(t, cfg.EnableCORE) - assert.False(t, cfg.AllowPrecompiledFallback) + assert.False(t, cfg.AllowPrebuiltFallback) assert.False(t, cfg.AllowRuntimeCompiledFallback) assert.Equal(t, "false", os.Getenv("NETWORK_TRACER_FENTRY_TESTS")) }) @@ -37,7 +37,7 @@ func TestBuildModeConstants(t *testing.T) { cfg := ebpf.NewConfig() assert.False(t, cfg.EnableRuntimeCompiler) assert.True(t, cfg.EnableCORE) - assert.False(t, cfg.AllowPrecompiledFallback) + assert.False(t, cfg.AllowPrebuiltFallback) assert.False(t, cfg.AllowRuntimeCompiledFallback) assert.Equal(t, "false", os.Getenv("NETWORK_TRACER_FENTRY_TESTS")) }) @@ -45,7 +45,7 @@ func TestBuildModeConstants(t *testing.T) { cfg := ebpf.NewConfig() assert.False(t, cfg.EnableRuntimeCompiler) assert.True(t, cfg.EnableCORE) - assert.False(t, cfg.AllowPrecompiledFallback) + assert.False(t, cfg.AllowPrebuiltFallback) assert.False(t, cfg.AllowRuntimeCompiledFallback) assert.Equal(t, "true", os.Getenv("NETWORK_TRACER_FENTRY_TESTS")) }) diff --git a/pkg/ebpf/prebuilt/deprecate.go b/pkg/ebpf/prebuilt/deprecate.go new file mode 100644 index 0000000000000..22cd060cc120a --- /dev/null +++ b/pkg/ebpf/prebuilt/deprecate.go @@ -0,0 +1,47 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024-present Datadog, Inc. + +//go:build linux + +// Package prebuilt implements prebuilt specific eBPF functionality +package prebuilt + +import ( + "github.com/DataDog/datadog-agent/pkg/util/kernel" + "github.com/DataDog/datadog-agent/pkg/util/log" +) + +var ( + // DeprecatedKernelVersionRhel is the kernel version + // where prebuilt eBPF is deprecated on RHEL based kernels + DeprecatedKernelVersionRhel = kernel.VersionCode(5, 14, 0) + // DeprecatedKernelVersion is the kernel version + // where prebuilt eBPF is deprecated on non-RHEL based kernels + DeprecatedKernelVersion = kernel.VersionCode(6, 0, 0) +) + +// IsDeprecated returns true if prebuilt ebpf is deprecated +// on this host +func IsDeprecated() bool { + // has to be kernel 6+ or RHEL 9+ (kernel 5.14+) + family, err := kernel.Family() + if err != nil { + log.Warnf("could not determine OS family: %s", err) + return false + } + + // check kernel version + kv, err := kernel.HostVersion() + if err != nil { + log.Warnf("could not determine kernel version: %s", err) + return false + } + + if family == "rhel" { + return kv >= DeprecatedKernelVersionRhel + } + + return kv >= DeprecatedKernelVersion +} diff --git a/pkg/ebpf/prebuilt/deprecate_other.go b/pkg/ebpf/prebuilt/deprecate_other.go new file mode 100644 index 0000000000000..7ef7b4946d499 --- /dev/null +++ b/pkg/ebpf/prebuilt/deprecate_other.go @@ -0,0 +1,15 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024-present Datadog, Inc. + +//go:build !linux + +// Package prebuilt implements prebuilt specific eBPF functionality +package prebuilt + +// IsDeprecated returns true if prebuilt ebpf is deprecated +// on this host +func IsDeprecated() bool { + return false +} diff --git a/pkg/ebpf/uprobes/attacher.go b/pkg/ebpf/uprobes/attacher.go index de71ff62a00a6..0ddf21859c1ec 100644 --- a/pkg/ebpf/uprobes/attacher.go +++ b/pkg/ebpf/uprobes/attacher.go @@ -27,7 +27,6 @@ import ( "github.com/DataDog/datadog-agent/pkg/network/go/bininspect" "github.com/DataDog/datadog-agent/pkg/network/usm/sharedlibraries" "github.com/DataDog/datadog-agent/pkg/network/usm/utils" - "github.com/DataDog/datadog-agent/pkg/process/monitor" "github.com/DataDog/datadog-agent/pkg/util/kernel" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -155,6 +154,19 @@ func (r *AttachRule) Validate() error { return result } +// ProcessMonitor is an interface that allows subscribing to process start and exit events +type ProcessMonitor interface { + // SubscribeExec subscribes to process start events, with a callback that + // receives the PID of the process. Returns a function that can be called to + // unsubscribe from the event. + SubscribeExec(func(uint32)) func() + + // SubscribeExit subscribes to process exit events, with a callback that + // receives the PID of the process. Returns a function that can be called to + // unsubscribe from the event. + SubscribeExit(func(uint32)) func() +} + // AttacherConfig defines the configuration for the attacher type AttacherConfig struct { // Rules defines a series of rules that tell the attacher how to attach the probes @@ -307,19 +319,24 @@ type UprobeAttacher struct { // handlesExecutablesCached is a cache for the handlesExecutables function, avoiding // recomputation every time handlesExecutablesCached *bool -} -// NewUprobeAttacher creates a new UprobeAttacher. Receives as arguments the -// name of the attacher, the configuration, the probe manager (ebpf.Manager -// usually), a callback to be called whenever a probe is attached (optional, can -// be nil), and the binary inspector to be used (e.g., while we usually want -// NativeBinaryInspector here, we might want the GoBinaryInspector to attach to -// Go functions in a different way). -// Note that the config is copied, not referenced. The attacher caches some values -// that depend on the configuration, so any changes to the configuration after the -// attacher would make those caches incoherent. This way we ensure that the attacher -// is always consistent with the configuration it was created with. -func NewUprobeAttacher(name string, config AttacherConfig, mgr ProbeManager, onAttachCallback AttachCallback, inspector BinaryInspector) (*UprobeAttacher, error) { + // processMonitor is the process monitor that we use to subscribe to process start and exit events + processMonitor ProcessMonitor +} + +// NewUprobeAttacher creates a new UprobeAttacher. Receives as arguments +// - The name of the attacher +// - The configuration. Note that the config is copied, not referenced. The attacher caches some values +// that depend on the configuration, so any changes to the configuration after the +// attacher would make those caches incoherent. This way we ensure that the attacher is always consistent with the configuration it was created with. +// - The eBPF probe manager (ebpf.Manager usually) +// - A callback to be called whenever a probe is attached (optional, can be nil) +// - The binary inspector to be used (e.g., while we usually want NativeBinaryInspector here, +// we might want the GoBinaryInspector to attach to Go functions in a different +// way). +// - The process monitor to be used to subscribe to process start and exit events. The lifecycle of the process monitor is managed by the caller, the attacher +// will not stop the monitor when it stops. +func NewUprobeAttacher(name string, config AttacherConfig, mgr ProbeManager, onAttachCallback AttachCallback, inspector BinaryInspector, processMonitor ProcessMonitor) (*UprobeAttacher, error) { config.SetDefaults() if err := config.Validate(); err != nil { @@ -335,6 +352,7 @@ func NewUprobeAttacher(name string, config AttacherConfig, mgr ProbeManager, onA pathToAttachedProbes: make(map[string][]manager.ProbeIdentificationPair), done: make(chan struct{}), inspector: inspector, + processMonitor: processMonitor, } utils.AddAttacher(name, ua) @@ -381,12 +399,11 @@ func (ua *UprobeAttacher) handlesExecutables() bool { // Start starts the attacher, attaching to the processes and libraries as needed func (ua *UprobeAttacher) Start() error { var cleanupExec, cleanupExit func() - procMonitor := monitor.GetProcessMonitor() if ua.handlesExecutables() { - cleanupExec = procMonitor.SubscribeExec(ua.handleProcessStart) + cleanupExec = ua.processMonitor.SubscribeExec(ua.handleProcessStart) } // We always want to track process deletions, to avoid memory leaks - cleanupExit = procMonitor.SubscribeExit(ua.handleProcessExit) + cleanupExit = ua.processMonitor.SubscribeExit(ua.handleProcessExit) if ua.handlesLibraries() { if !sharedlibraries.IsSupported(ua.config.EbpfConfig) { @@ -424,7 +441,6 @@ func (ua *UprobeAttacher) Start() error { cleanupExec() } cleanupExit() - procMonitor.Stop() ua.fileRegistry.Clear() if ua.soWatcher != nil { ua.soWatcher.Stop() diff --git a/pkg/ebpf/uprobes/attacher_test.go b/pkg/ebpf/uprobes/attacher_test.go index 4297686e0c47b..73b290eba8443 100644 --- a/pkg/ebpf/uprobes/attacher_test.go +++ b/pkg/ebpf/uprobes/attacher_test.go @@ -25,6 +25,7 @@ import ( ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/ebpf/bytecode" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" eventmonitortestutil "github.com/DataDog/datadog-agent/pkg/eventmonitor/testutil" "github.com/DataDog/datadog-agent/pkg/network/go/bininspect" "github.com/DataDog/datadog-agent/pkg/network/usm/sharedlibraries" @@ -38,7 +39,7 @@ import ( // === Tests func TestCanCreateAttacher(t *testing.T) { - ua, err := NewUprobeAttacher("mock", AttacherConfig{}, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", AttacherConfig{}, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) } @@ -50,7 +51,7 @@ func TestAttachPidExcludesInternal(t *testing.T) { ExcludeTargets: ExcludeInternal, ProcRoot: procRoot, } - ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) @@ -62,7 +63,7 @@ func TestAttachPidExcludesSelf(t *testing.T) { config := AttacherConfig{ ExcludeTargets: ExcludeSelf, } - ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) @@ -76,7 +77,7 @@ func TestGetExecutablePath(t *testing.T) { config := AttacherConfig{ ProcRoot: procRoot, } - ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) @@ -119,7 +120,7 @@ func TestGetLibrariesFromMapsFile(t *testing.T) { config := AttacherConfig{ ProcRoot: procRoot, } - ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) @@ -131,7 +132,7 @@ func TestGetLibrariesFromMapsFile(t *testing.T) { } func TestComputeRequestedSymbols(t *testing.T) { - ua, err := NewUprobeAttacher("mock", AttacherConfig{}, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", AttacherConfig{}, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) @@ -203,7 +204,7 @@ func TestComputeRequestedSymbols(t *testing.T) { } func TestStartAndStopWithoutLibraryWatcher(t *testing.T) { - ua, err := NewUprobeAttacher("mock", AttacherConfig{}, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", AttacherConfig{}, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) @@ -222,7 +223,7 @@ func TestStartAndStopWithLibraryWatcher(t *testing.T) { } rules := []*AttachRule{{LibraryNameRegex: regexp.MustCompile(`libssl.so`), Targets: AttachToSharedLibraries}} - ua, err := NewUprobeAttacher("mock", AttacherConfig{Rules: rules, EbpfConfig: ebpfCfg}, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", AttacherConfig{Rules: rules, EbpfConfig: ebpfCfg}, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) require.True(t, ua.handlesLibraries()) @@ -273,7 +274,7 @@ func TestMonitor(t *testing.T) { return } - launchProcessMonitor(t, false) + procMon := launchProcessMonitor(t, false) config := AttacherConfig{ Rules: []*AttachRule{{ @@ -282,7 +283,7 @@ func TestMonitor(t *testing.T) { }}, EbpfConfig: ebpfCfg, } - ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil, procMon) require.NoError(t, err) require.NotNil(t, ua) @@ -332,7 +333,7 @@ func TestSync(t *testing.T) { EnablePeriodicScanNewProcesses: true, } - ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(tt, err) require.NotNil(tt, ua) @@ -364,7 +365,7 @@ func TestSync(t *testing.T) { EnablePeriodicScanNewProcesses: true, } - ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("mock", config, &MockManager{}, nil, nil, newMockProcessMonitor()) require.NoError(tt, err) require.NotNil(tt, ua) @@ -440,7 +441,7 @@ func TestAttachToBinaryAndDetach(t *testing.T) { mockMan := &MockManager{} inspector := &MockBinaryInspector{} - ua, err := NewUprobeAttacher("mock", config, mockMan, nil, inspector) + ua, err := NewUprobeAttacher("mock", config, mockMan, nil, inspector, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) @@ -501,7 +502,7 @@ func TestAttachToBinaryAtReturnLocation(t *testing.T) { mockMan := &MockManager{} inspector := &MockBinaryInspector{} - ua, err := NewUprobeAttacher("mock", config, mockMan, nil, inspector) + ua, err := NewUprobeAttacher("mock", config, mockMan, nil, inspector, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) @@ -582,7 +583,7 @@ func TestAttachToLibrariesOfPid(t *testing.T) { mockMan := &MockManager{} inspector := &MockBinaryInspector{} registry := &MockFileRegistry{} - ua, err := NewUprobeAttacher("mock", config, mockMan, nil, inspector) + ua, err := NewUprobeAttacher("mock", config, mockMan, nil, inspector, newMockProcessMonitor()) require.NoError(t, err) require.NotNil(t, ua) ua.fileRegistry = registry @@ -655,7 +656,7 @@ func TestUprobeAttacher(t *testing.T) { return } - launchProcessMonitor(t, false) + procMon := launchProcessMonitor(t, false) buf, err := bytecode.GetReader(ebpfCfg.BPFDir, "uprobe_attacher-test.o") require.NoError(t, err) @@ -699,7 +700,7 @@ func TestUprobeAttacher(t *testing.T) { attachedProbes = append(attachedProbes, attachedProbe{probe: probe, fpath: fpath}) } - ua, err := NewUprobeAttacher("test", attacherCfg, &mgr, callback, &NativeBinaryInspector{}) + ua, err := NewUprobeAttacher("test", attacherCfg, &mgr, callback, &NativeBinaryInspector{}, procMon) require.NoError(t, err) require.NotNil(t, ua) @@ -736,13 +737,15 @@ func TestUprobeAttacher(t *testing.T) { require.Equal(t, uint32(cmd.Process.Pid), mainProbe.fpath.PID) } -func launchProcessMonitor(t *testing.T, useEventStream bool) { +func launchProcessMonitor(t *testing.T, useEventStream bool) *monitor.ProcessMonitor { pm := monitor.GetProcessMonitor() t.Cleanup(pm.Stop) require.NoError(t, pm.Initialize(useEventStream)) if useEventStream { eventmonitortestutil.StartEventMonitor(t, procmontestutil.RegisterProcessMonitorEventConsumer) } + + return pm } func createTempTestFile(t *testing.T, name string) (string, utils.PathIdentifier) { @@ -764,22 +767,27 @@ func createTempTestFile(t *testing.T, name string) (string, utils.PathIdentifier type SharedLibrarySuite struct { suite.Suite + procMonitor ProcessMonitor } func TestAttacherSharedLibrary(t *testing.T) { - ebpftest.TestBuildModes(t, []ebpftest.BuildMode{ebpftest.Prebuilt, ebpftest.RuntimeCompiled, ebpftest.CORE}, "", func(tt *testing.T) { + modes := []ebpftest.BuildMode{ebpftest.RuntimeCompiled, ebpftest.CORE} + if !prebuilt.IsDeprecated() { + modes = append(modes, ebpftest.Prebuilt) + } + ebpftest.TestBuildModes(t, modes, "", func(tt *testing.T) { if !sharedlibraries.IsSupported(ddebpf.NewConfig()) { tt.Skip("shared library tracing not supported for this platform") } tt.Run("netlink", func(ttt *testing.T) { - launchProcessMonitor(ttt, false) - suite.Run(ttt, new(SharedLibrarySuite)) + processMonitor := launchProcessMonitor(ttt, false) + suite.Run(ttt, &SharedLibrarySuite{procMonitor: processMonitor}) }) tt.Run("event stream", func(ttt *testing.T) { - launchProcessMonitor(ttt, true) - suite.Run(ttt, new(SharedLibrarySuite)) + processMonitor := launchProcessMonitor(ttt, true) + suite.Run(ttt, &SharedLibrarySuite{procMonitor: processMonitor}) }) }) } @@ -800,7 +808,7 @@ func (s *SharedLibrarySuite) TestSingleFile() { PerformInitialScan: false, } - ua, err := NewUprobeAttacher("test", attachCfg, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("test", attachCfg, &MockManager{}, nil, nil, s.procMonitor) require.NoError(t, err) mockRegistry := &MockFileRegistry{} @@ -877,7 +885,7 @@ func (s *SharedLibrarySuite) TestDetectionWithPIDAndRootNamespace() { EbpfConfig: ebpfCfg, } - ua, err := NewUprobeAttacher("test", attachCfg, &MockManager{}, nil, nil) + ua, err := NewUprobeAttacher("test", attachCfg, &MockManager{}, nil, nil, s.procMonitor) require.NoError(t, err) mockRegistry := &MockFileRegistry{} diff --git a/pkg/ebpf/uprobes/doc.go b/pkg/ebpf/uprobes/doc.go index 887d653ae8d82..d5abf8939180c 100644 --- a/pkg/ebpf/uprobes/doc.go +++ b/pkg/ebpf/uprobes/doc.go @@ -37,11 +37,11 @@ and which probes to attach to them. Example usage: EbpfConfig: ebpfCfg, } - ua, err := NewUprobeAttacher("test", attacherCfg, &mgr, callback, &NativeBinaryInspector{}) + ua, err := NewUprobeAttacher("test", attacherCfg, &mgr, callback, &NativeBinaryInspector{}, processMonitor) ua.Start() Once started, the attacher monitors new processes and `open` calls for new -shared libraries. For the first task it uses pkg/process/monitor/ProcessMonitor, +shared libraries. For the first task it uses the monitor provided as argument, and for the second it uses the shared-libraries program in pkg/network/usm/sharedlibraries. @@ -56,5 +56,9 @@ pkg/network/usm/sharedlibraries. the whole attach operation will be considered as failed, and the probes will be detached. If you want to control which probes are optional and which are mandatory, you can use the manager.AllOf/manager.BestEffort selectors in a single rule. + + - The recommended way to add a process monitor is using the event stream, creating a event consumer. There is also + monitor.GetProcessMonitor, but that monitor is intended for use in USM only and is not recommended for use in other + parts of the codebase, as it will be deprecated once netlink is not needed anymore. */ package uprobes diff --git a/pkg/ebpf/uprobes/procfs.go b/pkg/ebpf/uprobes/procfs.go index ff355e2fe9e1b..badc6f2f7e203 100644 --- a/pkg/ebpf/uprobes/procfs.go +++ b/pkg/ebpf/uprobes/procfs.go @@ -17,7 +17,9 @@ import ( "time" ) -const procFSUpdateTimeout = 100 * time.Millisecond +const numProcFSUpdateRetries = 10 +const procFSUpdateInterval = 1 * time.Millisecond +const procFSUpdateTimeout = numProcFSUpdateRetries * procFSUpdateInterval // ProcInfo holds the information extracted from procfs, to avoid repeat calls to the filesystem. type ProcInfo struct { @@ -50,7 +52,7 @@ func waitUntilSucceeds[T any](p *ProcInfo, procFile string, readFunc func(string for err != nil && end.After(time.Now()) { result, err = readFunc(filePath) if err != nil { - time.Sleep(10 * time.Millisecond) + time.Sleep(procFSUpdateInterval) } } diff --git a/pkg/ebpf/uprobes/testutil.go b/pkg/ebpf/uprobes/testutil.go index 0c91c4ef3912f..51e69e5597962 100644 --- a/pkg/ebpf/uprobes/testutil.go +++ b/pkg/ebpf/uprobes/testutil.go @@ -94,6 +94,29 @@ func (m *MockBinaryInspector) Cleanup(fpath utils.FilePath) { _ = m.Called(fpath) } +type mockProcessMonitor struct { + mock.Mock +} + +func (m *mockProcessMonitor) SubscribeExec(cb func(uint32)) func() { + args := m.Called(cb) + return args.Get(0).(func()) +} + +func (m *mockProcessMonitor) SubscribeExit(cb func(uint32)) func() { + args := m.Called(cb) + return args.Get(0).(func()) +} + +// Create a new mockProcessMonitor that accepts any callback and returns a no-op function +func newMockProcessMonitor() *mockProcessMonitor { + pm := &mockProcessMonitor{} + pm.On("SubscribeExec", mock.Anything).Return(func() {}) + pm.On("SubscribeExit", mock.Anything).Return(func() {}) + + return pm +} + // === Test utils // FakeProcFSEntry represents a fake /proc filesystem entry for testing purposes. diff --git a/pkg/eventmonitor/interface.go b/pkg/eventmonitor/consumer.go similarity index 64% rename from pkg/eventmonitor/interface.go rename to pkg/eventmonitor/consumer.go index c9de1e61ff3cf..11cbbf7ea42e5 100644 --- a/pkg/eventmonitor/interface.go +++ b/pkg/eventmonitor/consumer.go @@ -8,15 +8,16 @@ package eventmonitor import "github.com/DataDog/datadog-agent/pkg/security/probe" -// EventConsumer event consumer -type EventConsumer interface { - probe.EventConsumerInterface +// EventConsumerHandler provides an interface for event consumer handlers +type EventConsumerHandler interface { + probe.EventConsumerHandler } -// EventConsumerInterface defines an event consumer -type EventConsumerInterface interface { - // ID returns the ID of the event consumer - ID() string +// EventConsumer provides a state interface for any consumers of the event_monitor module. +// Each event consumer should also implement the EventConsumerHandler interface to handle the retrieved events +type EventConsumer interface { + // IDer implements the ID method to return unique ID of the event consumer + probe.IDer // Start starts the event consumer Start() error // Stop stops the event consumer diff --git a/pkg/eventmonitor/eventmonitor.go b/pkg/eventmonitor/eventmonitor.go index ce93880272057..e37ddebd55784 100644 --- a/pkg/eventmonitor/eventmonitor.go +++ b/pkg/eventmonitor/eventmonitor.go @@ -53,7 +53,7 @@ type EventMonitor struct { ctx context.Context cancelFnc context.CancelFunc sendStatsChan chan chan bool - eventConsumers []EventConsumerInterface + eventConsumers []EventConsumer wg sync.WaitGroup } @@ -68,8 +68,8 @@ func (m *EventMonitor) Register(_ *module.Router) error { return m.Start() } -// AddEventConsumer registers an event handler -func (m *EventMonitor) AddEventConsumer(consumer EventConsumer) error { +// AddEventConsumerHandler registers an event handler +func (m *EventMonitor) AddEventConsumerHandler(consumer EventConsumerHandler) error { for _, eventType := range consumer.EventTypes() { if !slices.Contains(allowedEventTypes, eventType) { return fmt.Errorf("event type (%s) not allowed", eventType) @@ -80,7 +80,7 @@ func (m *EventMonitor) AddEventConsumer(consumer EventConsumer) error { } // RegisterEventConsumer registers an event consumer -func (m *EventMonitor) RegisterEventConsumer(consumer EventConsumerInterface) { +func (m *EventMonitor) RegisterEventConsumer(consumer EventConsumer) { m.eventConsumers = append(m.eventConsumers, consumer) } diff --git a/pkg/eventmonitor/eventmonitor_other.go b/pkg/eventmonitor/eventmonitor_other.go index 83c1cd7bf7119..03935b82e18b6 100644 --- a/pkg/eventmonitor/eventmonitor_other.go +++ b/pkg/eventmonitor/eventmonitor_other.go @@ -26,7 +26,7 @@ type EventMonitor struct { Probe *probe.Probe } -// AddEventConsumer add a consumer -func (m *EventMonitor) AddEventConsumer(_ EventConsumer) error { +// AddEventConsumerHandler add a consumer +func (m *EventMonitor) AddEventConsumerHandler(_ EventConsumerHandler) error { return nil } diff --git a/pkg/eventmonitor/examples/consumer.go b/pkg/eventmonitor/examples/consumer.go index 62d5b8440d215..4c6e4b97de4d3 100644 --- a/pkg/eventmonitor/examples/consumer.go +++ b/pkg/eventmonitor/examples/consumer.go @@ -5,6 +5,7 @@ //go:generate go run github.com/DataDog/datadog-agent/pkg/security/generators/event_copy -scope "(fc *SimpleEventConsumer)" -pkg examples -output ./event_copy.go SimpleEvent . +// Package examples provides an example of how to use the event monitor module using a basic consumer package examples import ( @@ -35,7 +36,7 @@ type SimpleEventConsumer struct { // NewSimpleEventConsumer returns a new simple event consumer func NewSimpleEventConsumer(em *eventmonitor.EventMonitor) *SimpleEventConsumer { fc := &SimpleEventConsumer{} - _ = em.AddEventConsumer(fc) + _ = em.AddEventConsumerHandler(fc) return fc } diff --git a/pkg/flare/archive.go b/pkg/flare/archive.go index 0f279eab0cc5e..76f5d3d6bc000 100644 --- a/pkg/flare/archive.go +++ b/pkg/flare/archive.go @@ -152,6 +152,7 @@ func provideSystemProbe(fb flaretypes.FlareBuilder) error { fb.AddFileFromFunc(filepath.Join("system-probe", "system_probe_telemetry.log"), getSystemProbeTelemetry) // nolint:errcheck fb.AddFileFromFunc(filepath.Join("system-probe", "conntrack_cached.log"), getSystemProbeConntrackCached) // nolint:errcheck fb.AddFileFromFunc(filepath.Join("system-probe", "conntrack_host.log"), getSystemProbeConntrackHost) // nolint:errcheck + fb.AddFileFromFunc(filepath.Join("system-probe", "ebpf_btf_loader.log"), getSystemProbeBTFLoaderInfo) // nolint:errcheck } return nil } @@ -266,6 +267,9 @@ func getSystemProbeConntrackCached() ([]byte, error) { func getSystemProbeConntrackHost() ([]byte, error) { return sysprobe.GetSystemProbeConntrackHost(getSystemProbeSocketPath()) } +func getSystemProbeBTFLoaderInfo() ([]byte, error) { + return sysprobe.GetSystemProbeBTFLoaderInfo(getSystemProbeSocketPath()) +} // getProcessAgentFullConfig fetches process-agent runtime config as YAML and returns it to be added to process_agent_runtime_config_dump.yaml func getProcessAgentFullConfig() ([]byte, error) { @@ -364,23 +368,22 @@ func getDiagnoses(isFlareLocal bool, deps diagnose.SuitesDeps) func() ([]byte, e } return diagnose.RunDiagnoseStdOut(w, diagCfg, diagnoses) } - if ac, ok := deps.AC.Get(); ok { - diagnoseDeps := diagnose.NewSuitesDepsInCLIProcess(deps.SenderManager, deps.SecretResolver, deps.WMeta, ac) - diagnoses, err := diagnose.RunInCLIProcess(diagCfg, diagnoseDeps) - if err != nil && !diagCfg.RunLocal { - fmt.Fprintln(w, color.YellowString(fmt.Sprintf("Error running diagnose in Agent process: %s", err))) - fmt.Fprintln(w, "Running diagnose command locally (may take extra time to run checks locally) ...") - - diagCfg.RunLocal = true - diagnoses, err = diagnose.RunInCLIProcess(diagCfg, diagnoseDeps) - if err != nil { - fmt.Fprintln(w, color.RedString(fmt.Sprintf("Error running diagnose: %s", err))) - return err - } + + diagnoseDeps := diagnose.NewSuitesDepsInCLIProcess(deps.SenderManager, deps.SecretResolver, deps.WMeta, deps.AC, deps.Tagger) + diagnoses, err := diagnose.RunInCLIProcess(diagCfg, diagnoseDeps) + if err != nil && !diagCfg.RunLocal { + fmt.Fprintln(w, color.YellowString(fmt.Sprintf("Error running diagnose in Agent process: %s", err))) + fmt.Fprintln(w, "Running diagnose command locally (may take extra time to run checks locally) ...") + + diagCfg.RunLocal = true + diagnoses, err = diagnose.RunInCLIProcess(diagCfg, diagnoseDeps) + if err != nil { + fmt.Fprintln(w, color.RedString(fmt.Sprintf("Error running diagnose: %s", err))) + return err } - return diagnose.RunDiagnoseStdOut(w, diagCfg, diagnoses) } - return fmt.Errorf("collector or autoDiscovery not found") + return diagnose.RunDiagnoseStdOut(w, diagCfg, diagnoses) + } return func() ([]byte, error) { return functionOutputToBytes(fct), nil } diff --git a/pkg/flare/sysprobe/archive_linux.go b/pkg/flare/sysprobe/archive_linux.go index 72f33f11f253e..d6312d5cc62bf 100644 --- a/pkg/flare/sysprobe/archive_linux.go +++ b/pkg/flare/sysprobe/archive_linux.go @@ -27,3 +27,12 @@ func GetSystemProbeConntrackHost(socketPath string) ([]byte, error) { } return probeUtil.GetConnTrackHost() } + +// GetSystemProbeBTFLoaderInfo queries ebpf_btf_loader_info which gets where the BTF data came from +func GetSystemProbeBTFLoaderInfo(socketPath string) ([]byte, error) { + probeUtil, err := net.GetRemoteSystemProbeUtil(socketPath) + if err != nil { + return nil, err + } + return probeUtil.GetBTFLoaderInfo() +} diff --git a/pkg/flare/sysprobe/archive_nolinux.go b/pkg/flare/sysprobe/archive_nolinux.go index 3506c78e47ec2..c9c441ff7752f 100644 --- a/pkg/flare/sysprobe/archive_nolinux.go +++ b/pkg/flare/sysprobe/archive_nolinux.go @@ -9,12 +9,17 @@ package sysprobe import "errors" -// GetSystemProbeConntrackCached is not supported without the process agent on linux +// GetSystemProbeConntrackCached is a stub designed to prevent builds without the process agent from importing pkg/process/net func GetSystemProbeConntrackCached(_ string) ([]byte, error) { - return nil, errors.New("GetSystemProbeConntrackCached is not supported without the process agent on linux") + return nil, errors.New("GetSystemProbeConntrackCached is not supported") } -// GetSystemProbeConntrackHost is not supported without the process agent on linux +// GetSystemProbeConntrackHost is a stub designed to prevent builds without the process agent from importing pkg/process/net func GetSystemProbeConntrackHost(_ string) ([]byte, error) { - return nil, errors.New("GetSystemProbeConntrackHost is not supported without the process agent on linux") + return nil, errors.New("GetSystemProbeConntrackHost is not supported") +} + +// GetSystemProbeBTFLoaderInfo is a stub designed to prevent builds without the process agent from importing pkg/process/net +func GetSystemProbeBTFLoaderInfo(_ string) ([]byte, error) { + return nil, errors.New("GetSystemProbeBTFLoaderInfo is not supported") } diff --git a/pkg/gpu/config.go b/pkg/gpu/config/config.go similarity index 59% rename from pkg/gpu/config.go rename to pkg/gpu/config/config.go index d8beee7591dff..e9920e62a6e30 100644 --- a/pkg/gpu/config.go +++ b/pkg/gpu/config/config.go @@ -3,20 +3,50 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2024-present Datadog, Inc. -// Package gpu provides the GPU monitoring functionality. -package gpu +//go:build linux + +// Package config provides the GPU monitoring config. +package config import ( - sysconfig "github.com/DataDog/datadog-agent/cmd/system-probe/config" - pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" + "errors" + "fmt" "time" + sysconfig "github.com/DataDog/datadog-agent/cmd/system-probe/config" + pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/ebpf" + "github.com/DataDog/datadog-agent/pkg/util/kernel" ) // GPUNS is the namespace for the GPU monitoring probe. const GPUNS = "gpu_monitoring" +// ErrNotSupported is the error returned if GPU monitoring is not supported on this platform +var ErrNotSupported = errors.New("GPU Monitoring is not supported") + +// MinimumKernelVersion indicates the minimum kernel version required for GPU monitoring +var MinimumKernelVersion kernel.Version + +func init() { + // we rely on ring buffer support for GPU monitoring, hence the minimal kernel version is 5.8.0 + MinimumKernelVersion = kernel.VersionCode(5, 8, 0) +} + +// CheckGPUSupported checks if the host's kernel supports GPU monitoring +func CheckGPUSupported() error { + kversion, err := kernel.HostVersion() + if err != nil { + return fmt.Errorf("%w: could not determine the current kernel version: %w", ErrNotSupported, err) + } + + if kversion < MinimumKernelVersion { + return fmt.Errorf("%w: a Linux kernel version of %s or higher is required; we detected %s", ErrNotSupported, MinimumKernelVersion, kversion) + } + + return nil +} + // Config holds the configuration for the GPU monitoring probe. type Config struct { ebpf.Config diff --git a/pkg/gpu/consumer.go b/pkg/gpu/consumer.go index 3eb75daf01532..adb340c0aa06d 100644 --- a/pkg/gpu/consumer.go +++ b/pkg/gpu/consumer.go @@ -14,6 +14,7 @@ import ( "unsafe" ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" + "github.com/DataDog/datadog-agent/pkg/gpu/config" gpuebpf "github.com/DataDog/datadog-agent/pkg/gpu/ebpf" "github.com/DataDog/datadog-agent/pkg/process/monitor" "github.com/DataDog/datadog-agent/pkg/status/health" @@ -30,11 +31,11 @@ type cudaEventConsumer struct { streamHandlers map[streamKey]*StreamHandler wg sync.WaitGroup running atomic.Bool - cfg *Config + cfg *config.Config } // newCudaEventConsumer creates a new CUDA event consumer. -func newCudaEventConsumer(eventHandler ddebpf.EventHandler, cfg *Config) *cudaEventConsumer { +func newCudaEventConsumer(eventHandler ddebpf.EventHandler, cfg *config.Config) *cudaEventConsumer { return &cudaEventConsumer{ eventHandler: eventHandler, closed: make(chan struct{}), diff --git a/pkg/gpu/consumer_test.go b/pkg/gpu/consumer_test.go index 9051e22bfea12..3f98e9f72eff3 100644 --- a/pkg/gpu/consumer_test.go +++ b/pkg/gpu/consumer_test.go @@ -14,11 +14,12 @@ import ( "github.com/stretchr/testify/require" ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" + "github.com/DataDog/datadog-agent/pkg/gpu/config" ) func TestConsumerCanStartAndStop(t *testing.T) { handler := ddebpf.NewRingBufferHandler(consumerChannelSize) - cfg := NewConfig() + cfg := config.NewConfig() consumer := newCudaEventConsumer(handler, cfg) consumer.Start() diff --git a/pkg/gpu/context.go b/pkg/gpu/context.go index 74d46c53fa152..46926ff097ea5 100644 --- a/pkg/gpu/context.go +++ b/pkg/gpu/context.go @@ -33,7 +33,7 @@ func getSystemContext(nvmlLib nvml.Interface) (*systemContext, error) { nvmlLib: nvmlLib, } - if err := ctx.queryDevices(); err != nil { + if err := ctx.fillDeviceInfo(); err != nil { return nil, fmt.Errorf("error querying devices: %w", err) } @@ -46,20 +46,23 @@ func getSystemContext(nvmlLib nvml.Interface) (*systemContext, error) { return ctx, nil } -func (ctx *systemContext) queryDevices() error { - devices, err := getGPUDevices(ctx.nvmlLib) - if err != nil { - return fmt.Errorf("error getting GPU devices: %w", err) +func (ctx *systemContext) fillDeviceInfo() error { + count, ret := ctx.nvmlLib.DeviceGetCount() + if ret != nvml.SUCCESS { + return fmt.Errorf("failed to get device count: %s", nvml.ErrorString(ret)) } + for i := 0; i < count; i++ { + dev, ret := ctx.nvmlLib.DeviceGetHandleByIndex(i) + if ret != nvml.SUCCESS { + return fmt.Errorf("failed to get device handle for index %d: %s", i, nvml.ErrorString(ret)) + } - for i, device := range devices { - maxThreads, err := getMaxThreadsForDevice(device) - if err != nil { - return fmt.Errorf("error getting max threads for device %s: %w", device, err) + maxThreads, ret := dev.GetNumGpuCores() + if ret != nvml.SUCCESS { + return fmt.Errorf("error getting max threads for device %s: %s", dev, nvml.ErrorString(ret)) } ctx.maxGpuThreadsPerDevice[i] = maxThreads } - return nil } diff --git a/pkg/gpu/cuda/fatbin_test.go b/pkg/gpu/cuda/fatbin_test.go index 54eb62729c8ec..702a9fa0207e5 100644 --- a/pkg/gpu/cuda/fatbin_test.go +++ b/pkg/gpu/cuda/fatbin_test.go @@ -8,7 +8,9 @@ package cuda import ( + "fmt" "path/filepath" + "strings" "testing" "golang.org/x/exp/maps" @@ -18,19 +20,20 @@ import ( "github.com/DataDog/datadog-agent/pkg/network/protocols/http/testutil" ) -// The test data is a CUDA fatbin file compiled with the Makefile present in the same directory. -func getCudaSample(t testing.TB) string { +// The test data is a CUDA fatbin file compiled with the Makefile present in the same directory, +// using `make ` (for now, only supported samples are `sample` and `heavy-sample`). +func getCudaSample(t testing.TB, name string) string { curDir, err := testutil.CurDir() require.NoError(t, err) - sample := filepath.Join(curDir, "testdata", "sample") + sample := filepath.Join(curDir, "testdata", name) require.FileExists(t, sample) return sample } func TestParseFatbinFromPath(t *testing.T) { - path := getCudaSample(t) + path := getCudaSample(t, "sample") res, err := ParseFatbinFromELFFilePath(path) require.NoError(t, err) @@ -70,11 +73,66 @@ func TestParseFatbinFromPath(t *testing.T) { } func BenchmarkParseFatbinFromPath(b *testing.B) { - path := getCudaSample(b) - for i := 0; i < b.N; i++ { - _, err := ParseFatbinFromELFFilePath(path) - if err != nil { - b.Fatalf("unexpected error: %v", err) + samples := []string{"sample", "heavy-sample"} + for _, sample := range samples { + b.Run(sample, func(b *testing.B) { + path := getCudaSample(b, sample) + for i := 0; i < b.N; i++ { + _, err := ParseFatbinFromELFFilePath(path) + if err != nil { + b.Fatalf("unexpected error: %v", err) + } + } + }) + } +} + +// The heavy-sample binary is an automatically-generated CUDA fatbin file with a +// large number of kernels, designed to stress the parser. The parser workload +// scales with the number of variables per kernel and kernels. +func TestParseBigFatbinFromPath(t *testing.T) { + path := getCudaSample(t, "heavy-sample") + res, err := ParseFatbinFromELFFilePath(path) + require.NoError(t, err) + + // These parameters need to match the same values used in the Makefile to generate the sample + numKernels := 100 + numVariablesPerKernel := 20 + sharedMemSize := 1024 + + var expectedSharedMemSizes = make(map[string]uint64) + var expectedKernels = make([]string, numKernels) + for i := 0; i < numKernels; i++ { + mangledArgSpec := strings.Repeat("S_", numVariablesPerKernel-1) + funcName := fmt.Sprintf("kernel_%d", i) + mangledKernName := fmt.Sprintf("_Z%d%sPf%s", len(funcName), funcName, mangledArgSpec) + expectedKernels[i] = mangledKernName + expectedSharedMemSizes[mangledKernName] = uint64(sharedMemSize) + } + + seenSmVersionsAndKernels := make(map[uint32][]string) + + for key, kernel := range res.Kernels { + seenSmVersionsAndKernels[key.SmVersion] = append(seenSmVersionsAndKernels[key.SmVersion], key.Name) + require.Equal(t, key.Name, kernel.Name) + + expectedMemSize, ok := expectedSharedMemSizes[key.Name] + require.True(t, ok, "unexpected kernel %s, expected kernels=%v", key.Name, expectedKernels) + + // The memory sizes are different for sm_90, checked with cuobjdump + if key.SmVersion != 90 && false { + require.Equal(t, expectedMemSize, kernel.SharedMem, "unexpected shared memory size for kernel %s, sm=%d", key.Name, key.SmVersion) } + + require.Greater(t, kernel.KernelSize, uint64(0), "unexpected kernel size for kernel %s, sm=%d", key.Name, key.SmVersion) + } + + // From the Makefile, all the -gencode arch=compute_XX,code=sm_XX flags + expectedSmVersions := []uint32{50, 52, 60, 61, 70, 75, 80, 86, 89, 90} + require.ElementsMatch(t, expectedSmVersions, maps.Keys(seenSmVersionsAndKernels)) + + // Check that all the kernels are present in each version + for version, kernelNames := range seenSmVersionsAndKernels { + require.ElementsMatch(t, expectedKernels, kernelNames, "missing kernels for version %d", version) } } diff --git a/pkg/gpu/cuda/testdata/Makefile b/pkg/gpu/cuda/testdata/Makefile index 8cd04ebcdd52e..81eb940322582 100644 --- a/pkg/gpu/cuda/testdata/Makefile +++ b/pkg/gpu/cuda/testdata/Makefile @@ -1,8 +1,16 @@ NVCC = /usr/local/cuda/bin/nvcc +TEMPL_GENERATOR = ./gen-heavy-sample.go -all: sample +GENERATOR_VARIABLES = 20 +GENERATOR_KERNELS = 100 +GENERATOR_SHARED_MEMORY = 1024 +GENERATOR_INSTRUCTIONS = 10 # Keep low to avoid large binaries, as number of instructions don't affect the performance of our parsing code -sample.o: sample.cu +all: sample heavy-sample + +.PRECIOUS: %.cu + +%.o: %.cu $(NVCC) -ccbin g++ -m64 -Xcompiler -ggdb -Xcompiler -pg --threads 0 --std=c++11 \ -gencode arch=compute_50,code=sm_50 \ -gencode arch=compute_52,code=sm_52 \ @@ -15,9 +23,9 @@ sample.o: sample.cu -gencode arch=compute_89,code=sm_89 \ -gencode arch=compute_90,code=sm_90 \ -gencode arch=compute_90,code=compute_90 \ - -o sample.o -c sample.cu + -o $@ -c $< -sample: sample.o +%: %.o $(NVCC) -ccbin g++ -m64 -Xcompiler -ggdb -Xcompiler -pg \ -gencode arch=compute_50,code=sm_50 \ -gencode arch=compute_52,code=sm_52 \ @@ -30,4 +38,7 @@ sample: sample.o -gencode arch=compute_89,code=sm_89 \ -gencode arch=compute_90,code=sm_90 \ -gencode arch=compute_90,code=compute_90 \ - -o sample sample.o + -o $@ $< + +%.cu: %.cu.tmpl $(TEMPL_GENERATOR) Makefile + go run $(TEMPL_GENERATOR) -template $< -output $@ -kernels $(GENERATOR_KERNELS) -variables $(GENERATOR_VARIABLES) -shared-memory $(GENERATOR_SHARED_MEMORY) -instructions $(GENERATOR_INSTRUCTIONS) diff --git a/pkg/gpu/cuda/testdata/gen-heavy-sample.go b/pkg/gpu/cuda/testdata/gen-heavy-sample.go new file mode 100644 index 0000000000000..14671371deb7e --- /dev/null +++ b/pkg/gpu/cuda/testdata/gen-heavy-sample.go @@ -0,0 +1,113 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024-present Datadog, Inc. + +// Package main is the entry point for the heavy sample template generator +package main + +import ( + "flag" + "fmt" + "math/rand/v2" + "os" + "strings" + "text/template" +) + +var templatePath = flag.String("template", "heavy-sample.cu.tmpl", "Path to the template file") +var outputPath = flag.String("output", "heavy-sample.cu", "Path to the output file") +var numKernels = flag.Int("kernels", 80, "Number of kernels to generate") +var numVariablesPerKernel = flag.Int("variables", 10, "Number of variables to generate per kernel") + +// Note that the number of instructions per kernel doesn't really affect our fatbin parser, but it does increase the binary size, so it's +// useful to keep it low to avoid committing large binaries to the repository +var numInstructionsPerKernel = flag.Int("instructions", 10, "Number of instructions to generate per kernel") +var sharedMemorySize = flag.Int("shared-memory", 1024, "Size of the shared memory in bytes") + +const sharedMemoryVar = "myVar" + +// Kernel represents a kernel entry in the template +type Kernel struct { + Name string + Argdef string + Argcall string + Instructions []string + SharedMemorySize int +} + +// Variable represents a variable entry in the template that will be shared between kernels +type Variable struct { + Name string + Type string +} + +// TemplateData represents the data that will be passed to the template +type TemplateData struct { + Kernels []Kernel + Variables []Variable +} + +func genInstructions(numInstructions int) []string { + instructions := make([]string, numInstructions) + for i := 0; i < numInstructions; i++ { + indexSrc := rand.IntN(10) + valueMult := rand.Float64() * 50 + instructions[i] = fmt.Sprintf("%s[%d] = %f * %s[threadIdx.x];", sharedMemoryVar, indexSrc, valueMult, sharedMemoryVar) + } + return instructions +} + +func main() { + flag.Parse() + + // Load the template file + tmpl, err := template.New(*templatePath).ParseFiles(*templatePath) + if err != nil { + fmt.Fprintf(os.Stderr, "Error parsing template file: %v\n", err) + os.Exit(1) + } + + // Create the output file + out, err := os.Create(*outputPath) + if err != nil { + fmt.Fprintf(os.Stderr, "Error creating output file: %v\n", err) + os.Exit(1) + } + defer out.Close() + + var data TemplateData + for i := 0; i < *numKernels; i++ { + kernel := Kernel{ + Name: fmt.Sprintf("kernel_%d", i), + Instructions: genInstructions(*numInstructionsPerKernel), + SharedMemorySize: *sharedMemorySize, + } + + var argDef []string + var argCall []string + + for j := 0; j < *numVariablesPerKernel; j++ { + varName := fmt.Sprintf("var_%d_%d", i, j) + varType := "float *" + data.Variables = append(data.Variables, Variable{Name: varName, Type: varType}) + argDef = append(argDef, fmt.Sprintf("%s %s", varType, varName)) + argCall = append(argCall, fmt.Sprintf("d_%s", varName)) + + // Add data to this variable from the shared memory, to force the compiler to keep it + kernel.Instructions = append(kernel.Instructions, fmt.Sprintf("%s[%d] = %s[%d];", varName, j, sharedMemoryVar, j)) + } + + kernel.Argdef = strings.Join(argDef, ", ") + kernel.Argcall = strings.Join(argCall, ", ") + + data.Kernels = append(data.Kernels, kernel) + } + + // Execute the template + err = tmpl.Execute(out, data) + if err != nil { + fmt.Fprintf(os.Stderr, "Error executing template: %v\n", err) + os.Exit(1) + } +} diff --git a/pkg/gpu/cuda/testdata/heavy-sample b/pkg/gpu/cuda/testdata/heavy-sample new file mode 100755 index 0000000000000..c9ce4bf5a93d0 Binary files /dev/null and b/pkg/gpu/cuda/testdata/heavy-sample differ diff --git a/pkg/gpu/cuda/testdata/heavy-sample.cu b/pkg/gpu/cuda/testdata/heavy-sample.cu new file mode 100644 index 0000000000000..d3b7f0947691b --- /dev/null +++ b/pkg/gpu/cuda/testdata/heavy-sample.cu @@ -0,0 +1,11720 @@ +/* AUTO-GENERATED, DO NOT CHANGE */ + +// To regenerate, run `make heavy-sample.cu` in this directory + +#include + +#include + + +__global__ void kernel_0(float * var_0_0, float * var_0_1, float * var_0_2, float * var_0_3, float * var_0_4, float * var_0_5, float * var_0_6, float * var_0_7, float * var_0_8, float * var_0_9, float * var_0_10, float * var_0_11, float * var_0_12, float * var_0_13, float * var_0_14, float * var_0_15, float * var_0_16, float * var_0_17, float * var_0_18, float * var_0_19) { + __shared__ float myVar[1024]; + myVar[7] = 13.358492 * myVar[threadIdx.x]; + myVar[0] = 29.996864 * myVar[threadIdx.x]; + myVar[7] = 26.850372 * myVar[threadIdx.x]; + myVar[7] = 47.405648 * myVar[threadIdx.x]; + myVar[8] = 28.605543 * myVar[threadIdx.x]; + myVar[8] = 30.566722 * myVar[threadIdx.x]; + myVar[3] = 8.149732 * myVar[threadIdx.x]; + myVar[2] = 42.915701 * myVar[threadIdx.x]; + myVar[0] = 36.084747 * myVar[threadIdx.x]; + myVar[6] = 2.276106 * myVar[threadIdx.x]; + var_0_0[0] = myVar[0]; + var_0_1[1] = myVar[1]; + var_0_2[2] = myVar[2]; + var_0_3[3] = myVar[3]; + var_0_4[4] = myVar[4]; + var_0_5[5] = myVar[5]; + var_0_6[6] = myVar[6]; + var_0_7[7] = myVar[7]; + var_0_8[8] = myVar[8]; + var_0_9[9] = myVar[9]; + var_0_10[10] = myVar[10]; + var_0_11[11] = myVar[11]; + var_0_12[12] = myVar[12]; + var_0_13[13] = myVar[13]; + var_0_14[14] = myVar[14]; + var_0_15[15] = myVar[15]; + var_0_16[16] = myVar[16]; + var_0_17[17] = myVar[17]; + var_0_18[18] = myVar[18]; + var_0_19[19] = myVar[19]; + +} + +__global__ void kernel_1(float * var_1_0, float * var_1_1, float * var_1_2, float * var_1_3, float * var_1_4, float * var_1_5, float * var_1_6, float * var_1_7, float * var_1_8, float * var_1_9, float * var_1_10, float * var_1_11, float * var_1_12, float * var_1_13, float * var_1_14, float * var_1_15, float * var_1_16, float * var_1_17, float * var_1_18, float * var_1_19) { + __shared__ float myVar[1024]; + myVar[4] = 4.577338 * myVar[threadIdx.x]; + myVar[4] = 21.162567 * myVar[threadIdx.x]; + myVar[7] = 0.128262 * myVar[threadIdx.x]; + myVar[8] = 22.890511 * myVar[threadIdx.x]; + myVar[8] = 22.667310 * myVar[threadIdx.x]; + myVar[0] = 29.358554 * myVar[threadIdx.x]; + myVar[5] = 13.730931 * myVar[threadIdx.x]; + myVar[6] = 32.720741 * myVar[threadIdx.x]; + myVar[7] = 11.978346 * myVar[threadIdx.x]; + myVar[2] = 32.092827 * myVar[threadIdx.x]; + var_1_0[0] = myVar[0]; + var_1_1[1] = myVar[1]; + var_1_2[2] = myVar[2]; + var_1_3[3] = myVar[3]; + var_1_4[4] = myVar[4]; + var_1_5[5] = myVar[5]; + var_1_6[6] = myVar[6]; + var_1_7[7] = myVar[7]; + var_1_8[8] = myVar[8]; + var_1_9[9] = myVar[9]; + var_1_10[10] = myVar[10]; + var_1_11[11] = myVar[11]; + var_1_12[12] = myVar[12]; + var_1_13[13] = myVar[13]; + var_1_14[14] = myVar[14]; + var_1_15[15] = myVar[15]; + var_1_16[16] = myVar[16]; + var_1_17[17] = myVar[17]; + var_1_18[18] = myVar[18]; + var_1_19[19] = myVar[19]; + +} + +__global__ void kernel_2(float * var_2_0, float * var_2_1, float * var_2_2, float * var_2_3, float * var_2_4, float * var_2_5, float * var_2_6, float * var_2_7, float * var_2_8, float * var_2_9, float * var_2_10, float * var_2_11, float * var_2_12, float * var_2_13, float * var_2_14, float * var_2_15, float * var_2_16, float * var_2_17, float * var_2_18, float * var_2_19) { + __shared__ float myVar[1024]; + myVar[3] = 49.191664 * myVar[threadIdx.x]; + myVar[3] = 5.722245 * myVar[threadIdx.x]; + myVar[5] = 3.621897 * myVar[threadIdx.x]; + myVar[0] = 10.483091 * myVar[threadIdx.x]; + myVar[6] = 36.425846 * myVar[threadIdx.x]; + myVar[9] = 49.066374 * myVar[threadIdx.x]; + myVar[3] = 41.370231 * myVar[threadIdx.x]; + myVar[2] = 38.310331 * myVar[threadIdx.x]; + myVar[2] = 38.696066 * myVar[threadIdx.x]; + myVar[5] = 17.802057 * myVar[threadIdx.x]; + var_2_0[0] = myVar[0]; + var_2_1[1] = myVar[1]; + var_2_2[2] = myVar[2]; + var_2_3[3] = myVar[3]; + var_2_4[4] = myVar[4]; + var_2_5[5] = myVar[5]; + var_2_6[6] = myVar[6]; + var_2_7[7] = myVar[7]; + var_2_8[8] = myVar[8]; + var_2_9[9] = myVar[9]; + var_2_10[10] = myVar[10]; + var_2_11[11] = myVar[11]; + var_2_12[12] = myVar[12]; + var_2_13[13] = myVar[13]; + var_2_14[14] = myVar[14]; + var_2_15[15] = myVar[15]; + var_2_16[16] = myVar[16]; + var_2_17[17] = myVar[17]; + var_2_18[18] = myVar[18]; + var_2_19[19] = myVar[19]; + +} + +__global__ void kernel_3(float * var_3_0, float * var_3_1, float * var_3_2, float * var_3_3, float * var_3_4, float * var_3_5, float * var_3_6, float * var_3_7, float * var_3_8, float * var_3_9, float * var_3_10, float * var_3_11, float * var_3_12, float * var_3_13, float * var_3_14, float * var_3_15, float * var_3_16, float * var_3_17, float * var_3_18, float * var_3_19) { + __shared__ float myVar[1024]; + myVar[1] = 3.657881 * myVar[threadIdx.x]; + myVar[9] = 47.144202 * myVar[threadIdx.x]; + myVar[7] = 26.768394 * myVar[threadIdx.x]; + myVar[4] = 25.254215 * myVar[threadIdx.x]; + myVar[8] = 36.901003 * myVar[threadIdx.x]; + myVar[5] = 12.665010 * myVar[threadIdx.x]; + myVar[6] = 12.501012 * myVar[threadIdx.x]; + myVar[2] = 33.849199 * myVar[threadIdx.x]; + myVar[1] = 44.025130 * myVar[threadIdx.x]; + myVar[1] = 48.566763 * myVar[threadIdx.x]; + var_3_0[0] = myVar[0]; + var_3_1[1] = myVar[1]; + var_3_2[2] = myVar[2]; + var_3_3[3] = myVar[3]; + var_3_4[4] = myVar[4]; + var_3_5[5] = myVar[5]; + var_3_6[6] = myVar[6]; + var_3_7[7] = myVar[7]; + var_3_8[8] = myVar[8]; + var_3_9[9] = myVar[9]; + var_3_10[10] = myVar[10]; + var_3_11[11] = myVar[11]; + var_3_12[12] = myVar[12]; + var_3_13[13] = myVar[13]; + var_3_14[14] = myVar[14]; + var_3_15[15] = myVar[15]; + var_3_16[16] = myVar[16]; + var_3_17[17] = myVar[17]; + var_3_18[18] = myVar[18]; + var_3_19[19] = myVar[19]; + +} + +__global__ void kernel_4(float * var_4_0, float * var_4_1, float * var_4_2, float * var_4_3, float * var_4_4, float * var_4_5, float * var_4_6, float * var_4_7, float * var_4_8, float * var_4_9, float * var_4_10, float * var_4_11, float * var_4_12, float * var_4_13, float * var_4_14, float * var_4_15, float * var_4_16, float * var_4_17, float * var_4_18, float * var_4_19) { + __shared__ float myVar[1024]; + myVar[9] = 34.814125 * myVar[threadIdx.x]; + myVar[0] = 7.439284 * myVar[threadIdx.x]; + myVar[8] = 24.182738 * myVar[threadIdx.x]; + myVar[6] = 41.521589 * myVar[threadIdx.x]; + myVar[0] = 8.476383 * myVar[threadIdx.x]; + myVar[4] = 4.308362 * myVar[threadIdx.x]; + myVar[0] = 34.019957 * myVar[threadIdx.x]; + myVar[4] = 14.880842 * myVar[threadIdx.x]; + myVar[1] = 25.167021 * myVar[threadIdx.x]; + myVar[8] = 14.620295 * myVar[threadIdx.x]; + var_4_0[0] = myVar[0]; + var_4_1[1] = myVar[1]; + var_4_2[2] = myVar[2]; + var_4_3[3] = myVar[3]; + var_4_4[4] = myVar[4]; + var_4_5[5] = myVar[5]; + var_4_6[6] = myVar[6]; + var_4_7[7] = myVar[7]; + var_4_8[8] = myVar[8]; + var_4_9[9] = myVar[9]; + var_4_10[10] = myVar[10]; + var_4_11[11] = myVar[11]; + var_4_12[12] = myVar[12]; + var_4_13[13] = myVar[13]; + var_4_14[14] = myVar[14]; + var_4_15[15] = myVar[15]; + var_4_16[16] = myVar[16]; + var_4_17[17] = myVar[17]; + var_4_18[18] = myVar[18]; + var_4_19[19] = myVar[19]; + +} + +__global__ void kernel_5(float * var_5_0, float * var_5_1, float * var_5_2, float * var_5_3, float * var_5_4, float * var_5_5, float * var_5_6, float * var_5_7, float * var_5_8, float * var_5_9, float * var_5_10, float * var_5_11, float * var_5_12, float * var_5_13, float * var_5_14, float * var_5_15, float * var_5_16, float * var_5_17, float * var_5_18, float * var_5_19) { + __shared__ float myVar[1024]; + myVar[2] = 37.042397 * myVar[threadIdx.x]; + myVar[0] = 15.897506 * myVar[threadIdx.x]; + myVar[9] = 29.881857 * myVar[threadIdx.x]; + myVar[4] = 28.287586 * myVar[threadIdx.x]; + myVar[8] = 13.202707 * myVar[threadIdx.x]; + myVar[4] = 23.235843 * myVar[threadIdx.x]; + myVar[3] = 45.601563 * myVar[threadIdx.x]; + myVar[0] = 22.131163 * myVar[threadIdx.x]; + myVar[1] = 2.447910 * myVar[threadIdx.x]; + myVar[6] = 48.949264 * myVar[threadIdx.x]; + var_5_0[0] = myVar[0]; + var_5_1[1] = myVar[1]; + var_5_2[2] = myVar[2]; + var_5_3[3] = myVar[3]; + var_5_4[4] = myVar[4]; + var_5_5[5] = myVar[5]; + var_5_6[6] = myVar[6]; + var_5_7[7] = myVar[7]; + var_5_8[8] = myVar[8]; + var_5_9[9] = myVar[9]; + var_5_10[10] = myVar[10]; + var_5_11[11] = myVar[11]; + var_5_12[12] = myVar[12]; + var_5_13[13] = myVar[13]; + var_5_14[14] = myVar[14]; + var_5_15[15] = myVar[15]; + var_5_16[16] = myVar[16]; + var_5_17[17] = myVar[17]; + var_5_18[18] = myVar[18]; + var_5_19[19] = myVar[19]; + +} + +__global__ void kernel_6(float * var_6_0, float * var_6_1, float * var_6_2, float * var_6_3, float * var_6_4, float * var_6_5, float * var_6_6, float * var_6_7, float * var_6_8, float * var_6_9, float * var_6_10, float * var_6_11, float * var_6_12, float * var_6_13, float * var_6_14, float * var_6_15, float * var_6_16, float * var_6_17, float * var_6_18, float * var_6_19) { + __shared__ float myVar[1024]; + myVar[5] = 42.612716 * myVar[threadIdx.x]; + myVar[1] = 32.709412 * myVar[threadIdx.x]; + myVar[2] = 1.664703 * myVar[threadIdx.x]; + myVar[7] = 17.973638 * myVar[threadIdx.x]; + myVar[1] = 20.774570 * myVar[threadIdx.x]; + myVar[5] = 16.371010 * myVar[threadIdx.x]; + myVar[3] = 19.487553 * myVar[threadIdx.x]; + myVar[3] = 36.774980 * myVar[threadIdx.x]; + myVar[5] = 28.604668 * myVar[threadIdx.x]; + myVar[2] = 15.117050 * myVar[threadIdx.x]; + var_6_0[0] = myVar[0]; + var_6_1[1] = myVar[1]; + var_6_2[2] = myVar[2]; + var_6_3[3] = myVar[3]; + var_6_4[4] = myVar[4]; + var_6_5[5] = myVar[5]; + var_6_6[6] = myVar[6]; + var_6_7[7] = myVar[7]; + var_6_8[8] = myVar[8]; + var_6_9[9] = myVar[9]; + var_6_10[10] = myVar[10]; + var_6_11[11] = myVar[11]; + var_6_12[12] = myVar[12]; + var_6_13[13] = myVar[13]; + var_6_14[14] = myVar[14]; + var_6_15[15] = myVar[15]; + var_6_16[16] = myVar[16]; + var_6_17[17] = myVar[17]; + var_6_18[18] = myVar[18]; + var_6_19[19] = myVar[19]; + +} + +__global__ void kernel_7(float * var_7_0, float * var_7_1, float * var_7_2, float * var_7_3, float * var_7_4, float * var_7_5, float * var_7_6, float * var_7_7, float * var_7_8, float * var_7_9, float * var_7_10, float * var_7_11, float * var_7_12, float * var_7_13, float * var_7_14, float * var_7_15, float * var_7_16, float * var_7_17, float * var_7_18, float * var_7_19) { + __shared__ float myVar[1024]; + myVar[4] = 9.570039 * myVar[threadIdx.x]; + myVar[9] = 7.446622 * myVar[threadIdx.x]; + myVar[8] = 4.543599 * myVar[threadIdx.x]; + myVar[7] = 26.174945 * myVar[threadIdx.x]; + myVar[4] = 13.540677 * myVar[threadIdx.x]; + myVar[9] = 33.803400 * myVar[threadIdx.x]; + myVar[8] = 24.045981 * myVar[threadIdx.x]; + myVar[3] = 22.198640 * myVar[threadIdx.x]; + myVar[9] = 22.882328 * myVar[threadIdx.x]; + myVar[3] = 9.353756 * myVar[threadIdx.x]; + var_7_0[0] = myVar[0]; + var_7_1[1] = myVar[1]; + var_7_2[2] = myVar[2]; + var_7_3[3] = myVar[3]; + var_7_4[4] = myVar[4]; + var_7_5[5] = myVar[5]; + var_7_6[6] = myVar[6]; + var_7_7[7] = myVar[7]; + var_7_8[8] = myVar[8]; + var_7_9[9] = myVar[9]; + var_7_10[10] = myVar[10]; + var_7_11[11] = myVar[11]; + var_7_12[12] = myVar[12]; + var_7_13[13] = myVar[13]; + var_7_14[14] = myVar[14]; + var_7_15[15] = myVar[15]; + var_7_16[16] = myVar[16]; + var_7_17[17] = myVar[17]; + var_7_18[18] = myVar[18]; + var_7_19[19] = myVar[19]; + +} + +__global__ void kernel_8(float * var_8_0, float * var_8_1, float * var_8_2, float * var_8_3, float * var_8_4, float * var_8_5, float * var_8_6, float * var_8_7, float * var_8_8, float * var_8_9, float * var_8_10, float * var_8_11, float * var_8_12, float * var_8_13, float * var_8_14, float * var_8_15, float * var_8_16, float * var_8_17, float * var_8_18, float * var_8_19) { + __shared__ float myVar[1024]; + myVar[7] = 15.547479 * myVar[threadIdx.x]; + myVar[3] = 48.901650 * myVar[threadIdx.x]; + myVar[5] = 26.480024 * myVar[threadIdx.x]; + myVar[6] = 3.905452 * myVar[threadIdx.x]; + myVar[8] = 10.110801 * myVar[threadIdx.x]; + myVar[5] = 39.252634 * myVar[threadIdx.x]; + myVar[0] = 40.038305 * myVar[threadIdx.x]; + myVar[7] = 35.166664 * myVar[threadIdx.x]; + myVar[2] = 37.185844 * myVar[threadIdx.x]; + myVar[5] = 18.754616 * myVar[threadIdx.x]; + var_8_0[0] = myVar[0]; + var_8_1[1] = myVar[1]; + var_8_2[2] = myVar[2]; + var_8_3[3] = myVar[3]; + var_8_4[4] = myVar[4]; + var_8_5[5] = myVar[5]; + var_8_6[6] = myVar[6]; + var_8_7[7] = myVar[7]; + var_8_8[8] = myVar[8]; + var_8_9[9] = myVar[9]; + var_8_10[10] = myVar[10]; + var_8_11[11] = myVar[11]; + var_8_12[12] = myVar[12]; + var_8_13[13] = myVar[13]; + var_8_14[14] = myVar[14]; + var_8_15[15] = myVar[15]; + var_8_16[16] = myVar[16]; + var_8_17[17] = myVar[17]; + var_8_18[18] = myVar[18]; + var_8_19[19] = myVar[19]; + +} + +__global__ void kernel_9(float * var_9_0, float * var_9_1, float * var_9_2, float * var_9_3, float * var_9_4, float * var_9_5, float * var_9_6, float * var_9_7, float * var_9_8, float * var_9_9, float * var_9_10, float * var_9_11, float * var_9_12, float * var_9_13, float * var_9_14, float * var_9_15, float * var_9_16, float * var_9_17, float * var_9_18, float * var_9_19) { + __shared__ float myVar[1024]; + myVar[6] = 14.290958 * myVar[threadIdx.x]; + myVar[8] = 42.139091 * myVar[threadIdx.x]; + myVar[8] = 36.378596 * myVar[threadIdx.x]; + myVar[3] = 46.441771 * myVar[threadIdx.x]; + myVar[6] = 8.854676 * myVar[threadIdx.x]; + myVar[8] = 20.100396 * myVar[threadIdx.x]; + myVar[6] = 8.781566 * myVar[threadIdx.x]; + myVar[8] = 44.446736 * myVar[threadIdx.x]; + myVar[5] = 7.496880 * myVar[threadIdx.x]; + myVar[8] = 40.785167 * myVar[threadIdx.x]; + var_9_0[0] = myVar[0]; + var_9_1[1] = myVar[1]; + var_9_2[2] = myVar[2]; + var_9_3[3] = myVar[3]; + var_9_4[4] = myVar[4]; + var_9_5[5] = myVar[5]; + var_9_6[6] = myVar[6]; + var_9_7[7] = myVar[7]; + var_9_8[8] = myVar[8]; + var_9_9[9] = myVar[9]; + var_9_10[10] = myVar[10]; + var_9_11[11] = myVar[11]; + var_9_12[12] = myVar[12]; + var_9_13[13] = myVar[13]; + var_9_14[14] = myVar[14]; + var_9_15[15] = myVar[15]; + var_9_16[16] = myVar[16]; + var_9_17[17] = myVar[17]; + var_9_18[18] = myVar[18]; + var_9_19[19] = myVar[19]; + +} + +__global__ void kernel_10(float * var_10_0, float * var_10_1, float * var_10_2, float * var_10_3, float * var_10_4, float * var_10_5, float * var_10_6, float * var_10_7, float * var_10_8, float * var_10_9, float * var_10_10, float * var_10_11, float * var_10_12, float * var_10_13, float * var_10_14, float * var_10_15, float * var_10_16, float * var_10_17, float * var_10_18, float * var_10_19) { + __shared__ float myVar[1024]; + myVar[6] = 41.374924 * myVar[threadIdx.x]; + myVar[7] = 5.583937 * myVar[threadIdx.x]; + myVar[1] = 11.415106 * myVar[threadIdx.x]; + myVar[7] = 16.040032 * myVar[threadIdx.x]; + myVar[9] = 49.003678 * myVar[threadIdx.x]; + myVar[9] = 33.529291 * myVar[threadIdx.x]; + myVar[9] = 3.725300 * myVar[threadIdx.x]; + myVar[9] = 36.318961 * myVar[threadIdx.x]; + myVar[4] = 34.676808 * myVar[threadIdx.x]; + myVar[8] = 0.789490 * myVar[threadIdx.x]; + var_10_0[0] = myVar[0]; + var_10_1[1] = myVar[1]; + var_10_2[2] = myVar[2]; + var_10_3[3] = myVar[3]; + var_10_4[4] = myVar[4]; + var_10_5[5] = myVar[5]; + var_10_6[6] = myVar[6]; + var_10_7[7] = myVar[7]; + var_10_8[8] = myVar[8]; + var_10_9[9] = myVar[9]; + var_10_10[10] = myVar[10]; + var_10_11[11] = myVar[11]; + var_10_12[12] = myVar[12]; + var_10_13[13] = myVar[13]; + var_10_14[14] = myVar[14]; + var_10_15[15] = myVar[15]; + var_10_16[16] = myVar[16]; + var_10_17[17] = myVar[17]; + var_10_18[18] = myVar[18]; + var_10_19[19] = myVar[19]; + +} + +__global__ void kernel_11(float * var_11_0, float * var_11_1, float * var_11_2, float * var_11_3, float * var_11_4, float * var_11_5, float * var_11_6, float * var_11_7, float * var_11_8, float * var_11_9, float * var_11_10, float * var_11_11, float * var_11_12, float * var_11_13, float * var_11_14, float * var_11_15, float * var_11_16, float * var_11_17, float * var_11_18, float * var_11_19) { + __shared__ float myVar[1024]; + myVar[5] = 27.667212 * myVar[threadIdx.x]; + myVar[2] = 12.702892 * myVar[threadIdx.x]; + myVar[2] = 18.730612 * myVar[threadIdx.x]; + myVar[9] = 8.009668 * myVar[threadIdx.x]; + myVar[9] = 1.903979 * myVar[threadIdx.x]; + myVar[9] = 20.042565 * myVar[threadIdx.x]; + myVar[0] = 34.292619 * myVar[threadIdx.x]; + myVar[9] = 39.456481 * myVar[threadIdx.x]; + myVar[1] = 25.805260 * myVar[threadIdx.x]; + myVar[7] = 10.881045 * myVar[threadIdx.x]; + var_11_0[0] = myVar[0]; + var_11_1[1] = myVar[1]; + var_11_2[2] = myVar[2]; + var_11_3[3] = myVar[3]; + var_11_4[4] = myVar[4]; + var_11_5[5] = myVar[5]; + var_11_6[6] = myVar[6]; + var_11_7[7] = myVar[7]; + var_11_8[8] = myVar[8]; + var_11_9[9] = myVar[9]; + var_11_10[10] = myVar[10]; + var_11_11[11] = myVar[11]; + var_11_12[12] = myVar[12]; + var_11_13[13] = myVar[13]; + var_11_14[14] = myVar[14]; + var_11_15[15] = myVar[15]; + var_11_16[16] = myVar[16]; + var_11_17[17] = myVar[17]; + var_11_18[18] = myVar[18]; + var_11_19[19] = myVar[19]; + +} + +__global__ void kernel_12(float * var_12_0, float * var_12_1, float * var_12_2, float * var_12_3, float * var_12_4, float * var_12_5, float * var_12_6, float * var_12_7, float * var_12_8, float * var_12_9, float * var_12_10, float * var_12_11, float * var_12_12, float * var_12_13, float * var_12_14, float * var_12_15, float * var_12_16, float * var_12_17, float * var_12_18, float * var_12_19) { + __shared__ float myVar[1024]; + myVar[4] = 25.536327 * myVar[threadIdx.x]; + myVar[6] = 5.530078 * myVar[threadIdx.x]; + myVar[4] = 1.930924 * myVar[threadIdx.x]; + myVar[9] = 38.945469 * myVar[threadIdx.x]; + myVar[9] = 35.199808 * myVar[threadIdx.x]; + myVar[4] = 45.394917 * myVar[threadIdx.x]; + myVar[1] = 25.106426 * myVar[threadIdx.x]; + myVar[3] = 43.623141 * myVar[threadIdx.x]; + myVar[5] = 39.114022 * myVar[threadIdx.x]; + myVar[9] = 33.734836 * myVar[threadIdx.x]; + var_12_0[0] = myVar[0]; + var_12_1[1] = myVar[1]; + var_12_2[2] = myVar[2]; + var_12_3[3] = myVar[3]; + var_12_4[4] = myVar[4]; + var_12_5[5] = myVar[5]; + var_12_6[6] = myVar[6]; + var_12_7[7] = myVar[7]; + var_12_8[8] = myVar[8]; + var_12_9[9] = myVar[9]; + var_12_10[10] = myVar[10]; + var_12_11[11] = myVar[11]; + var_12_12[12] = myVar[12]; + var_12_13[13] = myVar[13]; + var_12_14[14] = myVar[14]; + var_12_15[15] = myVar[15]; + var_12_16[16] = myVar[16]; + var_12_17[17] = myVar[17]; + var_12_18[18] = myVar[18]; + var_12_19[19] = myVar[19]; + +} + +__global__ void kernel_13(float * var_13_0, float * var_13_1, float * var_13_2, float * var_13_3, float * var_13_4, float * var_13_5, float * var_13_6, float * var_13_7, float * var_13_8, float * var_13_9, float * var_13_10, float * var_13_11, float * var_13_12, float * var_13_13, float * var_13_14, float * var_13_15, float * var_13_16, float * var_13_17, float * var_13_18, float * var_13_19) { + __shared__ float myVar[1024]; + myVar[9] = 37.548477 * myVar[threadIdx.x]; + myVar[2] = 42.389733 * myVar[threadIdx.x]; + myVar[2] = 9.754293 * myVar[threadIdx.x]; + myVar[1] = 24.123587 * myVar[threadIdx.x]; + myVar[2] = 23.260944 * myVar[threadIdx.x]; + myVar[9] = 18.619336 * myVar[threadIdx.x]; + myVar[2] = 17.496481 * myVar[threadIdx.x]; + myVar[1] = 40.139043 * myVar[threadIdx.x]; + myVar[5] = 22.620901 * myVar[threadIdx.x]; + myVar[8] = 29.155860 * myVar[threadIdx.x]; + var_13_0[0] = myVar[0]; + var_13_1[1] = myVar[1]; + var_13_2[2] = myVar[2]; + var_13_3[3] = myVar[3]; + var_13_4[4] = myVar[4]; + var_13_5[5] = myVar[5]; + var_13_6[6] = myVar[6]; + var_13_7[7] = myVar[7]; + var_13_8[8] = myVar[8]; + var_13_9[9] = myVar[9]; + var_13_10[10] = myVar[10]; + var_13_11[11] = myVar[11]; + var_13_12[12] = myVar[12]; + var_13_13[13] = myVar[13]; + var_13_14[14] = myVar[14]; + var_13_15[15] = myVar[15]; + var_13_16[16] = myVar[16]; + var_13_17[17] = myVar[17]; + var_13_18[18] = myVar[18]; + var_13_19[19] = myVar[19]; + +} + +__global__ void kernel_14(float * var_14_0, float * var_14_1, float * var_14_2, float * var_14_3, float * var_14_4, float * var_14_5, float * var_14_6, float * var_14_7, float * var_14_8, float * var_14_9, float * var_14_10, float * var_14_11, float * var_14_12, float * var_14_13, float * var_14_14, float * var_14_15, float * var_14_16, float * var_14_17, float * var_14_18, float * var_14_19) { + __shared__ float myVar[1024]; + myVar[8] = 20.535383 * myVar[threadIdx.x]; + myVar[1] = 35.714406 * myVar[threadIdx.x]; + myVar[9] = 29.199587 * myVar[threadIdx.x]; + myVar[4] = 33.618211 * myVar[threadIdx.x]; + myVar[8] = 9.594275 * myVar[threadIdx.x]; + myVar[9] = 7.102031 * myVar[threadIdx.x]; + myVar[9] = 5.373745 * myVar[threadIdx.x]; + myVar[6] = 33.548882 * myVar[threadIdx.x]; + myVar[7] = 25.948322 * myVar[threadIdx.x]; + myVar[9] = 19.674437 * myVar[threadIdx.x]; + var_14_0[0] = myVar[0]; + var_14_1[1] = myVar[1]; + var_14_2[2] = myVar[2]; + var_14_3[3] = myVar[3]; + var_14_4[4] = myVar[4]; + var_14_5[5] = myVar[5]; + var_14_6[6] = myVar[6]; + var_14_7[7] = myVar[7]; + var_14_8[8] = myVar[8]; + var_14_9[9] = myVar[9]; + var_14_10[10] = myVar[10]; + var_14_11[11] = myVar[11]; + var_14_12[12] = myVar[12]; + var_14_13[13] = myVar[13]; + var_14_14[14] = myVar[14]; + var_14_15[15] = myVar[15]; + var_14_16[16] = myVar[16]; + var_14_17[17] = myVar[17]; + var_14_18[18] = myVar[18]; + var_14_19[19] = myVar[19]; + +} + +__global__ void kernel_15(float * var_15_0, float * var_15_1, float * var_15_2, float * var_15_3, float * var_15_4, float * var_15_5, float * var_15_6, float * var_15_7, float * var_15_8, float * var_15_9, float * var_15_10, float * var_15_11, float * var_15_12, float * var_15_13, float * var_15_14, float * var_15_15, float * var_15_16, float * var_15_17, float * var_15_18, float * var_15_19) { + __shared__ float myVar[1024]; + myVar[4] = 16.821004 * myVar[threadIdx.x]; + myVar[1] = 40.474564 * myVar[threadIdx.x]; + myVar[0] = 4.896632 * myVar[threadIdx.x]; + myVar[0] = 49.157457 * myVar[threadIdx.x]; + myVar[1] = 43.538341 * myVar[threadIdx.x]; + myVar[5] = 3.270043 * myVar[threadIdx.x]; + myVar[5] = 10.193788 * myVar[threadIdx.x]; + myVar[1] = 2.723051 * myVar[threadIdx.x]; + myVar[3] = 14.915672 * myVar[threadIdx.x]; + myVar[8] = 30.460698 * myVar[threadIdx.x]; + var_15_0[0] = myVar[0]; + var_15_1[1] = myVar[1]; + var_15_2[2] = myVar[2]; + var_15_3[3] = myVar[3]; + var_15_4[4] = myVar[4]; + var_15_5[5] = myVar[5]; + var_15_6[6] = myVar[6]; + var_15_7[7] = myVar[7]; + var_15_8[8] = myVar[8]; + var_15_9[9] = myVar[9]; + var_15_10[10] = myVar[10]; + var_15_11[11] = myVar[11]; + var_15_12[12] = myVar[12]; + var_15_13[13] = myVar[13]; + var_15_14[14] = myVar[14]; + var_15_15[15] = myVar[15]; + var_15_16[16] = myVar[16]; + var_15_17[17] = myVar[17]; + var_15_18[18] = myVar[18]; + var_15_19[19] = myVar[19]; + +} + +__global__ void kernel_16(float * var_16_0, float * var_16_1, float * var_16_2, float * var_16_3, float * var_16_4, float * var_16_5, float * var_16_6, float * var_16_7, float * var_16_8, float * var_16_9, float * var_16_10, float * var_16_11, float * var_16_12, float * var_16_13, float * var_16_14, float * var_16_15, float * var_16_16, float * var_16_17, float * var_16_18, float * var_16_19) { + __shared__ float myVar[1024]; + myVar[1] = 30.125380 * myVar[threadIdx.x]; + myVar[5] = 49.279292 * myVar[threadIdx.x]; + myVar[4] = 40.110493 * myVar[threadIdx.x]; + myVar[6] = 1.210120 * myVar[threadIdx.x]; + myVar[5] = 6.750555 * myVar[threadIdx.x]; + myVar[3] = 41.840500 * myVar[threadIdx.x]; + myVar[8] = 32.901153 * myVar[threadIdx.x]; + myVar[3] = 28.661612 * myVar[threadIdx.x]; + myVar[4] = 2.114233 * myVar[threadIdx.x]; + myVar[0] = 41.587771 * myVar[threadIdx.x]; + var_16_0[0] = myVar[0]; + var_16_1[1] = myVar[1]; + var_16_2[2] = myVar[2]; + var_16_3[3] = myVar[3]; + var_16_4[4] = myVar[4]; + var_16_5[5] = myVar[5]; + var_16_6[6] = myVar[6]; + var_16_7[7] = myVar[7]; + var_16_8[8] = myVar[8]; + var_16_9[9] = myVar[9]; + var_16_10[10] = myVar[10]; + var_16_11[11] = myVar[11]; + var_16_12[12] = myVar[12]; + var_16_13[13] = myVar[13]; + var_16_14[14] = myVar[14]; + var_16_15[15] = myVar[15]; + var_16_16[16] = myVar[16]; + var_16_17[17] = myVar[17]; + var_16_18[18] = myVar[18]; + var_16_19[19] = myVar[19]; + +} + +__global__ void kernel_17(float * var_17_0, float * var_17_1, float * var_17_2, float * var_17_3, float * var_17_4, float * var_17_5, float * var_17_6, float * var_17_7, float * var_17_8, float * var_17_9, float * var_17_10, float * var_17_11, float * var_17_12, float * var_17_13, float * var_17_14, float * var_17_15, float * var_17_16, float * var_17_17, float * var_17_18, float * var_17_19) { + __shared__ float myVar[1024]; + myVar[5] = 42.657163 * myVar[threadIdx.x]; + myVar[7] = 46.068280 * myVar[threadIdx.x]; + myVar[4] = 9.105916 * myVar[threadIdx.x]; + myVar[5] = 30.973747 * myVar[threadIdx.x]; + myVar[2] = 17.915047 * myVar[threadIdx.x]; + myVar[7] = 26.762380 * myVar[threadIdx.x]; + myVar[4] = 33.421623 * myVar[threadIdx.x]; + myVar[1] = 44.503851 * myVar[threadIdx.x]; + myVar[5] = 25.264571 * myVar[threadIdx.x]; + myVar[6] = 33.079366 * myVar[threadIdx.x]; + var_17_0[0] = myVar[0]; + var_17_1[1] = myVar[1]; + var_17_2[2] = myVar[2]; + var_17_3[3] = myVar[3]; + var_17_4[4] = myVar[4]; + var_17_5[5] = myVar[5]; + var_17_6[6] = myVar[6]; + var_17_7[7] = myVar[7]; + var_17_8[8] = myVar[8]; + var_17_9[9] = myVar[9]; + var_17_10[10] = myVar[10]; + var_17_11[11] = myVar[11]; + var_17_12[12] = myVar[12]; + var_17_13[13] = myVar[13]; + var_17_14[14] = myVar[14]; + var_17_15[15] = myVar[15]; + var_17_16[16] = myVar[16]; + var_17_17[17] = myVar[17]; + var_17_18[18] = myVar[18]; + var_17_19[19] = myVar[19]; + +} + +__global__ void kernel_18(float * var_18_0, float * var_18_1, float * var_18_2, float * var_18_3, float * var_18_4, float * var_18_5, float * var_18_6, float * var_18_7, float * var_18_8, float * var_18_9, float * var_18_10, float * var_18_11, float * var_18_12, float * var_18_13, float * var_18_14, float * var_18_15, float * var_18_16, float * var_18_17, float * var_18_18, float * var_18_19) { + __shared__ float myVar[1024]; + myVar[7] = 47.140548 * myVar[threadIdx.x]; + myVar[0] = 46.028238 * myVar[threadIdx.x]; + myVar[7] = 6.932360 * myVar[threadIdx.x]; + myVar[8] = 29.252615 * myVar[threadIdx.x]; + myVar[6] = 8.795276 * myVar[threadIdx.x]; + myVar[1] = 25.034969 * myVar[threadIdx.x]; + myVar[0] = 33.216461 * myVar[threadIdx.x]; + myVar[0] = 11.724631 * myVar[threadIdx.x]; + myVar[0] = 2.454614 * myVar[threadIdx.x]; + myVar[4] = 6.795019 * myVar[threadIdx.x]; + var_18_0[0] = myVar[0]; + var_18_1[1] = myVar[1]; + var_18_2[2] = myVar[2]; + var_18_3[3] = myVar[3]; + var_18_4[4] = myVar[4]; + var_18_5[5] = myVar[5]; + var_18_6[6] = myVar[6]; + var_18_7[7] = myVar[7]; + var_18_8[8] = myVar[8]; + var_18_9[9] = myVar[9]; + var_18_10[10] = myVar[10]; + var_18_11[11] = myVar[11]; + var_18_12[12] = myVar[12]; + var_18_13[13] = myVar[13]; + var_18_14[14] = myVar[14]; + var_18_15[15] = myVar[15]; + var_18_16[16] = myVar[16]; + var_18_17[17] = myVar[17]; + var_18_18[18] = myVar[18]; + var_18_19[19] = myVar[19]; + +} + +__global__ void kernel_19(float * var_19_0, float * var_19_1, float * var_19_2, float * var_19_3, float * var_19_4, float * var_19_5, float * var_19_6, float * var_19_7, float * var_19_8, float * var_19_9, float * var_19_10, float * var_19_11, float * var_19_12, float * var_19_13, float * var_19_14, float * var_19_15, float * var_19_16, float * var_19_17, float * var_19_18, float * var_19_19) { + __shared__ float myVar[1024]; + myVar[5] = 44.514315 * myVar[threadIdx.x]; + myVar[5] = 15.645175 * myVar[threadIdx.x]; + myVar[5] = 31.812628 * myVar[threadIdx.x]; + myVar[0] = 5.528910 * myVar[threadIdx.x]; + myVar[5] = 40.822349 * myVar[threadIdx.x]; + myVar[9] = 19.084764 * myVar[threadIdx.x]; + myVar[4] = 22.711739 * myVar[threadIdx.x]; + myVar[0] = 12.284228 * myVar[threadIdx.x]; + myVar[6] = 8.482777 * myVar[threadIdx.x]; + myVar[7] = 40.246930 * myVar[threadIdx.x]; + var_19_0[0] = myVar[0]; + var_19_1[1] = myVar[1]; + var_19_2[2] = myVar[2]; + var_19_3[3] = myVar[3]; + var_19_4[4] = myVar[4]; + var_19_5[5] = myVar[5]; + var_19_6[6] = myVar[6]; + var_19_7[7] = myVar[7]; + var_19_8[8] = myVar[8]; + var_19_9[9] = myVar[9]; + var_19_10[10] = myVar[10]; + var_19_11[11] = myVar[11]; + var_19_12[12] = myVar[12]; + var_19_13[13] = myVar[13]; + var_19_14[14] = myVar[14]; + var_19_15[15] = myVar[15]; + var_19_16[16] = myVar[16]; + var_19_17[17] = myVar[17]; + var_19_18[18] = myVar[18]; + var_19_19[19] = myVar[19]; + +} + +__global__ void kernel_20(float * var_20_0, float * var_20_1, float * var_20_2, float * var_20_3, float * var_20_4, float * var_20_5, float * var_20_6, float * var_20_7, float * var_20_8, float * var_20_9, float * var_20_10, float * var_20_11, float * var_20_12, float * var_20_13, float * var_20_14, float * var_20_15, float * var_20_16, float * var_20_17, float * var_20_18, float * var_20_19) { + __shared__ float myVar[1024]; + myVar[3] = 8.920762 * myVar[threadIdx.x]; + myVar[7] = 37.353696 * myVar[threadIdx.x]; + myVar[3] = 32.099913 * myVar[threadIdx.x]; + myVar[8] = 24.096614 * myVar[threadIdx.x]; + myVar[9] = 14.495044 * myVar[threadIdx.x]; + myVar[6] = 35.974989 * myVar[threadIdx.x]; + myVar[7] = 21.908123 * myVar[threadIdx.x]; + myVar[0] = 41.261727 * myVar[threadIdx.x]; + myVar[4] = 21.221434 * myVar[threadIdx.x]; + myVar[5] = 0.046441 * myVar[threadIdx.x]; + var_20_0[0] = myVar[0]; + var_20_1[1] = myVar[1]; + var_20_2[2] = myVar[2]; + var_20_3[3] = myVar[3]; + var_20_4[4] = myVar[4]; + var_20_5[5] = myVar[5]; + var_20_6[6] = myVar[6]; + var_20_7[7] = myVar[7]; + var_20_8[8] = myVar[8]; + var_20_9[9] = myVar[9]; + var_20_10[10] = myVar[10]; + var_20_11[11] = myVar[11]; + var_20_12[12] = myVar[12]; + var_20_13[13] = myVar[13]; + var_20_14[14] = myVar[14]; + var_20_15[15] = myVar[15]; + var_20_16[16] = myVar[16]; + var_20_17[17] = myVar[17]; + var_20_18[18] = myVar[18]; + var_20_19[19] = myVar[19]; + +} + +__global__ void kernel_21(float * var_21_0, float * var_21_1, float * var_21_2, float * var_21_3, float * var_21_4, float * var_21_5, float * var_21_6, float * var_21_7, float * var_21_8, float * var_21_9, float * var_21_10, float * var_21_11, float * var_21_12, float * var_21_13, float * var_21_14, float * var_21_15, float * var_21_16, float * var_21_17, float * var_21_18, float * var_21_19) { + __shared__ float myVar[1024]; + myVar[8] = 22.112567 * myVar[threadIdx.x]; + myVar[3] = 27.653067 * myVar[threadIdx.x]; + myVar[6] = 16.924127 * myVar[threadIdx.x]; + myVar[1] = 33.412665 * myVar[threadIdx.x]; + myVar[7] = 2.221997 * myVar[threadIdx.x]; + myVar[7] = 45.256766 * myVar[threadIdx.x]; + myVar[6] = 37.572069 * myVar[threadIdx.x]; + myVar[6] = 25.978406 * myVar[threadIdx.x]; + myVar[5] = 29.277489 * myVar[threadIdx.x]; + myVar[0] = 46.767500 * myVar[threadIdx.x]; + var_21_0[0] = myVar[0]; + var_21_1[1] = myVar[1]; + var_21_2[2] = myVar[2]; + var_21_3[3] = myVar[3]; + var_21_4[4] = myVar[4]; + var_21_5[5] = myVar[5]; + var_21_6[6] = myVar[6]; + var_21_7[7] = myVar[7]; + var_21_8[8] = myVar[8]; + var_21_9[9] = myVar[9]; + var_21_10[10] = myVar[10]; + var_21_11[11] = myVar[11]; + var_21_12[12] = myVar[12]; + var_21_13[13] = myVar[13]; + var_21_14[14] = myVar[14]; + var_21_15[15] = myVar[15]; + var_21_16[16] = myVar[16]; + var_21_17[17] = myVar[17]; + var_21_18[18] = myVar[18]; + var_21_19[19] = myVar[19]; + +} + +__global__ void kernel_22(float * var_22_0, float * var_22_1, float * var_22_2, float * var_22_3, float * var_22_4, float * var_22_5, float * var_22_6, float * var_22_7, float * var_22_8, float * var_22_9, float * var_22_10, float * var_22_11, float * var_22_12, float * var_22_13, float * var_22_14, float * var_22_15, float * var_22_16, float * var_22_17, float * var_22_18, float * var_22_19) { + __shared__ float myVar[1024]; + myVar[4] = 31.285070 * myVar[threadIdx.x]; + myVar[7] = 0.863628 * myVar[threadIdx.x]; + myVar[8] = 25.720817 * myVar[threadIdx.x]; + myVar[0] = 12.004407 * myVar[threadIdx.x]; + myVar[0] = 45.033315 * myVar[threadIdx.x]; + myVar[8] = 40.415036 * myVar[threadIdx.x]; + myVar[4] = 25.509417 * myVar[threadIdx.x]; + myVar[6] = 34.767809 * myVar[threadIdx.x]; + myVar[0] = 12.637889 * myVar[threadIdx.x]; + myVar[6] = 10.133237 * myVar[threadIdx.x]; + var_22_0[0] = myVar[0]; + var_22_1[1] = myVar[1]; + var_22_2[2] = myVar[2]; + var_22_3[3] = myVar[3]; + var_22_4[4] = myVar[4]; + var_22_5[5] = myVar[5]; + var_22_6[6] = myVar[6]; + var_22_7[7] = myVar[7]; + var_22_8[8] = myVar[8]; + var_22_9[9] = myVar[9]; + var_22_10[10] = myVar[10]; + var_22_11[11] = myVar[11]; + var_22_12[12] = myVar[12]; + var_22_13[13] = myVar[13]; + var_22_14[14] = myVar[14]; + var_22_15[15] = myVar[15]; + var_22_16[16] = myVar[16]; + var_22_17[17] = myVar[17]; + var_22_18[18] = myVar[18]; + var_22_19[19] = myVar[19]; + +} + +__global__ void kernel_23(float * var_23_0, float * var_23_1, float * var_23_2, float * var_23_3, float * var_23_4, float * var_23_5, float * var_23_6, float * var_23_7, float * var_23_8, float * var_23_9, float * var_23_10, float * var_23_11, float * var_23_12, float * var_23_13, float * var_23_14, float * var_23_15, float * var_23_16, float * var_23_17, float * var_23_18, float * var_23_19) { + __shared__ float myVar[1024]; + myVar[5] = 21.524582 * myVar[threadIdx.x]; + myVar[6] = 29.706542 * myVar[threadIdx.x]; + myVar[6] = 31.447616 * myVar[threadIdx.x]; + myVar[7] = 32.046018 * myVar[threadIdx.x]; + myVar[1] = 31.068229 * myVar[threadIdx.x]; + myVar[7] = 5.766474 * myVar[threadIdx.x]; + myVar[7] = 24.443588 * myVar[threadIdx.x]; + myVar[3] = 40.997058 * myVar[threadIdx.x]; + myVar[0] = 22.817930 * myVar[threadIdx.x]; + myVar[1] = 8.522397 * myVar[threadIdx.x]; + var_23_0[0] = myVar[0]; + var_23_1[1] = myVar[1]; + var_23_2[2] = myVar[2]; + var_23_3[3] = myVar[3]; + var_23_4[4] = myVar[4]; + var_23_5[5] = myVar[5]; + var_23_6[6] = myVar[6]; + var_23_7[7] = myVar[7]; + var_23_8[8] = myVar[8]; + var_23_9[9] = myVar[9]; + var_23_10[10] = myVar[10]; + var_23_11[11] = myVar[11]; + var_23_12[12] = myVar[12]; + var_23_13[13] = myVar[13]; + var_23_14[14] = myVar[14]; + var_23_15[15] = myVar[15]; + var_23_16[16] = myVar[16]; + var_23_17[17] = myVar[17]; + var_23_18[18] = myVar[18]; + var_23_19[19] = myVar[19]; + +} + +__global__ void kernel_24(float * var_24_0, float * var_24_1, float * var_24_2, float * var_24_3, float * var_24_4, float * var_24_5, float * var_24_6, float * var_24_7, float * var_24_8, float * var_24_9, float * var_24_10, float * var_24_11, float * var_24_12, float * var_24_13, float * var_24_14, float * var_24_15, float * var_24_16, float * var_24_17, float * var_24_18, float * var_24_19) { + __shared__ float myVar[1024]; + myVar[2] = 17.014051 * myVar[threadIdx.x]; + myVar[0] = 3.181015 * myVar[threadIdx.x]; + myVar[3] = 29.333601 * myVar[threadIdx.x]; + myVar[1] = 39.439184 * myVar[threadIdx.x]; + myVar[7] = 25.280476 * myVar[threadIdx.x]; + myVar[3] = 19.974617 * myVar[threadIdx.x]; + myVar[0] = 38.258641 * myVar[threadIdx.x]; + myVar[2] = 10.066041 * myVar[threadIdx.x]; + myVar[3] = 31.378324 * myVar[threadIdx.x]; + myVar[3] = 16.652854 * myVar[threadIdx.x]; + var_24_0[0] = myVar[0]; + var_24_1[1] = myVar[1]; + var_24_2[2] = myVar[2]; + var_24_3[3] = myVar[3]; + var_24_4[4] = myVar[4]; + var_24_5[5] = myVar[5]; + var_24_6[6] = myVar[6]; + var_24_7[7] = myVar[7]; + var_24_8[8] = myVar[8]; + var_24_9[9] = myVar[9]; + var_24_10[10] = myVar[10]; + var_24_11[11] = myVar[11]; + var_24_12[12] = myVar[12]; + var_24_13[13] = myVar[13]; + var_24_14[14] = myVar[14]; + var_24_15[15] = myVar[15]; + var_24_16[16] = myVar[16]; + var_24_17[17] = myVar[17]; + var_24_18[18] = myVar[18]; + var_24_19[19] = myVar[19]; + +} + +__global__ void kernel_25(float * var_25_0, float * var_25_1, float * var_25_2, float * var_25_3, float * var_25_4, float * var_25_5, float * var_25_6, float * var_25_7, float * var_25_8, float * var_25_9, float * var_25_10, float * var_25_11, float * var_25_12, float * var_25_13, float * var_25_14, float * var_25_15, float * var_25_16, float * var_25_17, float * var_25_18, float * var_25_19) { + __shared__ float myVar[1024]; + myVar[8] = 7.517236 * myVar[threadIdx.x]; + myVar[6] = 28.264222 * myVar[threadIdx.x]; + myVar[8] = 4.411520 * myVar[threadIdx.x]; + myVar[1] = 7.778072 * myVar[threadIdx.x]; + myVar[5] = 32.653238 * myVar[threadIdx.x]; + myVar[1] = 15.025972 * myVar[threadIdx.x]; + myVar[3] = 27.817416 * myVar[threadIdx.x]; + myVar[2] = 30.711862 * myVar[threadIdx.x]; + myVar[9] = 34.396261 * myVar[threadIdx.x]; + myVar[7] = 44.214172 * myVar[threadIdx.x]; + var_25_0[0] = myVar[0]; + var_25_1[1] = myVar[1]; + var_25_2[2] = myVar[2]; + var_25_3[3] = myVar[3]; + var_25_4[4] = myVar[4]; + var_25_5[5] = myVar[5]; + var_25_6[6] = myVar[6]; + var_25_7[7] = myVar[7]; + var_25_8[8] = myVar[8]; + var_25_9[9] = myVar[9]; + var_25_10[10] = myVar[10]; + var_25_11[11] = myVar[11]; + var_25_12[12] = myVar[12]; + var_25_13[13] = myVar[13]; + var_25_14[14] = myVar[14]; + var_25_15[15] = myVar[15]; + var_25_16[16] = myVar[16]; + var_25_17[17] = myVar[17]; + var_25_18[18] = myVar[18]; + var_25_19[19] = myVar[19]; + +} + +__global__ void kernel_26(float * var_26_0, float * var_26_1, float * var_26_2, float * var_26_3, float * var_26_4, float * var_26_5, float * var_26_6, float * var_26_7, float * var_26_8, float * var_26_9, float * var_26_10, float * var_26_11, float * var_26_12, float * var_26_13, float * var_26_14, float * var_26_15, float * var_26_16, float * var_26_17, float * var_26_18, float * var_26_19) { + __shared__ float myVar[1024]; + myVar[4] = 48.641031 * myVar[threadIdx.x]; + myVar[9] = 43.952846 * myVar[threadIdx.x]; + myVar[8] = 26.538523 * myVar[threadIdx.x]; + myVar[2] = 8.435853 * myVar[threadIdx.x]; + myVar[1] = 36.593866 * myVar[threadIdx.x]; + myVar[5] = 17.569830 * myVar[threadIdx.x]; + myVar[6] = 42.516282 * myVar[threadIdx.x]; + myVar[4] = 47.853700 * myVar[threadIdx.x]; + myVar[5] = 41.775186 * myVar[threadIdx.x]; + myVar[4] = 29.159559 * myVar[threadIdx.x]; + var_26_0[0] = myVar[0]; + var_26_1[1] = myVar[1]; + var_26_2[2] = myVar[2]; + var_26_3[3] = myVar[3]; + var_26_4[4] = myVar[4]; + var_26_5[5] = myVar[5]; + var_26_6[6] = myVar[6]; + var_26_7[7] = myVar[7]; + var_26_8[8] = myVar[8]; + var_26_9[9] = myVar[9]; + var_26_10[10] = myVar[10]; + var_26_11[11] = myVar[11]; + var_26_12[12] = myVar[12]; + var_26_13[13] = myVar[13]; + var_26_14[14] = myVar[14]; + var_26_15[15] = myVar[15]; + var_26_16[16] = myVar[16]; + var_26_17[17] = myVar[17]; + var_26_18[18] = myVar[18]; + var_26_19[19] = myVar[19]; + +} + +__global__ void kernel_27(float * var_27_0, float * var_27_1, float * var_27_2, float * var_27_3, float * var_27_4, float * var_27_5, float * var_27_6, float * var_27_7, float * var_27_8, float * var_27_9, float * var_27_10, float * var_27_11, float * var_27_12, float * var_27_13, float * var_27_14, float * var_27_15, float * var_27_16, float * var_27_17, float * var_27_18, float * var_27_19) { + __shared__ float myVar[1024]; + myVar[9] = 44.593467 * myVar[threadIdx.x]; + myVar[5] = 4.774136 * myVar[threadIdx.x]; + myVar[5] = 0.608903 * myVar[threadIdx.x]; + myVar[5] = 27.921276 * myVar[threadIdx.x]; + myVar[6] = 23.472995 * myVar[threadIdx.x]; + myVar[4] = 45.549882 * myVar[threadIdx.x]; + myVar[8] = 30.662462 * myVar[threadIdx.x]; + myVar[3] = 13.045959 * myVar[threadIdx.x]; + myVar[2] = 45.326496 * myVar[threadIdx.x]; + myVar[2] = 30.163615 * myVar[threadIdx.x]; + var_27_0[0] = myVar[0]; + var_27_1[1] = myVar[1]; + var_27_2[2] = myVar[2]; + var_27_3[3] = myVar[3]; + var_27_4[4] = myVar[4]; + var_27_5[5] = myVar[5]; + var_27_6[6] = myVar[6]; + var_27_7[7] = myVar[7]; + var_27_8[8] = myVar[8]; + var_27_9[9] = myVar[9]; + var_27_10[10] = myVar[10]; + var_27_11[11] = myVar[11]; + var_27_12[12] = myVar[12]; + var_27_13[13] = myVar[13]; + var_27_14[14] = myVar[14]; + var_27_15[15] = myVar[15]; + var_27_16[16] = myVar[16]; + var_27_17[17] = myVar[17]; + var_27_18[18] = myVar[18]; + var_27_19[19] = myVar[19]; + +} + +__global__ void kernel_28(float * var_28_0, float * var_28_1, float * var_28_2, float * var_28_3, float * var_28_4, float * var_28_5, float * var_28_6, float * var_28_7, float * var_28_8, float * var_28_9, float * var_28_10, float * var_28_11, float * var_28_12, float * var_28_13, float * var_28_14, float * var_28_15, float * var_28_16, float * var_28_17, float * var_28_18, float * var_28_19) { + __shared__ float myVar[1024]; + myVar[4] = 21.657435 * myVar[threadIdx.x]; + myVar[9] = 29.884629 * myVar[threadIdx.x]; + myVar[8] = 21.673294 * myVar[threadIdx.x]; + myVar[6] = 3.731673 * myVar[threadIdx.x]; + myVar[2] = 22.881731 * myVar[threadIdx.x]; + myVar[9] = 19.223812 * myVar[threadIdx.x]; + myVar[9] = 36.169111 * myVar[threadIdx.x]; + myVar[8] = 34.115668 * myVar[threadIdx.x]; + myVar[3] = 4.904825 * myVar[threadIdx.x]; + myVar[2] = 0.995835 * myVar[threadIdx.x]; + var_28_0[0] = myVar[0]; + var_28_1[1] = myVar[1]; + var_28_2[2] = myVar[2]; + var_28_3[3] = myVar[3]; + var_28_4[4] = myVar[4]; + var_28_5[5] = myVar[5]; + var_28_6[6] = myVar[6]; + var_28_7[7] = myVar[7]; + var_28_8[8] = myVar[8]; + var_28_9[9] = myVar[9]; + var_28_10[10] = myVar[10]; + var_28_11[11] = myVar[11]; + var_28_12[12] = myVar[12]; + var_28_13[13] = myVar[13]; + var_28_14[14] = myVar[14]; + var_28_15[15] = myVar[15]; + var_28_16[16] = myVar[16]; + var_28_17[17] = myVar[17]; + var_28_18[18] = myVar[18]; + var_28_19[19] = myVar[19]; + +} + +__global__ void kernel_29(float * var_29_0, float * var_29_1, float * var_29_2, float * var_29_3, float * var_29_4, float * var_29_5, float * var_29_6, float * var_29_7, float * var_29_8, float * var_29_9, float * var_29_10, float * var_29_11, float * var_29_12, float * var_29_13, float * var_29_14, float * var_29_15, float * var_29_16, float * var_29_17, float * var_29_18, float * var_29_19) { + __shared__ float myVar[1024]; + myVar[7] = 25.151348 * myVar[threadIdx.x]; + myVar[3] = 5.073383 * myVar[threadIdx.x]; + myVar[2] = 49.057405 * myVar[threadIdx.x]; + myVar[5] = 10.375361 * myVar[threadIdx.x]; + myVar[5] = 34.815777 * myVar[threadIdx.x]; + myVar[6] = 19.558450 * myVar[threadIdx.x]; + myVar[4] = 23.350865 * myVar[threadIdx.x]; + myVar[9] = 5.091217 * myVar[threadIdx.x]; + myVar[0] = 22.062347 * myVar[threadIdx.x]; + myVar[7] = 39.179353 * myVar[threadIdx.x]; + var_29_0[0] = myVar[0]; + var_29_1[1] = myVar[1]; + var_29_2[2] = myVar[2]; + var_29_3[3] = myVar[3]; + var_29_4[4] = myVar[4]; + var_29_5[5] = myVar[5]; + var_29_6[6] = myVar[6]; + var_29_7[7] = myVar[7]; + var_29_8[8] = myVar[8]; + var_29_9[9] = myVar[9]; + var_29_10[10] = myVar[10]; + var_29_11[11] = myVar[11]; + var_29_12[12] = myVar[12]; + var_29_13[13] = myVar[13]; + var_29_14[14] = myVar[14]; + var_29_15[15] = myVar[15]; + var_29_16[16] = myVar[16]; + var_29_17[17] = myVar[17]; + var_29_18[18] = myVar[18]; + var_29_19[19] = myVar[19]; + +} + +__global__ void kernel_30(float * var_30_0, float * var_30_1, float * var_30_2, float * var_30_3, float * var_30_4, float * var_30_5, float * var_30_6, float * var_30_7, float * var_30_8, float * var_30_9, float * var_30_10, float * var_30_11, float * var_30_12, float * var_30_13, float * var_30_14, float * var_30_15, float * var_30_16, float * var_30_17, float * var_30_18, float * var_30_19) { + __shared__ float myVar[1024]; + myVar[5] = 36.046011 * myVar[threadIdx.x]; + myVar[3] = 14.885873 * myVar[threadIdx.x]; + myVar[7] = 38.248691 * myVar[threadIdx.x]; + myVar[1] = 43.093572 * myVar[threadIdx.x]; + myVar[5] = 19.913632 * myVar[threadIdx.x]; + myVar[6] = 6.243649 * myVar[threadIdx.x]; + myVar[7] = 23.822577 * myVar[threadIdx.x]; + myVar[7] = 32.748343 * myVar[threadIdx.x]; + myVar[1] = 0.240827 * myVar[threadIdx.x]; + myVar[2] = 12.217483 * myVar[threadIdx.x]; + var_30_0[0] = myVar[0]; + var_30_1[1] = myVar[1]; + var_30_2[2] = myVar[2]; + var_30_3[3] = myVar[3]; + var_30_4[4] = myVar[4]; + var_30_5[5] = myVar[5]; + var_30_6[6] = myVar[6]; + var_30_7[7] = myVar[7]; + var_30_8[8] = myVar[8]; + var_30_9[9] = myVar[9]; + var_30_10[10] = myVar[10]; + var_30_11[11] = myVar[11]; + var_30_12[12] = myVar[12]; + var_30_13[13] = myVar[13]; + var_30_14[14] = myVar[14]; + var_30_15[15] = myVar[15]; + var_30_16[16] = myVar[16]; + var_30_17[17] = myVar[17]; + var_30_18[18] = myVar[18]; + var_30_19[19] = myVar[19]; + +} + +__global__ void kernel_31(float * var_31_0, float * var_31_1, float * var_31_2, float * var_31_3, float * var_31_4, float * var_31_5, float * var_31_6, float * var_31_7, float * var_31_8, float * var_31_9, float * var_31_10, float * var_31_11, float * var_31_12, float * var_31_13, float * var_31_14, float * var_31_15, float * var_31_16, float * var_31_17, float * var_31_18, float * var_31_19) { + __shared__ float myVar[1024]; + myVar[1] = 5.874735 * myVar[threadIdx.x]; + myVar[3] = 37.347456 * myVar[threadIdx.x]; + myVar[2] = 37.747604 * myVar[threadIdx.x]; + myVar[4] = 31.348833 * myVar[threadIdx.x]; + myVar[2] = 34.267739 * myVar[threadIdx.x]; + myVar[7] = 28.779658 * myVar[threadIdx.x]; + myVar[7] = 38.259609 * myVar[threadIdx.x]; + myVar[4] = 40.641591 * myVar[threadIdx.x]; + myVar[8] = 25.630688 * myVar[threadIdx.x]; + myVar[2] = 8.221034 * myVar[threadIdx.x]; + var_31_0[0] = myVar[0]; + var_31_1[1] = myVar[1]; + var_31_2[2] = myVar[2]; + var_31_3[3] = myVar[3]; + var_31_4[4] = myVar[4]; + var_31_5[5] = myVar[5]; + var_31_6[6] = myVar[6]; + var_31_7[7] = myVar[7]; + var_31_8[8] = myVar[8]; + var_31_9[9] = myVar[9]; + var_31_10[10] = myVar[10]; + var_31_11[11] = myVar[11]; + var_31_12[12] = myVar[12]; + var_31_13[13] = myVar[13]; + var_31_14[14] = myVar[14]; + var_31_15[15] = myVar[15]; + var_31_16[16] = myVar[16]; + var_31_17[17] = myVar[17]; + var_31_18[18] = myVar[18]; + var_31_19[19] = myVar[19]; + +} + +__global__ void kernel_32(float * var_32_0, float * var_32_1, float * var_32_2, float * var_32_3, float * var_32_4, float * var_32_5, float * var_32_6, float * var_32_7, float * var_32_8, float * var_32_9, float * var_32_10, float * var_32_11, float * var_32_12, float * var_32_13, float * var_32_14, float * var_32_15, float * var_32_16, float * var_32_17, float * var_32_18, float * var_32_19) { + __shared__ float myVar[1024]; + myVar[3] = 37.831150 * myVar[threadIdx.x]; + myVar[5] = 28.793004 * myVar[threadIdx.x]; + myVar[4] = 19.871804 * myVar[threadIdx.x]; + myVar[2] = 39.019470 * myVar[threadIdx.x]; + myVar[0] = 26.222847 * myVar[threadIdx.x]; + myVar[2] = 12.296851 * myVar[threadIdx.x]; + myVar[2] = 32.653467 * myVar[threadIdx.x]; + myVar[6] = 21.242219 * myVar[threadIdx.x]; + myVar[3] = 47.590289 * myVar[threadIdx.x]; + myVar[3] = 39.070860 * myVar[threadIdx.x]; + var_32_0[0] = myVar[0]; + var_32_1[1] = myVar[1]; + var_32_2[2] = myVar[2]; + var_32_3[3] = myVar[3]; + var_32_4[4] = myVar[4]; + var_32_5[5] = myVar[5]; + var_32_6[6] = myVar[6]; + var_32_7[7] = myVar[7]; + var_32_8[8] = myVar[8]; + var_32_9[9] = myVar[9]; + var_32_10[10] = myVar[10]; + var_32_11[11] = myVar[11]; + var_32_12[12] = myVar[12]; + var_32_13[13] = myVar[13]; + var_32_14[14] = myVar[14]; + var_32_15[15] = myVar[15]; + var_32_16[16] = myVar[16]; + var_32_17[17] = myVar[17]; + var_32_18[18] = myVar[18]; + var_32_19[19] = myVar[19]; + +} + +__global__ void kernel_33(float * var_33_0, float * var_33_1, float * var_33_2, float * var_33_3, float * var_33_4, float * var_33_5, float * var_33_6, float * var_33_7, float * var_33_8, float * var_33_9, float * var_33_10, float * var_33_11, float * var_33_12, float * var_33_13, float * var_33_14, float * var_33_15, float * var_33_16, float * var_33_17, float * var_33_18, float * var_33_19) { + __shared__ float myVar[1024]; + myVar[5] = 38.030299 * myVar[threadIdx.x]; + myVar[5] = 44.122182 * myVar[threadIdx.x]; + myVar[3] = 34.982739 * myVar[threadIdx.x]; + myVar[7] = 31.233982 * myVar[threadIdx.x]; + myVar[9] = 41.721021 * myVar[threadIdx.x]; + myVar[4] = 46.965980 * myVar[threadIdx.x]; + myVar[4] = 35.483172 * myVar[threadIdx.x]; + myVar[0] = 20.314613 * myVar[threadIdx.x]; + myVar[0] = 23.829995 * myVar[threadIdx.x]; + myVar[0] = 34.938981 * myVar[threadIdx.x]; + var_33_0[0] = myVar[0]; + var_33_1[1] = myVar[1]; + var_33_2[2] = myVar[2]; + var_33_3[3] = myVar[3]; + var_33_4[4] = myVar[4]; + var_33_5[5] = myVar[5]; + var_33_6[6] = myVar[6]; + var_33_7[7] = myVar[7]; + var_33_8[8] = myVar[8]; + var_33_9[9] = myVar[9]; + var_33_10[10] = myVar[10]; + var_33_11[11] = myVar[11]; + var_33_12[12] = myVar[12]; + var_33_13[13] = myVar[13]; + var_33_14[14] = myVar[14]; + var_33_15[15] = myVar[15]; + var_33_16[16] = myVar[16]; + var_33_17[17] = myVar[17]; + var_33_18[18] = myVar[18]; + var_33_19[19] = myVar[19]; + +} + +__global__ void kernel_34(float * var_34_0, float * var_34_1, float * var_34_2, float * var_34_3, float * var_34_4, float * var_34_5, float * var_34_6, float * var_34_7, float * var_34_8, float * var_34_9, float * var_34_10, float * var_34_11, float * var_34_12, float * var_34_13, float * var_34_14, float * var_34_15, float * var_34_16, float * var_34_17, float * var_34_18, float * var_34_19) { + __shared__ float myVar[1024]; + myVar[1] = 4.848555 * myVar[threadIdx.x]; + myVar[9] = 45.594005 * myVar[threadIdx.x]; + myVar[4] = 5.275042 * myVar[threadIdx.x]; + myVar[6] = 47.467082 * myVar[threadIdx.x]; + myVar[0] = 43.599883 * myVar[threadIdx.x]; + myVar[0] = 22.543226 * myVar[threadIdx.x]; + myVar[3] = 10.500562 * myVar[threadIdx.x]; + myVar[9] = 7.076448 * myVar[threadIdx.x]; + myVar[6] = 37.155668 * myVar[threadIdx.x]; + myVar[6] = 39.351688 * myVar[threadIdx.x]; + var_34_0[0] = myVar[0]; + var_34_1[1] = myVar[1]; + var_34_2[2] = myVar[2]; + var_34_3[3] = myVar[3]; + var_34_4[4] = myVar[4]; + var_34_5[5] = myVar[5]; + var_34_6[6] = myVar[6]; + var_34_7[7] = myVar[7]; + var_34_8[8] = myVar[8]; + var_34_9[9] = myVar[9]; + var_34_10[10] = myVar[10]; + var_34_11[11] = myVar[11]; + var_34_12[12] = myVar[12]; + var_34_13[13] = myVar[13]; + var_34_14[14] = myVar[14]; + var_34_15[15] = myVar[15]; + var_34_16[16] = myVar[16]; + var_34_17[17] = myVar[17]; + var_34_18[18] = myVar[18]; + var_34_19[19] = myVar[19]; + +} + +__global__ void kernel_35(float * var_35_0, float * var_35_1, float * var_35_2, float * var_35_3, float * var_35_4, float * var_35_5, float * var_35_6, float * var_35_7, float * var_35_8, float * var_35_9, float * var_35_10, float * var_35_11, float * var_35_12, float * var_35_13, float * var_35_14, float * var_35_15, float * var_35_16, float * var_35_17, float * var_35_18, float * var_35_19) { + __shared__ float myVar[1024]; + myVar[2] = 20.230487 * myVar[threadIdx.x]; + myVar[5] = 22.713707 * myVar[threadIdx.x]; + myVar[7] = 35.011226 * myVar[threadIdx.x]; + myVar[8] = 4.429307 * myVar[threadIdx.x]; + myVar[4] = 32.732229 * myVar[threadIdx.x]; + myVar[7] = 43.417915 * myVar[threadIdx.x]; + myVar[7] = 8.217305 * myVar[threadIdx.x]; + myVar[1] = 39.014612 * myVar[threadIdx.x]; + myVar[0] = 14.273283 * myVar[threadIdx.x]; + myVar[9] = 11.301961 * myVar[threadIdx.x]; + var_35_0[0] = myVar[0]; + var_35_1[1] = myVar[1]; + var_35_2[2] = myVar[2]; + var_35_3[3] = myVar[3]; + var_35_4[4] = myVar[4]; + var_35_5[5] = myVar[5]; + var_35_6[6] = myVar[6]; + var_35_7[7] = myVar[7]; + var_35_8[8] = myVar[8]; + var_35_9[9] = myVar[9]; + var_35_10[10] = myVar[10]; + var_35_11[11] = myVar[11]; + var_35_12[12] = myVar[12]; + var_35_13[13] = myVar[13]; + var_35_14[14] = myVar[14]; + var_35_15[15] = myVar[15]; + var_35_16[16] = myVar[16]; + var_35_17[17] = myVar[17]; + var_35_18[18] = myVar[18]; + var_35_19[19] = myVar[19]; + +} + +__global__ void kernel_36(float * var_36_0, float * var_36_1, float * var_36_2, float * var_36_3, float * var_36_4, float * var_36_5, float * var_36_6, float * var_36_7, float * var_36_8, float * var_36_9, float * var_36_10, float * var_36_11, float * var_36_12, float * var_36_13, float * var_36_14, float * var_36_15, float * var_36_16, float * var_36_17, float * var_36_18, float * var_36_19) { + __shared__ float myVar[1024]; + myVar[5] = 45.179389 * myVar[threadIdx.x]; + myVar[2] = 20.411022 * myVar[threadIdx.x]; + myVar[3] = 10.367868 * myVar[threadIdx.x]; + myVar[5] = 41.563758 * myVar[threadIdx.x]; + myVar[0] = 8.981381 * myVar[threadIdx.x]; + myVar[1] = 14.762939 * myVar[threadIdx.x]; + myVar[9] = 31.785718 * myVar[threadIdx.x]; + myVar[9] = 12.968729 * myVar[threadIdx.x]; + myVar[2] = 0.609264 * myVar[threadIdx.x]; + myVar[6] = 44.362367 * myVar[threadIdx.x]; + var_36_0[0] = myVar[0]; + var_36_1[1] = myVar[1]; + var_36_2[2] = myVar[2]; + var_36_3[3] = myVar[3]; + var_36_4[4] = myVar[4]; + var_36_5[5] = myVar[5]; + var_36_6[6] = myVar[6]; + var_36_7[7] = myVar[7]; + var_36_8[8] = myVar[8]; + var_36_9[9] = myVar[9]; + var_36_10[10] = myVar[10]; + var_36_11[11] = myVar[11]; + var_36_12[12] = myVar[12]; + var_36_13[13] = myVar[13]; + var_36_14[14] = myVar[14]; + var_36_15[15] = myVar[15]; + var_36_16[16] = myVar[16]; + var_36_17[17] = myVar[17]; + var_36_18[18] = myVar[18]; + var_36_19[19] = myVar[19]; + +} + +__global__ void kernel_37(float * var_37_0, float * var_37_1, float * var_37_2, float * var_37_3, float * var_37_4, float * var_37_5, float * var_37_6, float * var_37_7, float * var_37_8, float * var_37_9, float * var_37_10, float * var_37_11, float * var_37_12, float * var_37_13, float * var_37_14, float * var_37_15, float * var_37_16, float * var_37_17, float * var_37_18, float * var_37_19) { + __shared__ float myVar[1024]; + myVar[3] = 35.093701 * myVar[threadIdx.x]; + myVar[2] = 42.819633 * myVar[threadIdx.x]; + myVar[7] = 14.836877 * myVar[threadIdx.x]; + myVar[8] = 25.653325 * myVar[threadIdx.x]; + myVar[4] = 26.962135 * myVar[threadIdx.x]; + myVar[5] = 39.779576 * myVar[threadIdx.x]; + myVar[1] = 39.045629 * myVar[threadIdx.x]; + myVar[1] = 12.076513 * myVar[threadIdx.x]; + myVar[3] = 49.070441 * myVar[threadIdx.x]; + myVar[5] = 44.290816 * myVar[threadIdx.x]; + var_37_0[0] = myVar[0]; + var_37_1[1] = myVar[1]; + var_37_2[2] = myVar[2]; + var_37_3[3] = myVar[3]; + var_37_4[4] = myVar[4]; + var_37_5[5] = myVar[5]; + var_37_6[6] = myVar[6]; + var_37_7[7] = myVar[7]; + var_37_8[8] = myVar[8]; + var_37_9[9] = myVar[9]; + var_37_10[10] = myVar[10]; + var_37_11[11] = myVar[11]; + var_37_12[12] = myVar[12]; + var_37_13[13] = myVar[13]; + var_37_14[14] = myVar[14]; + var_37_15[15] = myVar[15]; + var_37_16[16] = myVar[16]; + var_37_17[17] = myVar[17]; + var_37_18[18] = myVar[18]; + var_37_19[19] = myVar[19]; + +} + +__global__ void kernel_38(float * var_38_0, float * var_38_1, float * var_38_2, float * var_38_3, float * var_38_4, float * var_38_5, float * var_38_6, float * var_38_7, float * var_38_8, float * var_38_9, float * var_38_10, float * var_38_11, float * var_38_12, float * var_38_13, float * var_38_14, float * var_38_15, float * var_38_16, float * var_38_17, float * var_38_18, float * var_38_19) { + __shared__ float myVar[1024]; + myVar[8] = 16.950942 * myVar[threadIdx.x]; + myVar[6] = 16.723500 * myVar[threadIdx.x]; + myVar[1] = 0.501504 * myVar[threadIdx.x]; + myVar[8] = 15.969000 * myVar[threadIdx.x]; + myVar[9] = 21.267720 * myVar[threadIdx.x]; + myVar[4] = 49.429729 * myVar[threadIdx.x]; + myVar[1] = 19.745463 * myVar[threadIdx.x]; + myVar[0] = 6.291363 * myVar[threadIdx.x]; + myVar[5] = 1.115146 * myVar[threadIdx.x]; + myVar[0] = 30.363812 * myVar[threadIdx.x]; + var_38_0[0] = myVar[0]; + var_38_1[1] = myVar[1]; + var_38_2[2] = myVar[2]; + var_38_3[3] = myVar[3]; + var_38_4[4] = myVar[4]; + var_38_5[5] = myVar[5]; + var_38_6[6] = myVar[6]; + var_38_7[7] = myVar[7]; + var_38_8[8] = myVar[8]; + var_38_9[9] = myVar[9]; + var_38_10[10] = myVar[10]; + var_38_11[11] = myVar[11]; + var_38_12[12] = myVar[12]; + var_38_13[13] = myVar[13]; + var_38_14[14] = myVar[14]; + var_38_15[15] = myVar[15]; + var_38_16[16] = myVar[16]; + var_38_17[17] = myVar[17]; + var_38_18[18] = myVar[18]; + var_38_19[19] = myVar[19]; + +} + +__global__ void kernel_39(float * var_39_0, float * var_39_1, float * var_39_2, float * var_39_3, float * var_39_4, float * var_39_5, float * var_39_6, float * var_39_7, float * var_39_8, float * var_39_9, float * var_39_10, float * var_39_11, float * var_39_12, float * var_39_13, float * var_39_14, float * var_39_15, float * var_39_16, float * var_39_17, float * var_39_18, float * var_39_19) { + __shared__ float myVar[1024]; + myVar[4] = 48.490515 * myVar[threadIdx.x]; + myVar[9] = 12.608231 * myVar[threadIdx.x]; + myVar[2] = 35.157848 * myVar[threadIdx.x]; + myVar[0] = 1.188302 * myVar[threadIdx.x]; + myVar[5] = 45.364279 * myVar[threadIdx.x]; + myVar[3] = 34.068832 * myVar[threadIdx.x]; + myVar[2] = 21.128017 * myVar[threadIdx.x]; + myVar[5] = 14.244563 * myVar[threadIdx.x]; + myVar[3] = 3.151376 * myVar[threadIdx.x]; + myVar[6] = 2.305583 * myVar[threadIdx.x]; + var_39_0[0] = myVar[0]; + var_39_1[1] = myVar[1]; + var_39_2[2] = myVar[2]; + var_39_3[3] = myVar[3]; + var_39_4[4] = myVar[4]; + var_39_5[5] = myVar[5]; + var_39_6[6] = myVar[6]; + var_39_7[7] = myVar[7]; + var_39_8[8] = myVar[8]; + var_39_9[9] = myVar[9]; + var_39_10[10] = myVar[10]; + var_39_11[11] = myVar[11]; + var_39_12[12] = myVar[12]; + var_39_13[13] = myVar[13]; + var_39_14[14] = myVar[14]; + var_39_15[15] = myVar[15]; + var_39_16[16] = myVar[16]; + var_39_17[17] = myVar[17]; + var_39_18[18] = myVar[18]; + var_39_19[19] = myVar[19]; + +} + +__global__ void kernel_40(float * var_40_0, float * var_40_1, float * var_40_2, float * var_40_3, float * var_40_4, float * var_40_5, float * var_40_6, float * var_40_7, float * var_40_8, float * var_40_9, float * var_40_10, float * var_40_11, float * var_40_12, float * var_40_13, float * var_40_14, float * var_40_15, float * var_40_16, float * var_40_17, float * var_40_18, float * var_40_19) { + __shared__ float myVar[1024]; + myVar[6] = 38.743765 * myVar[threadIdx.x]; + myVar[0] = 3.914831 * myVar[threadIdx.x]; + myVar[0] = 45.867457 * myVar[threadIdx.x]; + myVar[8] = 15.480244 * myVar[threadIdx.x]; + myVar[6] = 7.260518 * myVar[threadIdx.x]; + myVar[3] = 7.096993 * myVar[threadIdx.x]; + myVar[5] = 5.880275 * myVar[threadIdx.x]; + myVar[3] = 22.825388 * myVar[threadIdx.x]; + myVar[2] = 16.359728 * myVar[threadIdx.x]; + myVar[3] = 15.126936 * myVar[threadIdx.x]; + var_40_0[0] = myVar[0]; + var_40_1[1] = myVar[1]; + var_40_2[2] = myVar[2]; + var_40_3[3] = myVar[3]; + var_40_4[4] = myVar[4]; + var_40_5[5] = myVar[5]; + var_40_6[6] = myVar[6]; + var_40_7[7] = myVar[7]; + var_40_8[8] = myVar[8]; + var_40_9[9] = myVar[9]; + var_40_10[10] = myVar[10]; + var_40_11[11] = myVar[11]; + var_40_12[12] = myVar[12]; + var_40_13[13] = myVar[13]; + var_40_14[14] = myVar[14]; + var_40_15[15] = myVar[15]; + var_40_16[16] = myVar[16]; + var_40_17[17] = myVar[17]; + var_40_18[18] = myVar[18]; + var_40_19[19] = myVar[19]; + +} + +__global__ void kernel_41(float * var_41_0, float * var_41_1, float * var_41_2, float * var_41_3, float * var_41_4, float * var_41_5, float * var_41_6, float * var_41_7, float * var_41_8, float * var_41_9, float * var_41_10, float * var_41_11, float * var_41_12, float * var_41_13, float * var_41_14, float * var_41_15, float * var_41_16, float * var_41_17, float * var_41_18, float * var_41_19) { + __shared__ float myVar[1024]; + myVar[3] = 20.568324 * myVar[threadIdx.x]; + myVar[1] = 21.021676 * myVar[threadIdx.x]; + myVar[1] = 40.620338 * myVar[threadIdx.x]; + myVar[9] = 36.677789 * myVar[threadIdx.x]; + myVar[7] = 27.680906 * myVar[threadIdx.x]; + myVar[2] = 44.656317 * myVar[threadIdx.x]; + myVar[9] = 22.003000 * myVar[threadIdx.x]; + myVar[4] = 16.280718 * myVar[threadIdx.x]; + myVar[9] = 16.620876 * myVar[threadIdx.x]; + myVar[8] = 0.349996 * myVar[threadIdx.x]; + var_41_0[0] = myVar[0]; + var_41_1[1] = myVar[1]; + var_41_2[2] = myVar[2]; + var_41_3[3] = myVar[3]; + var_41_4[4] = myVar[4]; + var_41_5[5] = myVar[5]; + var_41_6[6] = myVar[6]; + var_41_7[7] = myVar[7]; + var_41_8[8] = myVar[8]; + var_41_9[9] = myVar[9]; + var_41_10[10] = myVar[10]; + var_41_11[11] = myVar[11]; + var_41_12[12] = myVar[12]; + var_41_13[13] = myVar[13]; + var_41_14[14] = myVar[14]; + var_41_15[15] = myVar[15]; + var_41_16[16] = myVar[16]; + var_41_17[17] = myVar[17]; + var_41_18[18] = myVar[18]; + var_41_19[19] = myVar[19]; + +} + +__global__ void kernel_42(float * var_42_0, float * var_42_1, float * var_42_2, float * var_42_3, float * var_42_4, float * var_42_5, float * var_42_6, float * var_42_7, float * var_42_8, float * var_42_9, float * var_42_10, float * var_42_11, float * var_42_12, float * var_42_13, float * var_42_14, float * var_42_15, float * var_42_16, float * var_42_17, float * var_42_18, float * var_42_19) { + __shared__ float myVar[1024]; + myVar[6] = 42.111438 * myVar[threadIdx.x]; + myVar[8] = 3.365143 * myVar[threadIdx.x]; + myVar[2] = 33.891024 * myVar[threadIdx.x]; + myVar[4] = 41.766899 * myVar[threadIdx.x]; + myVar[2] = 7.180711 * myVar[threadIdx.x]; + myVar[9] = 40.939054 * myVar[threadIdx.x]; + myVar[2] = 27.350946 * myVar[threadIdx.x]; + myVar[2] = 39.810918 * myVar[threadIdx.x]; + myVar[0] = 37.526751 * myVar[threadIdx.x]; + myVar[4] = 26.537539 * myVar[threadIdx.x]; + var_42_0[0] = myVar[0]; + var_42_1[1] = myVar[1]; + var_42_2[2] = myVar[2]; + var_42_3[3] = myVar[3]; + var_42_4[4] = myVar[4]; + var_42_5[5] = myVar[5]; + var_42_6[6] = myVar[6]; + var_42_7[7] = myVar[7]; + var_42_8[8] = myVar[8]; + var_42_9[9] = myVar[9]; + var_42_10[10] = myVar[10]; + var_42_11[11] = myVar[11]; + var_42_12[12] = myVar[12]; + var_42_13[13] = myVar[13]; + var_42_14[14] = myVar[14]; + var_42_15[15] = myVar[15]; + var_42_16[16] = myVar[16]; + var_42_17[17] = myVar[17]; + var_42_18[18] = myVar[18]; + var_42_19[19] = myVar[19]; + +} + +__global__ void kernel_43(float * var_43_0, float * var_43_1, float * var_43_2, float * var_43_3, float * var_43_4, float * var_43_5, float * var_43_6, float * var_43_7, float * var_43_8, float * var_43_9, float * var_43_10, float * var_43_11, float * var_43_12, float * var_43_13, float * var_43_14, float * var_43_15, float * var_43_16, float * var_43_17, float * var_43_18, float * var_43_19) { + __shared__ float myVar[1024]; + myVar[2] = 36.382057 * myVar[threadIdx.x]; + myVar[7] = 23.767897 * myVar[threadIdx.x]; + myVar[0] = 49.106766 * myVar[threadIdx.x]; + myVar[8] = 28.979968 * myVar[threadIdx.x]; + myVar[1] = 21.884905 * myVar[threadIdx.x]; + myVar[2] = 24.992381 * myVar[threadIdx.x]; + myVar[6] = 47.545519 * myVar[threadIdx.x]; + myVar[3] = 0.659092 * myVar[threadIdx.x]; + myVar[3] = 41.286335 * myVar[threadIdx.x]; + myVar[8] = 22.498220 * myVar[threadIdx.x]; + var_43_0[0] = myVar[0]; + var_43_1[1] = myVar[1]; + var_43_2[2] = myVar[2]; + var_43_3[3] = myVar[3]; + var_43_4[4] = myVar[4]; + var_43_5[5] = myVar[5]; + var_43_6[6] = myVar[6]; + var_43_7[7] = myVar[7]; + var_43_8[8] = myVar[8]; + var_43_9[9] = myVar[9]; + var_43_10[10] = myVar[10]; + var_43_11[11] = myVar[11]; + var_43_12[12] = myVar[12]; + var_43_13[13] = myVar[13]; + var_43_14[14] = myVar[14]; + var_43_15[15] = myVar[15]; + var_43_16[16] = myVar[16]; + var_43_17[17] = myVar[17]; + var_43_18[18] = myVar[18]; + var_43_19[19] = myVar[19]; + +} + +__global__ void kernel_44(float * var_44_0, float * var_44_1, float * var_44_2, float * var_44_3, float * var_44_4, float * var_44_5, float * var_44_6, float * var_44_7, float * var_44_8, float * var_44_9, float * var_44_10, float * var_44_11, float * var_44_12, float * var_44_13, float * var_44_14, float * var_44_15, float * var_44_16, float * var_44_17, float * var_44_18, float * var_44_19) { + __shared__ float myVar[1024]; + myVar[1] = 22.696796 * myVar[threadIdx.x]; + myVar[4] = 7.228871 * myVar[threadIdx.x]; + myVar[6] = 32.201492 * myVar[threadIdx.x]; + myVar[9] = 23.192476 * myVar[threadIdx.x]; + myVar[7] = 29.049439 * myVar[threadIdx.x]; + myVar[4] = 41.982081 * myVar[threadIdx.x]; + myVar[5] = 32.711130 * myVar[threadIdx.x]; + myVar[9] = 43.816981 * myVar[threadIdx.x]; + myVar[4] = 34.609433 * myVar[threadIdx.x]; + myVar[9] = 28.135683 * myVar[threadIdx.x]; + var_44_0[0] = myVar[0]; + var_44_1[1] = myVar[1]; + var_44_2[2] = myVar[2]; + var_44_3[3] = myVar[3]; + var_44_4[4] = myVar[4]; + var_44_5[5] = myVar[5]; + var_44_6[6] = myVar[6]; + var_44_7[7] = myVar[7]; + var_44_8[8] = myVar[8]; + var_44_9[9] = myVar[9]; + var_44_10[10] = myVar[10]; + var_44_11[11] = myVar[11]; + var_44_12[12] = myVar[12]; + var_44_13[13] = myVar[13]; + var_44_14[14] = myVar[14]; + var_44_15[15] = myVar[15]; + var_44_16[16] = myVar[16]; + var_44_17[17] = myVar[17]; + var_44_18[18] = myVar[18]; + var_44_19[19] = myVar[19]; + +} + +__global__ void kernel_45(float * var_45_0, float * var_45_1, float * var_45_2, float * var_45_3, float * var_45_4, float * var_45_5, float * var_45_6, float * var_45_7, float * var_45_8, float * var_45_9, float * var_45_10, float * var_45_11, float * var_45_12, float * var_45_13, float * var_45_14, float * var_45_15, float * var_45_16, float * var_45_17, float * var_45_18, float * var_45_19) { + __shared__ float myVar[1024]; + myVar[1] = 5.264738 * myVar[threadIdx.x]; + myVar[8] = 26.466403 * myVar[threadIdx.x]; + myVar[2] = 6.018990 * myVar[threadIdx.x]; + myVar[8] = 8.928184 * myVar[threadIdx.x]; + myVar[7] = 16.665097 * myVar[threadIdx.x]; + myVar[5] = 42.861306 * myVar[threadIdx.x]; + myVar[9] = 31.633341 * myVar[threadIdx.x]; + myVar[2] = 27.710102 * myVar[threadIdx.x]; + myVar[8] = 39.455016 * myVar[threadIdx.x]; + myVar[1] = 19.087801 * myVar[threadIdx.x]; + var_45_0[0] = myVar[0]; + var_45_1[1] = myVar[1]; + var_45_2[2] = myVar[2]; + var_45_3[3] = myVar[3]; + var_45_4[4] = myVar[4]; + var_45_5[5] = myVar[5]; + var_45_6[6] = myVar[6]; + var_45_7[7] = myVar[7]; + var_45_8[8] = myVar[8]; + var_45_9[9] = myVar[9]; + var_45_10[10] = myVar[10]; + var_45_11[11] = myVar[11]; + var_45_12[12] = myVar[12]; + var_45_13[13] = myVar[13]; + var_45_14[14] = myVar[14]; + var_45_15[15] = myVar[15]; + var_45_16[16] = myVar[16]; + var_45_17[17] = myVar[17]; + var_45_18[18] = myVar[18]; + var_45_19[19] = myVar[19]; + +} + +__global__ void kernel_46(float * var_46_0, float * var_46_1, float * var_46_2, float * var_46_3, float * var_46_4, float * var_46_5, float * var_46_6, float * var_46_7, float * var_46_8, float * var_46_9, float * var_46_10, float * var_46_11, float * var_46_12, float * var_46_13, float * var_46_14, float * var_46_15, float * var_46_16, float * var_46_17, float * var_46_18, float * var_46_19) { + __shared__ float myVar[1024]; + myVar[6] = 29.320805 * myVar[threadIdx.x]; + myVar[3] = 13.928934 * myVar[threadIdx.x]; + myVar[0] = 40.096413 * myVar[threadIdx.x]; + myVar[2] = 44.771034 * myVar[threadIdx.x]; + myVar[9] = 19.382410 * myVar[threadIdx.x]; + myVar[2] = 5.395163 * myVar[threadIdx.x]; + myVar[1] = 18.947185 * myVar[threadIdx.x]; + myVar[5] = 9.527862 * myVar[threadIdx.x]; + myVar[2] = 42.415643 * myVar[threadIdx.x]; + myVar[7] = 38.430310 * myVar[threadIdx.x]; + var_46_0[0] = myVar[0]; + var_46_1[1] = myVar[1]; + var_46_2[2] = myVar[2]; + var_46_3[3] = myVar[3]; + var_46_4[4] = myVar[4]; + var_46_5[5] = myVar[5]; + var_46_6[6] = myVar[6]; + var_46_7[7] = myVar[7]; + var_46_8[8] = myVar[8]; + var_46_9[9] = myVar[9]; + var_46_10[10] = myVar[10]; + var_46_11[11] = myVar[11]; + var_46_12[12] = myVar[12]; + var_46_13[13] = myVar[13]; + var_46_14[14] = myVar[14]; + var_46_15[15] = myVar[15]; + var_46_16[16] = myVar[16]; + var_46_17[17] = myVar[17]; + var_46_18[18] = myVar[18]; + var_46_19[19] = myVar[19]; + +} + +__global__ void kernel_47(float * var_47_0, float * var_47_1, float * var_47_2, float * var_47_3, float * var_47_4, float * var_47_5, float * var_47_6, float * var_47_7, float * var_47_8, float * var_47_9, float * var_47_10, float * var_47_11, float * var_47_12, float * var_47_13, float * var_47_14, float * var_47_15, float * var_47_16, float * var_47_17, float * var_47_18, float * var_47_19) { + __shared__ float myVar[1024]; + myVar[4] = 5.982213 * myVar[threadIdx.x]; + myVar[3] = 37.258891 * myVar[threadIdx.x]; + myVar[9] = 25.699217 * myVar[threadIdx.x]; + myVar[3] = 40.365154 * myVar[threadIdx.x]; + myVar[5] = 14.262341 * myVar[threadIdx.x]; + myVar[4] = 40.991364 * myVar[threadIdx.x]; + myVar[3] = 8.103409 * myVar[threadIdx.x]; + myVar[1] = 40.528052 * myVar[threadIdx.x]; + myVar[5] = 21.207895 * myVar[threadIdx.x]; + myVar[5] = 5.529244 * myVar[threadIdx.x]; + var_47_0[0] = myVar[0]; + var_47_1[1] = myVar[1]; + var_47_2[2] = myVar[2]; + var_47_3[3] = myVar[3]; + var_47_4[4] = myVar[4]; + var_47_5[5] = myVar[5]; + var_47_6[6] = myVar[6]; + var_47_7[7] = myVar[7]; + var_47_8[8] = myVar[8]; + var_47_9[9] = myVar[9]; + var_47_10[10] = myVar[10]; + var_47_11[11] = myVar[11]; + var_47_12[12] = myVar[12]; + var_47_13[13] = myVar[13]; + var_47_14[14] = myVar[14]; + var_47_15[15] = myVar[15]; + var_47_16[16] = myVar[16]; + var_47_17[17] = myVar[17]; + var_47_18[18] = myVar[18]; + var_47_19[19] = myVar[19]; + +} + +__global__ void kernel_48(float * var_48_0, float * var_48_1, float * var_48_2, float * var_48_3, float * var_48_4, float * var_48_5, float * var_48_6, float * var_48_7, float * var_48_8, float * var_48_9, float * var_48_10, float * var_48_11, float * var_48_12, float * var_48_13, float * var_48_14, float * var_48_15, float * var_48_16, float * var_48_17, float * var_48_18, float * var_48_19) { + __shared__ float myVar[1024]; + myVar[6] = 19.114624 * myVar[threadIdx.x]; + myVar[2] = 12.542276 * myVar[threadIdx.x]; + myVar[3] = 1.622599 * myVar[threadIdx.x]; + myVar[3] = 39.816754 * myVar[threadIdx.x]; + myVar[6] = 23.014758 * myVar[threadIdx.x]; + myVar[1] = 45.052447 * myVar[threadIdx.x]; + myVar[9] = 7.343654 * myVar[threadIdx.x]; + myVar[8] = 19.386823 * myVar[threadIdx.x]; + myVar[9] = 32.406551 * myVar[threadIdx.x]; + myVar[5] = 31.336219 * myVar[threadIdx.x]; + var_48_0[0] = myVar[0]; + var_48_1[1] = myVar[1]; + var_48_2[2] = myVar[2]; + var_48_3[3] = myVar[3]; + var_48_4[4] = myVar[4]; + var_48_5[5] = myVar[5]; + var_48_6[6] = myVar[6]; + var_48_7[7] = myVar[7]; + var_48_8[8] = myVar[8]; + var_48_9[9] = myVar[9]; + var_48_10[10] = myVar[10]; + var_48_11[11] = myVar[11]; + var_48_12[12] = myVar[12]; + var_48_13[13] = myVar[13]; + var_48_14[14] = myVar[14]; + var_48_15[15] = myVar[15]; + var_48_16[16] = myVar[16]; + var_48_17[17] = myVar[17]; + var_48_18[18] = myVar[18]; + var_48_19[19] = myVar[19]; + +} + +__global__ void kernel_49(float * var_49_0, float * var_49_1, float * var_49_2, float * var_49_3, float * var_49_4, float * var_49_5, float * var_49_6, float * var_49_7, float * var_49_8, float * var_49_9, float * var_49_10, float * var_49_11, float * var_49_12, float * var_49_13, float * var_49_14, float * var_49_15, float * var_49_16, float * var_49_17, float * var_49_18, float * var_49_19) { + __shared__ float myVar[1024]; + myVar[3] = 9.497627 * myVar[threadIdx.x]; + myVar[3] = 38.111004 * myVar[threadIdx.x]; + myVar[1] = 20.507056 * myVar[threadIdx.x]; + myVar[2] = 42.317821 * myVar[threadIdx.x]; + myVar[1] = 48.548658 * myVar[threadIdx.x]; + myVar[4] = 16.948474 * myVar[threadIdx.x]; + myVar[5] = 9.081909 * myVar[threadIdx.x]; + myVar[5] = 16.551171 * myVar[threadIdx.x]; + myVar[7] = 42.262653 * myVar[threadIdx.x]; + myVar[3] = 40.563470 * myVar[threadIdx.x]; + var_49_0[0] = myVar[0]; + var_49_1[1] = myVar[1]; + var_49_2[2] = myVar[2]; + var_49_3[3] = myVar[3]; + var_49_4[4] = myVar[4]; + var_49_5[5] = myVar[5]; + var_49_6[6] = myVar[6]; + var_49_7[7] = myVar[7]; + var_49_8[8] = myVar[8]; + var_49_9[9] = myVar[9]; + var_49_10[10] = myVar[10]; + var_49_11[11] = myVar[11]; + var_49_12[12] = myVar[12]; + var_49_13[13] = myVar[13]; + var_49_14[14] = myVar[14]; + var_49_15[15] = myVar[15]; + var_49_16[16] = myVar[16]; + var_49_17[17] = myVar[17]; + var_49_18[18] = myVar[18]; + var_49_19[19] = myVar[19]; + +} + +__global__ void kernel_50(float * var_50_0, float * var_50_1, float * var_50_2, float * var_50_3, float * var_50_4, float * var_50_5, float * var_50_6, float * var_50_7, float * var_50_8, float * var_50_9, float * var_50_10, float * var_50_11, float * var_50_12, float * var_50_13, float * var_50_14, float * var_50_15, float * var_50_16, float * var_50_17, float * var_50_18, float * var_50_19) { + __shared__ float myVar[1024]; + myVar[6] = 28.012459 * myVar[threadIdx.x]; + myVar[6] = 25.991875 * myVar[threadIdx.x]; + myVar[3] = 13.713698 * myVar[threadIdx.x]; + myVar[4] = 13.887336 * myVar[threadIdx.x]; + myVar[9] = 41.417406 * myVar[threadIdx.x]; + myVar[3] = 5.307227 * myVar[threadIdx.x]; + myVar[0] = 0.364875 * myVar[threadIdx.x]; + myVar[6] = 18.413486 * myVar[threadIdx.x]; + myVar[4] = 9.831031 * myVar[threadIdx.x]; + myVar[2] = 41.817142 * myVar[threadIdx.x]; + var_50_0[0] = myVar[0]; + var_50_1[1] = myVar[1]; + var_50_2[2] = myVar[2]; + var_50_3[3] = myVar[3]; + var_50_4[4] = myVar[4]; + var_50_5[5] = myVar[5]; + var_50_6[6] = myVar[6]; + var_50_7[7] = myVar[7]; + var_50_8[8] = myVar[8]; + var_50_9[9] = myVar[9]; + var_50_10[10] = myVar[10]; + var_50_11[11] = myVar[11]; + var_50_12[12] = myVar[12]; + var_50_13[13] = myVar[13]; + var_50_14[14] = myVar[14]; + var_50_15[15] = myVar[15]; + var_50_16[16] = myVar[16]; + var_50_17[17] = myVar[17]; + var_50_18[18] = myVar[18]; + var_50_19[19] = myVar[19]; + +} + +__global__ void kernel_51(float * var_51_0, float * var_51_1, float * var_51_2, float * var_51_3, float * var_51_4, float * var_51_5, float * var_51_6, float * var_51_7, float * var_51_8, float * var_51_9, float * var_51_10, float * var_51_11, float * var_51_12, float * var_51_13, float * var_51_14, float * var_51_15, float * var_51_16, float * var_51_17, float * var_51_18, float * var_51_19) { + __shared__ float myVar[1024]; + myVar[4] = 22.490023 * myVar[threadIdx.x]; + myVar[3] = 5.457193 * myVar[threadIdx.x]; + myVar[1] = 21.186693 * myVar[threadIdx.x]; + myVar[7] = 17.845219 * myVar[threadIdx.x]; + myVar[9] = 18.021808 * myVar[threadIdx.x]; + myVar[5] = 27.833284 * myVar[threadIdx.x]; + myVar[0] = 10.576937 * myVar[threadIdx.x]; + myVar[2] = 1.478394 * myVar[threadIdx.x]; + myVar[1] = 33.419164 * myVar[threadIdx.x]; + myVar[0] = 28.783970 * myVar[threadIdx.x]; + var_51_0[0] = myVar[0]; + var_51_1[1] = myVar[1]; + var_51_2[2] = myVar[2]; + var_51_3[3] = myVar[3]; + var_51_4[4] = myVar[4]; + var_51_5[5] = myVar[5]; + var_51_6[6] = myVar[6]; + var_51_7[7] = myVar[7]; + var_51_8[8] = myVar[8]; + var_51_9[9] = myVar[9]; + var_51_10[10] = myVar[10]; + var_51_11[11] = myVar[11]; + var_51_12[12] = myVar[12]; + var_51_13[13] = myVar[13]; + var_51_14[14] = myVar[14]; + var_51_15[15] = myVar[15]; + var_51_16[16] = myVar[16]; + var_51_17[17] = myVar[17]; + var_51_18[18] = myVar[18]; + var_51_19[19] = myVar[19]; + +} + +__global__ void kernel_52(float * var_52_0, float * var_52_1, float * var_52_2, float * var_52_3, float * var_52_4, float * var_52_5, float * var_52_6, float * var_52_7, float * var_52_8, float * var_52_9, float * var_52_10, float * var_52_11, float * var_52_12, float * var_52_13, float * var_52_14, float * var_52_15, float * var_52_16, float * var_52_17, float * var_52_18, float * var_52_19) { + __shared__ float myVar[1024]; + myVar[2] = 7.235504 * myVar[threadIdx.x]; + myVar[9] = 32.571032 * myVar[threadIdx.x]; + myVar[7] = 34.190828 * myVar[threadIdx.x]; + myVar[1] = 26.437176 * myVar[threadIdx.x]; + myVar[9] = 1.664443 * myVar[threadIdx.x]; + myVar[7] = 28.140066 * myVar[threadIdx.x]; + myVar[2] = 4.530189 * myVar[threadIdx.x]; + myVar[5] = 37.755731 * myVar[threadIdx.x]; + myVar[8] = 37.563695 * myVar[threadIdx.x]; + myVar[6] = 23.034860 * myVar[threadIdx.x]; + var_52_0[0] = myVar[0]; + var_52_1[1] = myVar[1]; + var_52_2[2] = myVar[2]; + var_52_3[3] = myVar[3]; + var_52_4[4] = myVar[4]; + var_52_5[5] = myVar[5]; + var_52_6[6] = myVar[6]; + var_52_7[7] = myVar[7]; + var_52_8[8] = myVar[8]; + var_52_9[9] = myVar[9]; + var_52_10[10] = myVar[10]; + var_52_11[11] = myVar[11]; + var_52_12[12] = myVar[12]; + var_52_13[13] = myVar[13]; + var_52_14[14] = myVar[14]; + var_52_15[15] = myVar[15]; + var_52_16[16] = myVar[16]; + var_52_17[17] = myVar[17]; + var_52_18[18] = myVar[18]; + var_52_19[19] = myVar[19]; + +} + +__global__ void kernel_53(float * var_53_0, float * var_53_1, float * var_53_2, float * var_53_3, float * var_53_4, float * var_53_5, float * var_53_6, float * var_53_7, float * var_53_8, float * var_53_9, float * var_53_10, float * var_53_11, float * var_53_12, float * var_53_13, float * var_53_14, float * var_53_15, float * var_53_16, float * var_53_17, float * var_53_18, float * var_53_19) { + __shared__ float myVar[1024]; + myVar[0] = 35.640143 * myVar[threadIdx.x]; + myVar[9] = 49.773588 * myVar[threadIdx.x]; + myVar[9] = 11.500338 * myVar[threadIdx.x]; + myVar[5] = 19.826921 * myVar[threadIdx.x]; + myVar[3] = 0.677061 * myVar[threadIdx.x]; + myVar[7] = 44.915955 * myVar[threadIdx.x]; + myVar[3] = 30.448106 * myVar[threadIdx.x]; + myVar[7] = 4.748795 * myVar[threadIdx.x]; + myVar[6] = 8.851894 * myVar[threadIdx.x]; + myVar[7] = 5.527967 * myVar[threadIdx.x]; + var_53_0[0] = myVar[0]; + var_53_1[1] = myVar[1]; + var_53_2[2] = myVar[2]; + var_53_3[3] = myVar[3]; + var_53_4[4] = myVar[4]; + var_53_5[5] = myVar[5]; + var_53_6[6] = myVar[6]; + var_53_7[7] = myVar[7]; + var_53_8[8] = myVar[8]; + var_53_9[9] = myVar[9]; + var_53_10[10] = myVar[10]; + var_53_11[11] = myVar[11]; + var_53_12[12] = myVar[12]; + var_53_13[13] = myVar[13]; + var_53_14[14] = myVar[14]; + var_53_15[15] = myVar[15]; + var_53_16[16] = myVar[16]; + var_53_17[17] = myVar[17]; + var_53_18[18] = myVar[18]; + var_53_19[19] = myVar[19]; + +} + +__global__ void kernel_54(float * var_54_0, float * var_54_1, float * var_54_2, float * var_54_3, float * var_54_4, float * var_54_5, float * var_54_6, float * var_54_7, float * var_54_8, float * var_54_9, float * var_54_10, float * var_54_11, float * var_54_12, float * var_54_13, float * var_54_14, float * var_54_15, float * var_54_16, float * var_54_17, float * var_54_18, float * var_54_19) { + __shared__ float myVar[1024]; + myVar[2] = 19.902653 * myVar[threadIdx.x]; + myVar[1] = 47.270573 * myVar[threadIdx.x]; + myVar[9] = 8.612166 * myVar[threadIdx.x]; + myVar[0] = 13.656687 * myVar[threadIdx.x]; + myVar[3] = 34.048088 * myVar[threadIdx.x]; + myVar[2] = 20.745672 * myVar[threadIdx.x]; + myVar[4] = 4.449649 * myVar[threadIdx.x]; + myVar[1] = 34.471773 * myVar[threadIdx.x]; + myVar[1] = 29.653638 * myVar[threadIdx.x]; + myVar[2] = 3.453407 * myVar[threadIdx.x]; + var_54_0[0] = myVar[0]; + var_54_1[1] = myVar[1]; + var_54_2[2] = myVar[2]; + var_54_3[3] = myVar[3]; + var_54_4[4] = myVar[4]; + var_54_5[5] = myVar[5]; + var_54_6[6] = myVar[6]; + var_54_7[7] = myVar[7]; + var_54_8[8] = myVar[8]; + var_54_9[9] = myVar[9]; + var_54_10[10] = myVar[10]; + var_54_11[11] = myVar[11]; + var_54_12[12] = myVar[12]; + var_54_13[13] = myVar[13]; + var_54_14[14] = myVar[14]; + var_54_15[15] = myVar[15]; + var_54_16[16] = myVar[16]; + var_54_17[17] = myVar[17]; + var_54_18[18] = myVar[18]; + var_54_19[19] = myVar[19]; + +} + +__global__ void kernel_55(float * var_55_0, float * var_55_1, float * var_55_2, float * var_55_3, float * var_55_4, float * var_55_5, float * var_55_6, float * var_55_7, float * var_55_8, float * var_55_9, float * var_55_10, float * var_55_11, float * var_55_12, float * var_55_13, float * var_55_14, float * var_55_15, float * var_55_16, float * var_55_17, float * var_55_18, float * var_55_19) { + __shared__ float myVar[1024]; + myVar[6] = 37.034285 * myVar[threadIdx.x]; + myVar[3] = 12.716498 * myVar[threadIdx.x]; + myVar[6] = 8.490564 * myVar[threadIdx.x]; + myVar[0] = 43.948535 * myVar[threadIdx.x]; + myVar[2] = 0.320381 * myVar[threadIdx.x]; + myVar[3] = 5.822891 * myVar[threadIdx.x]; + myVar[3] = 21.174635 * myVar[threadIdx.x]; + myVar[2] = 13.974690 * myVar[threadIdx.x]; + myVar[1] = 39.717704 * myVar[threadIdx.x]; + myVar[4] = 46.594515 * myVar[threadIdx.x]; + var_55_0[0] = myVar[0]; + var_55_1[1] = myVar[1]; + var_55_2[2] = myVar[2]; + var_55_3[3] = myVar[3]; + var_55_4[4] = myVar[4]; + var_55_5[5] = myVar[5]; + var_55_6[6] = myVar[6]; + var_55_7[7] = myVar[7]; + var_55_8[8] = myVar[8]; + var_55_9[9] = myVar[9]; + var_55_10[10] = myVar[10]; + var_55_11[11] = myVar[11]; + var_55_12[12] = myVar[12]; + var_55_13[13] = myVar[13]; + var_55_14[14] = myVar[14]; + var_55_15[15] = myVar[15]; + var_55_16[16] = myVar[16]; + var_55_17[17] = myVar[17]; + var_55_18[18] = myVar[18]; + var_55_19[19] = myVar[19]; + +} + +__global__ void kernel_56(float * var_56_0, float * var_56_1, float * var_56_2, float * var_56_3, float * var_56_4, float * var_56_5, float * var_56_6, float * var_56_7, float * var_56_8, float * var_56_9, float * var_56_10, float * var_56_11, float * var_56_12, float * var_56_13, float * var_56_14, float * var_56_15, float * var_56_16, float * var_56_17, float * var_56_18, float * var_56_19) { + __shared__ float myVar[1024]; + myVar[4] = 14.354722 * myVar[threadIdx.x]; + myVar[8] = 19.445647 * myVar[threadIdx.x]; + myVar[6] = 6.975940 * myVar[threadIdx.x]; + myVar[1] = 1.841344 * myVar[threadIdx.x]; + myVar[0] = 25.022314 * myVar[threadIdx.x]; + myVar[8] = 10.115960 * myVar[threadIdx.x]; + myVar[8] = 26.694995 * myVar[threadIdx.x]; + myVar[2] = 27.048145 * myVar[threadIdx.x]; + myVar[9] = 40.191317 * myVar[threadIdx.x]; + myVar[4] = 48.592553 * myVar[threadIdx.x]; + var_56_0[0] = myVar[0]; + var_56_1[1] = myVar[1]; + var_56_2[2] = myVar[2]; + var_56_3[3] = myVar[3]; + var_56_4[4] = myVar[4]; + var_56_5[5] = myVar[5]; + var_56_6[6] = myVar[6]; + var_56_7[7] = myVar[7]; + var_56_8[8] = myVar[8]; + var_56_9[9] = myVar[9]; + var_56_10[10] = myVar[10]; + var_56_11[11] = myVar[11]; + var_56_12[12] = myVar[12]; + var_56_13[13] = myVar[13]; + var_56_14[14] = myVar[14]; + var_56_15[15] = myVar[15]; + var_56_16[16] = myVar[16]; + var_56_17[17] = myVar[17]; + var_56_18[18] = myVar[18]; + var_56_19[19] = myVar[19]; + +} + +__global__ void kernel_57(float * var_57_0, float * var_57_1, float * var_57_2, float * var_57_3, float * var_57_4, float * var_57_5, float * var_57_6, float * var_57_7, float * var_57_8, float * var_57_9, float * var_57_10, float * var_57_11, float * var_57_12, float * var_57_13, float * var_57_14, float * var_57_15, float * var_57_16, float * var_57_17, float * var_57_18, float * var_57_19) { + __shared__ float myVar[1024]; + myVar[8] = 1.034066 * myVar[threadIdx.x]; + myVar[8] = 17.991719 * myVar[threadIdx.x]; + myVar[7] = 33.456486 * myVar[threadIdx.x]; + myVar[9] = 22.782415 * myVar[threadIdx.x]; + myVar[7] = 43.160783 * myVar[threadIdx.x]; + myVar[3] = 47.987453 * myVar[threadIdx.x]; + myVar[8] = 19.269042 * myVar[threadIdx.x]; + myVar[1] = 38.047578 * myVar[threadIdx.x]; + myVar[3] = 23.153168 * myVar[threadIdx.x]; + myVar[3] = 5.201573 * myVar[threadIdx.x]; + var_57_0[0] = myVar[0]; + var_57_1[1] = myVar[1]; + var_57_2[2] = myVar[2]; + var_57_3[3] = myVar[3]; + var_57_4[4] = myVar[4]; + var_57_5[5] = myVar[5]; + var_57_6[6] = myVar[6]; + var_57_7[7] = myVar[7]; + var_57_8[8] = myVar[8]; + var_57_9[9] = myVar[9]; + var_57_10[10] = myVar[10]; + var_57_11[11] = myVar[11]; + var_57_12[12] = myVar[12]; + var_57_13[13] = myVar[13]; + var_57_14[14] = myVar[14]; + var_57_15[15] = myVar[15]; + var_57_16[16] = myVar[16]; + var_57_17[17] = myVar[17]; + var_57_18[18] = myVar[18]; + var_57_19[19] = myVar[19]; + +} + +__global__ void kernel_58(float * var_58_0, float * var_58_1, float * var_58_2, float * var_58_3, float * var_58_4, float * var_58_5, float * var_58_6, float * var_58_7, float * var_58_8, float * var_58_9, float * var_58_10, float * var_58_11, float * var_58_12, float * var_58_13, float * var_58_14, float * var_58_15, float * var_58_16, float * var_58_17, float * var_58_18, float * var_58_19) { + __shared__ float myVar[1024]; + myVar[1] = 41.541838 * myVar[threadIdx.x]; + myVar[9] = 37.748709 * myVar[threadIdx.x]; + myVar[4] = 16.368320 * myVar[threadIdx.x]; + myVar[8] = 31.205332 * myVar[threadIdx.x]; + myVar[0] = 37.657988 * myVar[threadIdx.x]; + myVar[2] = 22.547574 * myVar[threadIdx.x]; + myVar[9] = 1.961046 * myVar[threadIdx.x]; + myVar[0] = 34.180845 * myVar[threadIdx.x]; + myVar[1] = 3.071738 * myVar[threadIdx.x]; + myVar[0] = 15.505802 * myVar[threadIdx.x]; + var_58_0[0] = myVar[0]; + var_58_1[1] = myVar[1]; + var_58_2[2] = myVar[2]; + var_58_3[3] = myVar[3]; + var_58_4[4] = myVar[4]; + var_58_5[5] = myVar[5]; + var_58_6[6] = myVar[6]; + var_58_7[7] = myVar[7]; + var_58_8[8] = myVar[8]; + var_58_9[9] = myVar[9]; + var_58_10[10] = myVar[10]; + var_58_11[11] = myVar[11]; + var_58_12[12] = myVar[12]; + var_58_13[13] = myVar[13]; + var_58_14[14] = myVar[14]; + var_58_15[15] = myVar[15]; + var_58_16[16] = myVar[16]; + var_58_17[17] = myVar[17]; + var_58_18[18] = myVar[18]; + var_58_19[19] = myVar[19]; + +} + +__global__ void kernel_59(float * var_59_0, float * var_59_1, float * var_59_2, float * var_59_3, float * var_59_4, float * var_59_5, float * var_59_6, float * var_59_7, float * var_59_8, float * var_59_9, float * var_59_10, float * var_59_11, float * var_59_12, float * var_59_13, float * var_59_14, float * var_59_15, float * var_59_16, float * var_59_17, float * var_59_18, float * var_59_19) { + __shared__ float myVar[1024]; + myVar[0] = 36.742748 * myVar[threadIdx.x]; + myVar[1] = 25.209210 * myVar[threadIdx.x]; + myVar[4] = 42.259580 * myVar[threadIdx.x]; + myVar[3] = 16.190616 * myVar[threadIdx.x]; + myVar[3] = 1.853530 * myVar[threadIdx.x]; + myVar[0] = 14.906392 * myVar[threadIdx.x]; + myVar[3] = 11.083243 * myVar[threadIdx.x]; + myVar[8] = 49.082613 * myVar[threadIdx.x]; + myVar[9] = 30.891738 * myVar[threadIdx.x]; + myVar[3] = 26.238603 * myVar[threadIdx.x]; + var_59_0[0] = myVar[0]; + var_59_1[1] = myVar[1]; + var_59_2[2] = myVar[2]; + var_59_3[3] = myVar[3]; + var_59_4[4] = myVar[4]; + var_59_5[5] = myVar[5]; + var_59_6[6] = myVar[6]; + var_59_7[7] = myVar[7]; + var_59_8[8] = myVar[8]; + var_59_9[9] = myVar[9]; + var_59_10[10] = myVar[10]; + var_59_11[11] = myVar[11]; + var_59_12[12] = myVar[12]; + var_59_13[13] = myVar[13]; + var_59_14[14] = myVar[14]; + var_59_15[15] = myVar[15]; + var_59_16[16] = myVar[16]; + var_59_17[17] = myVar[17]; + var_59_18[18] = myVar[18]; + var_59_19[19] = myVar[19]; + +} + +__global__ void kernel_60(float * var_60_0, float * var_60_1, float * var_60_2, float * var_60_3, float * var_60_4, float * var_60_5, float * var_60_6, float * var_60_7, float * var_60_8, float * var_60_9, float * var_60_10, float * var_60_11, float * var_60_12, float * var_60_13, float * var_60_14, float * var_60_15, float * var_60_16, float * var_60_17, float * var_60_18, float * var_60_19) { + __shared__ float myVar[1024]; + myVar[2] = 22.409327 * myVar[threadIdx.x]; + myVar[1] = 19.211186 * myVar[threadIdx.x]; + myVar[5] = 49.698355 * myVar[threadIdx.x]; + myVar[2] = 14.036316 * myVar[threadIdx.x]; + myVar[3] = 45.807214 * myVar[threadIdx.x]; + myVar[5] = 9.665548 * myVar[threadIdx.x]; + myVar[5] = 37.161092 * myVar[threadIdx.x]; + myVar[0] = 16.517638 * myVar[threadIdx.x]; + myVar[1] = 41.304760 * myVar[threadIdx.x]; + myVar[9] = 45.870091 * myVar[threadIdx.x]; + var_60_0[0] = myVar[0]; + var_60_1[1] = myVar[1]; + var_60_2[2] = myVar[2]; + var_60_3[3] = myVar[3]; + var_60_4[4] = myVar[4]; + var_60_5[5] = myVar[5]; + var_60_6[6] = myVar[6]; + var_60_7[7] = myVar[7]; + var_60_8[8] = myVar[8]; + var_60_9[9] = myVar[9]; + var_60_10[10] = myVar[10]; + var_60_11[11] = myVar[11]; + var_60_12[12] = myVar[12]; + var_60_13[13] = myVar[13]; + var_60_14[14] = myVar[14]; + var_60_15[15] = myVar[15]; + var_60_16[16] = myVar[16]; + var_60_17[17] = myVar[17]; + var_60_18[18] = myVar[18]; + var_60_19[19] = myVar[19]; + +} + +__global__ void kernel_61(float * var_61_0, float * var_61_1, float * var_61_2, float * var_61_3, float * var_61_4, float * var_61_5, float * var_61_6, float * var_61_7, float * var_61_8, float * var_61_9, float * var_61_10, float * var_61_11, float * var_61_12, float * var_61_13, float * var_61_14, float * var_61_15, float * var_61_16, float * var_61_17, float * var_61_18, float * var_61_19) { + __shared__ float myVar[1024]; + myVar[7] = 32.471986 * myVar[threadIdx.x]; + myVar[5] = 19.454519 * myVar[threadIdx.x]; + myVar[8] = 22.159774 * myVar[threadIdx.x]; + myVar[0] = 10.080446 * myVar[threadIdx.x]; + myVar[3] = 18.016182 * myVar[threadIdx.x]; + myVar[3] = 39.915484 * myVar[threadIdx.x]; + myVar[7] = 6.411692 * myVar[threadIdx.x]; + myVar[3] = 19.649969 * myVar[threadIdx.x]; + myVar[7] = 29.673918 * myVar[threadIdx.x]; + myVar[8] = 37.867687 * myVar[threadIdx.x]; + var_61_0[0] = myVar[0]; + var_61_1[1] = myVar[1]; + var_61_2[2] = myVar[2]; + var_61_3[3] = myVar[3]; + var_61_4[4] = myVar[4]; + var_61_5[5] = myVar[5]; + var_61_6[6] = myVar[6]; + var_61_7[7] = myVar[7]; + var_61_8[8] = myVar[8]; + var_61_9[9] = myVar[9]; + var_61_10[10] = myVar[10]; + var_61_11[11] = myVar[11]; + var_61_12[12] = myVar[12]; + var_61_13[13] = myVar[13]; + var_61_14[14] = myVar[14]; + var_61_15[15] = myVar[15]; + var_61_16[16] = myVar[16]; + var_61_17[17] = myVar[17]; + var_61_18[18] = myVar[18]; + var_61_19[19] = myVar[19]; + +} + +__global__ void kernel_62(float * var_62_0, float * var_62_1, float * var_62_2, float * var_62_3, float * var_62_4, float * var_62_5, float * var_62_6, float * var_62_7, float * var_62_8, float * var_62_9, float * var_62_10, float * var_62_11, float * var_62_12, float * var_62_13, float * var_62_14, float * var_62_15, float * var_62_16, float * var_62_17, float * var_62_18, float * var_62_19) { + __shared__ float myVar[1024]; + myVar[2] = 4.829668 * myVar[threadIdx.x]; + myVar[9] = 43.684248 * myVar[threadIdx.x]; + myVar[0] = 28.267032 * myVar[threadIdx.x]; + myVar[8] = 0.731295 * myVar[threadIdx.x]; + myVar[9] = 28.262118 * myVar[threadIdx.x]; + myVar[1] = 43.415830 * myVar[threadIdx.x]; + myVar[1] = 45.989398 * myVar[threadIdx.x]; + myVar[7] = 4.517703 * myVar[threadIdx.x]; + myVar[5] = 12.983002 * myVar[threadIdx.x]; + myVar[8] = 5.414934 * myVar[threadIdx.x]; + var_62_0[0] = myVar[0]; + var_62_1[1] = myVar[1]; + var_62_2[2] = myVar[2]; + var_62_3[3] = myVar[3]; + var_62_4[4] = myVar[4]; + var_62_5[5] = myVar[5]; + var_62_6[6] = myVar[6]; + var_62_7[7] = myVar[7]; + var_62_8[8] = myVar[8]; + var_62_9[9] = myVar[9]; + var_62_10[10] = myVar[10]; + var_62_11[11] = myVar[11]; + var_62_12[12] = myVar[12]; + var_62_13[13] = myVar[13]; + var_62_14[14] = myVar[14]; + var_62_15[15] = myVar[15]; + var_62_16[16] = myVar[16]; + var_62_17[17] = myVar[17]; + var_62_18[18] = myVar[18]; + var_62_19[19] = myVar[19]; + +} + +__global__ void kernel_63(float * var_63_0, float * var_63_1, float * var_63_2, float * var_63_3, float * var_63_4, float * var_63_5, float * var_63_6, float * var_63_7, float * var_63_8, float * var_63_9, float * var_63_10, float * var_63_11, float * var_63_12, float * var_63_13, float * var_63_14, float * var_63_15, float * var_63_16, float * var_63_17, float * var_63_18, float * var_63_19) { + __shared__ float myVar[1024]; + myVar[0] = 6.895080 * myVar[threadIdx.x]; + myVar[8] = 9.215553 * myVar[threadIdx.x]; + myVar[6] = 23.706782 * myVar[threadIdx.x]; + myVar[2] = 10.256461 * myVar[threadIdx.x]; + myVar[3] = 9.793091 * myVar[threadIdx.x]; + myVar[4] = 8.968549 * myVar[threadIdx.x]; + myVar[5] = 42.267950 * myVar[threadIdx.x]; + myVar[3] = 4.966480 * myVar[threadIdx.x]; + myVar[6] = 22.996148 * myVar[threadIdx.x]; + myVar[0] = 2.050984 * myVar[threadIdx.x]; + var_63_0[0] = myVar[0]; + var_63_1[1] = myVar[1]; + var_63_2[2] = myVar[2]; + var_63_3[3] = myVar[3]; + var_63_4[4] = myVar[4]; + var_63_5[5] = myVar[5]; + var_63_6[6] = myVar[6]; + var_63_7[7] = myVar[7]; + var_63_8[8] = myVar[8]; + var_63_9[9] = myVar[9]; + var_63_10[10] = myVar[10]; + var_63_11[11] = myVar[11]; + var_63_12[12] = myVar[12]; + var_63_13[13] = myVar[13]; + var_63_14[14] = myVar[14]; + var_63_15[15] = myVar[15]; + var_63_16[16] = myVar[16]; + var_63_17[17] = myVar[17]; + var_63_18[18] = myVar[18]; + var_63_19[19] = myVar[19]; + +} + +__global__ void kernel_64(float * var_64_0, float * var_64_1, float * var_64_2, float * var_64_3, float * var_64_4, float * var_64_5, float * var_64_6, float * var_64_7, float * var_64_8, float * var_64_9, float * var_64_10, float * var_64_11, float * var_64_12, float * var_64_13, float * var_64_14, float * var_64_15, float * var_64_16, float * var_64_17, float * var_64_18, float * var_64_19) { + __shared__ float myVar[1024]; + myVar[8] = 36.110596 * myVar[threadIdx.x]; + myVar[5] = 37.148806 * myVar[threadIdx.x]; + myVar[2] = 49.935301 * myVar[threadIdx.x]; + myVar[7] = 16.487061 * myVar[threadIdx.x]; + myVar[2] = 28.602171 * myVar[threadIdx.x]; + myVar[1] = 29.314083 * myVar[threadIdx.x]; + myVar[4] = 28.166662 * myVar[threadIdx.x]; + myVar[1] = 15.242463 * myVar[threadIdx.x]; + myVar[4] = 11.502013 * myVar[threadIdx.x]; + myVar[2] = 14.171394 * myVar[threadIdx.x]; + var_64_0[0] = myVar[0]; + var_64_1[1] = myVar[1]; + var_64_2[2] = myVar[2]; + var_64_3[3] = myVar[3]; + var_64_4[4] = myVar[4]; + var_64_5[5] = myVar[5]; + var_64_6[6] = myVar[6]; + var_64_7[7] = myVar[7]; + var_64_8[8] = myVar[8]; + var_64_9[9] = myVar[9]; + var_64_10[10] = myVar[10]; + var_64_11[11] = myVar[11]; + var_64_12[12] = myVar[12]; + var_64_13[13] = myVar[13]; + var_64_14[14] = myVar[14]; + var_64_15[15] = myVar[15]; + var_64_16[16] = myVar[16]; + var_64_17[17] = myVar[17]; + var_64_18[18] = myVar[18]; + var_64_19[19] = myVar[19]; + +} + +__global__ void kernel_65(float * var_65_0, float * var_65_1, float * var_65_2, float * var_65_3, float * var_65_4, float * var_65_5, float * var_65_6, float * var_65_7, float * var_65_8, float * var_65_9, float * var_65_10, float * var_65_11, float * var_65_12, float * var_65_13, float * var_65_14, float * var_65_15, float * var_65_16, float * var_65_17, float * var_65_18, float * var_65_19) { + __shared__ float myVar[1024]; + myVar[7] = 39.313026 * myVar[threadIdx.x]; + myVar[1] = 28.653257 * myVar[threadIdx.x]; + myVar[5] = 18.814101 * myVar[threadIdx.x]; + myVar[0] = 32.994610 * myVar[threadIdx.x]; + myVar[2] = 39.752569 * myVar[threadIdx.x]; + myVar[2] = 26.272723 * myVar[threadIdx.x]; + myVar[5] = 20.636778 * myVar[threadIdx.x]; + myVar[5] = 0.615425 * myVar[threadIdx.x]; + myVar[2] = 14.548679 * myVar[threadIdx.x]; + myVar[2] = 4.017999 * myVar[threadIdx.x]; + var_65_0[0] = myVar[0]; + var_65_1[1] = myVar[1]; + var_65_2[2] = myVar[2]; + var_65_3[3] = myVar[3]; + var_65_4[4] = myVar[4]; + var_65_5[5] = myVar[5]; + var_65_6[6] = myVar[6]; + var_65_7[7] = myVar[7]; + var_65_8[8] = myVar[8]; + var_65_9[9] = myVar[9]; + var_65_10[10] = myVar[10]; + var_65_11[11] = myVar[11]; + var_65_12[12] = myVar[12]; + var_65_13[13] = myVar[13]; + var_65_14[14] = myVar[14]; + var_65_15[15] = myVar[15]; + var_65_16[16] = myVar[16]; + var_65_17[17] = myVar[17]; + var_65_18[18] = myVar[18]; + var_65_19[19] = myVar[19]; + +} + +__global__ void kernel_66(float * var_66_0, float * var_66_1, float * var_66_2, float * var_66_3, float * var_66_4, float * var_66_5, float * var_66_6, float * var_66_7, float * var_66_8, float * var_66_9, float * var_66_10, float * var_66_11, float * var_66_12, float * var_66_13, float * var_66_14, float * var_66_15, float * var_66_16, float * var_66_17, float * var_66_18, float * var_66_19) { + __shared__ float myVar[1024]; + myVar[2] = 28.201326 * myVar[threadIdx.x]; + myVar[5] = 41.466212 * myVar[threadIdx.x]; + myVar[1] = 14.679026 * myVar[threadIdx.x]; + myVar[8] = 1.499039 * myVar[threadIdx.x]; + myVar[0] = 38.744664 * myVar[threadIdx.x]; + myVar[1] = 6.954847 * myVar[threadIdx.x]; + myVar[8] = 7.584151 * myVar[threadIdx.x]; + myVar[0] = 6.001016 * myVar[threadIdx.x]; + myVar[6] = 2.057322 * myVar[threadIdx.x]; + myVar[2] = 19.877629 * myVar[threadIdx.x]; + var_66_0[0] = myVar[0]; + var_66_1[1] = myVar[1]; + var_66_2[2] = myVar[2]; + var_66_3[3] = myVar[3]; + var_66_4[4] = myVar[4]; + var_66_5[5] = myVar[5]; + var_66_6[6] = myVar[6]; + var_66_7[7] = myVar[7]; + var_66_8[8] = myVar[8]; + var_66_9[9] = myVar[9]; + var_66_10[10] = myVar[10]; + var_66_11[11] = myVar[11]; + var_66_12[12] = myVar[12]; + var_66_13[13] = myVar[13]; + var_66_14[14] = myVar[14]; + var_66_15[15] = myVar[15]; + var_66_16[16] = myVar[16]; + var_66_17[17] = myVar[17]; + var_66_18[18] = myVar[18]; + var_66_19[19] = myVar[19]; + +} + +__global__ void kernel_67(float * var_67_0, float * var_67_1, float * var_67_2, float * var_67_3, float * var_67_4, float * var_67_5, float * var_67_6, float * var_67_7, float * var_67_8, float * var_67_9, float * var_67_10, float * var_67_11, float * var_67_12, float * var_67_13, float * var_67_14, float * var_67_15, float * var_67_16, float * var_67_17, float * var_67_18, float * var_67_19) { + __shared__ float myVar[1024]; + myVar[9] = 13.140397 * myVar[threadIdx.x]; + myVar[9] = 46.523538 * myVar[threadIdx.x]; + myVar[7] = 3.033182 * myVar[threadIdx.x]; + myVar[5] = 26.795130 * myVar[threadIdx.x]; + myVar[9] = 30.995732 * myVar[threadIdx.x]; + myVar[8] = 38.365689 * myVar[threadIdx.x]; + myVar[5] = 23.620947 * myVar[threadIdx.x]; + myVar[0] = 15.542619 * myVar[threadIdx.x]; + myVar[8] = 38.233037 * myVar[threadIdx.x]; + myVar[9] = 19.422601 * myVar[threadIdx.x]; + var_67_0[0] = myVar[0]; + var_67_1[1] = myVar[1]; + var_67_2[2] = myVar[2]; + var_67_3[3] = myVar[3]; + var_67_4[4] = myVar[4]; + var_67_5[5] = myVar[5]; + var_67_6[6] = myVar[6]; + var_67_7[7] = myVar[7]; + var_67_8[8] = myVar[8]; + var_67_9[9] = myVar[9]; + var_67_10[10] = myVar[10]; + var_67_11[11] = myVar[11]; + var_67_12[12] = myVar[12]; + var_67_13[13] = myVar[13]; + var_67_14[14] = myVar[14]; + var_67_15[15] = myVar[15]; + var_67_16[16] = myVar[16]; + var_67_17[17] = myVar[17]; + var_67_18[18] = myVar[18]; + var_67_19[19] = myVar[19]; + +} + +__global__ void kernel_68(float * var_68_0, float * var_68_1, float * var_68_2, float * var_68_3, float * var_68_4, float * var_68_5, float * var_68_6, float * var_68_7, float * var_68_8, float * var_68_9, float * var_68_10, float * var_68_11, float * var_68_12, float * var_68_13, float * var_68_14, float * var_68_15, float * var_68_16, float * var_68_17, float * var_68_18, float * var_68_19) { + __shared__ float myVar[1024]; + myVar[8] = 43.766329 * myVar[threadIdx.x]; + myVar[6] = 27.192649 * myVar[threadIdx.x]; + myVar[8] = 23.785973 * myVar[threadIdx.x]; + myVar[9] = 41.367051 * myVar[threadIdx.x]; + myVar[3] = 9.792684 * myVar[threadIdx.x]; + myVar[6] = 31.583700 * myVar[threadIdx.x]; + myVar[9] = 40.443538 * myVar[threadIdx.x]; + myVar[9] = 49.320981 * myVar[threadIdx.x]; + myVar[9] = 34.924821 * myVar[threadIdx.x]; + myVar[8] = 48.775670 * myVar[threadIdx.x]; + var_68_0[0] = myVar[0]; + var_68_1[1] = myVar[1]; + var_68_2[2] = myVar[2]; + var_68_3[3] = myVar[3]; + var_68_4[4] = myVar[4]; + var_68_5[5] = myVar[5]; + var_68_6[6] = myVar[6]; + var_68_7[7] = myVar[7]; + var_68_8[8] = myVar[8]; + var_68_9[9] = myVar[9]; + var_68_10[10] = myVar[10]; + var_68_11[11] = myVar[11]; + var_68_12[12] = myVar[12]; + var_68_13[13] = myVar[13]; + var_68_14[14] = myVar[14]; + var_68_15[15] = myVar[15]; + var_68_16[16] = myVar[16]; + var_68_17[17] = myVar[17]; + var_68_18[18] = myVar[18]; + var_68_19[19] = myVar[19]; + +} + +__global__ void kernel_69(float * var_69_0, float * var_69_1, float * var_69_2, float * var_69_3, float * var_69_4, float * var_69_5, float * var_69_6, float * var_69_7, float * var_69_8, float * var_69_9, float * var_69_10, float * var_69_11, float * var_69_12, float * var_69_13, float * var_69_14, float * var_69_15, float * var_69_16, float * var_69_17, float * var_69_18, float * var_69_19) { + __shared__ float myVar[1024]; + myVar[9] = 7.707027 * myVar[threadIdx.x]; + myVar[7] = 21.683945 * myVar[threadIdx.x]; + myVar[6] = 10.428954 * myVar[threadIdx.x]; + myVar[2] = 24.683253 * myVar[threadIdx.x]; + myVar[6] = 2.906943 * myVar[threadIdx.x]; + myVar[0] = 9.477013 * myVar[threadIdx.x]; + myVar[6] = 46.410466 * myVar[threadIdx.x]; + myVar[7] = 39.701940 * myVar[threadIdx.x]; + myVar[6] = 29.047030 * myVar[threadIdx.x]; + myVar[7] = 8.740714 * myVar[threadIdx.x]; + var_69_0[0] = myVar[0]; + var_69_1[1] = myVar[1]; + var_69_2[2] = myVar[2]; + var_69_3[3] = myVar[3]; + var_69_4[4] = myVar[4]; + var_69_5[5] = myVar[5]; + var_69_6[6] = myVar[6]; + var_69_7[7] = myVar[7]; + var_69_8[8] = myVar[8]; + var_69_9[9] = myVar[9]; + var_69_10[10] = myVar[10]; + var_69_11[11] = myVar[11]; + var_69_12[12] = myVar[12]; + var_69_13[13] = myVar[13]; + var_69_14[14] = myVar[14]; + var_69_15[15] = myVar[15]; + var_69_16[16] = myVar[16]; + var_69_17[17] = myVar[17]; + var_69_18[18] = myVar[18]; + var_69_19[19] = myVar[19]; + +} + +__global__ void kernel_70(float * var_70_0, float * var_70_1, float * var_70_2, float * var_70_3, float * var_70_4, float * var_70_5, float * var_70_6, float * var_70_7, float * var_70_8, float * var_70_9, float * var_70_10, float * var_70_11, float * var_70_12, float * var_70_13, float * var_70_14, float * var_70_15, float * var_70_16, float * var_70_17, float * var_70_18, float * var_70_19) { + __shared__ float myVar[1024]; + myVar[0] = 32.466671 * myVar[threadIdx.x]; + myVar[6] = 4.534523 * myVar[threadIdx.x]; + myVar[3] = 11.770629 * myVar[threadIdx.x]; + myVar[8] = 46.817250 * myVar[threadIdx.x]; + myVar[1] = 10.812564 * myVar[threadIdx.x]; + myVar[4] = 1.846516 * myVar[threadIdx.x]; + myVar[9] = 35.385064 * myVar[threadIdx.x]; + myVar[6] = 2.934052 * myVar[threadIdx.x]; + myVar[7] = 4.579234 * myVar[threadIdx.x]; + myVar[3] = 4.102144 * myVar[threadIdx.x]; + var_70_0[0] = myVar[0]; + var_70_1[1] = myVar[1]; + var_70_2[2] = myVar[2]; + var_70_3[3] = myVar[3]; + var_70_4[4] = myVar[4]; + var_70_5[5] = myVar[5]; + var_70_6[6] = myVar[6]; + var_70_7[7] = myVar[7]; + var_70_8[8] = myVar[8]; + var_70_9[9] = myVar[9]; + var_70_10[10] = myVar[10]; + var_70_11[11] = myVar[11]; + var_70_12[12] = myVar[12]; + var_70_13[13] = myVar[13]; + var_70_14[14] = myVar[14]; + var_70_15[15] = myVar[15]; + var_70_16[16] = myVar[16]; + var_70_17[17] = myVar[17]; + var_70_18[18] = myVar[18]; + var_70_19[19] = myVar[19]; + +} + +__global__ void kernel_71(float * var_71_0, float * var_71_1, float * var_71_2, float * var_71_3, float * var_71_4, float * var_71_5, float * var_71_6, float * var_71_7, float * var_71_8, float * var_71_9, float * var_71_10, float * var_71_11, float * var_71_12, float * var_71_13, float * var_71_14, float * var_71_15, float * var_71_16, float * var_71_17, float * var_71_18, float * var_71_19) { + __shared__ float myVar[1024]; + myVar[4] = 41.170601 * myVar[threadIdx.x]; + myVar[4] = 13.651976 * myVar[threadIdx.x]; + myVar[6] = 6.834099 * myVar[threadIdx.x]; + myVar[2] = 26.910055 * myVar[threadIdx.x]; + myVar[9] = 43.342289 * myVar[threadIdx.x]; + myVar[8] = 10.524127 * myVar[threadIdx.x]; + myVar[7] = 40.450485 * myVar[threadIdx.x]; + myVar[4] = 2.319119 * myVar[threadIdx.x]; + myVar[3] = 34.342359 * myVar[threadIdx.x]; + myVar[0] = 30.794013 * myVar[threadIdx.x]; + var_71_0[0] = myVar[0]; + var_71_1[1] = myVar[1]; + var_71_2[2] = myVar[2]; + var_71_3[3] = myVar[3]; + var_71_4[4] = myVar[4]; + var_71_5[5] = myVar[5]; + var_71_6[6] = myVar[6]; + var_71_7[7] = myVar[7]; + var_71_8[8] = myVar[8]; + var_71_9[9] = myVar[9]; + var_71_10[10] = myVar[10]; + var_71_11[11] = myVar[11]; + var_71_12[12] = myVar[12]; + var_71_13[13] = myVar[13]; + var_71_14[14] = myVar[14]; + var_71_15[15] = myVar[15]; + var_71_16[16] = myVar[16]; + var_71_17[17] = myVar[17]; + var_71_18[18] = myVar[18]; + var_71_19[19] = myVar[19]; + +} + +__global__ void kernel_72(float * var_72_0, float * var_72_1, float * var_72_2, float * var_72_3, float * var_72_4, float * var_72_5, float * var_72_6, float * var_72_7, float * var_72_8, float * var_72_9, float * var_72_10, float * var_72_11, float * var_72_12, float * var_72_13, float * var_72_14, float * var_72_15, float * var_72_16, float * var_72_17, float * var_72_18, float * var_72_19) { + __shared__ float myVar[1024]; + myVar[4] = 21.942838 * myVar[threadIdx.x]; + myVar[7] = 7.979056 * myVar[threadIdx.x]; + myVar[9] = 42.630924 * myVar[threadIdx.x]; + myVar[8] = 26.467586 * myVar[threadIdx.x]; + myVar[7] = 3.136713 * myVar[threadIdx.x]; + myVar[6] = 29.039205 * myVar[threadIdx.x]; + myVar[7] = 15.514938 * myVar[threadIdx.x]; + myVar[1] = 24.760805 * myVar[threadIdx.x]; + myVar[5] = 14.885079 * myVar[threadIdx.x]; + myVar[2] = 4.947861 * myVar[threadIdx.x]; + var_72_0[0] = myVar[0]; + var_72_1[1] = myVar[1]; + var_72_2[2] = myVar[2]; + var_72_3[3] = myVar[3]; + var_72_4[4] = myVar[4]; + var_72_5[5] = myVar[5]; + var_72_6[6] = myVar[6]; + var_72_7[7] = myVar[7]; + var_72_8[8] = myVar[8]; + var_72_9[9] = myVar[9]; + var_72_10[10] = myVar[10]; + var_72_11[11] = myVar[11]; + var_72_12[12] = myVar[12]; + var_72_13[13] = myVar[13]; + var_72_14[14] = myVar[14]; + var_72_15[15] = myVar[15]; + var_72_16[16] = myVar[16]; + var_72_17[17] = myVar[17]; + var_72_18[18] = myVar[18]; + var_72_19[19] = myVar[19]; + +} + +__global__ void kernel_73(float * var_73_0, float * var_73_1, float * var_73_2, float * var_73_3, float * var_73_4, float * var_73_5, float * var_73_6, float * var_73_7, float * var_73_8, float * var_73_9, float * var_73_10, float * var_73_11, float * var_73_12, float * var_73_13, float * var_73_14, float * var_73_15, float * var_73_16, float * var_73_17, float * var_73_18, float * var_73_19) { + __shared__ float myVar[1024]; + myVar[1] = 19.735558 * myVar[threadIdx.x]; + myVar[9] = 18.724792 * myVar[threadIdx.x]; + myVar[1] = 41.933294 * myVar[threadIdx.x]; + myVar[2] = 33.499581 * myVar[threadIdx.x]; + myVar[9] = 17.797468 * myVar[threadIdx.x]; + myVar[9] = 5.813515 * myVar[threadIdx.x]; + myVar[2] = 8.649189 * myVar[threadIdx.x]; + myVar[9] = 13.243289 * myVar[threadIdx.x]; + myVar[7] = 32.770060 * myVar[threadIdx.x]; + myVar[4] = 5.658495 * myVar[threadIdx.x]; + var_73_0[0] = myVar[0]; + var_73_1[1] = myVar[1]; + var_73_2[2] = myVar[2]; + var_73_3[3] = myVar[3]; + var_73_4[4] = myVar[4]; + var_73_5[5] = myVar[5]; + var_73_6[6] = myVar[6]; + var_73_7[7] = myVar[7]; + var_73_8[8] = myVar[8]; + var_73_9[9] = myVar[9]; + var_73_10[10] = myVar[10]; + var_73_11[11] = myVar[11]; + var_73_12[12] = myVar[12]; + var_73_13[13] = myVar[13]; + var_73_14[14] = myVar[14]; + var_73_15[15] = myVar[15]; + var_73_16[16] = myVar[16]; + var_73_17[17] = myVar[17]; + var_73_18[18] = myVar[18]; + var_73_19[19] = myVar[19]; + +} + +__global__ void kernel_74(float * var_74_0, float * var_74_1, float * var_74_2, float * var_74_3, float * var_74_4, float * var_74_5, float * var_74_6, float * var_74_7, float * var_74_8, float * var_74_9, float * var_74_10, float * var_74_11, float * var_74_12, float * var_74_13, float * var_74_14, float * var_74_15, float * var_74_16, float * var_74_17, float * var_74_18, float * var_74_19) { + __shared__ float myVar[1024]; + myVar[2] = 22.888231 * myVar[threadIdx.x]; + myVar[0] = 19.859960 * myVar[threadIdx.x]; + myVar[7] = 47.655515 * myVar[threadIdx.x]; + myVar[8] = 15.599701 * myVar[threadIdx.x]; + myVar[5] = 25.612808 * myVar[threadIdx.x]; + myVar[9] = 22.018348 * myVar[threadIdx.x]; + myVar[1] = 7.647660 * myVar[threadIdx.x]; + myVar[9] = 49.856509 * myVar[threadIdx.x]; + myVar[3] = 18.859440 * myVar[threadIdx.x]; + myVar[1] = 36.744651 * myVar[threadIdx.x]; + var_74_0[0] = myVar[0]; + var_74_1[1] = myVar[1]; + var_74_2[2] = myVar[2]; + var_74_3[3] = myVar[3]; + var_74_4[4] = myVar[4]; + var_74_5[5] = myVar[5]; + var_74_6[6] = myVar[6]; + var_74_7[7] = myVar[7]; + var_74_8[8] = myVar[8]; + var_74_9[9] = myVar[9]; + var_74_10[10] = myVar[10]; + var_74_11[11] = myVar[11]; + var_74_12[12] = myVar[12]; + var_74_13[13] = myVar[13]; + var_74_14[14] = myVar[14]; + var_74_15[15] = myVar[15]; + var_74_16[16] = myVar[16]; + var_74_17[17] = myVar[17]; + var_74_18[18] = myVar[18]; + var_74_19[19] = myVar[19]; + +} + +__global__ void kernel_75(float * var_75_0, float * var_75_1, float * var_75_2, float * var_75_3, float * var_75_4, float * var_75_5, float * var_75_6, float * var_75_7, float * var_75_8, float * var_75_9, float * var_75_10, float * var_75_11, float * var_75_12, float * var_75_13, float * var_75_14, float * var_75_15, float * var_75_16, float * var_75_17, float * var_75_18, float * var_75_19) { + __shared__ float myVar[1024]; + myVar[0] = 28.702369 * myVar[threadIdx.x]; + myVar[3] = 33.381361 * myVar[threadIdx.x]; + myVar[7] = 12.768239 * myVar[threadIdx.x]; + myVar[3] = 48.437948 * myVar[threadIdx.x]; + myVar[0] = 26.398561 * myVar[threadIdx.x]; + myVar[7] = 49.402374 * myVar[threadIdx.x]; + myVar[5] = 44.292255 * myVar[threadIdx.x]; + myVar[1] = 28.579125 * myVar[threadIdx.x]; + myVar[0] = 12.116632 * myVar[threadIdx.x]; + myVar[6] = 12.440771 * myVar[threadIdx.x]; + var_75_0[0] = myVar[0]; + var_75_1[1] = myVar[1]; + var_75_2[2] = myVar[2]; + var_75_3[3] = myVar[3]; + var_75_4[4] = myVar[4]; + var_75_5[5] = myVar[5]; + var_75_6[6] = myVar[6]; + var_75_7[7] = myVar[7]; + var_75_8[8] = myVar[8]; + var_75_9[9] = myVar[9]; + var_75_10[10] = myVar[10]; + var_75_11[11] = myVar[11]; + var_75_12[12] = myVar[12]; + var_75_13[13] = myVar[13]; + var_75_14[14] = myVar[14]; + var_75_15[15] = myVar[15]; + var_75_16[16] = myVar[16]; + var_75_17[17] = myVar[17]; + var_75_18[18] = myVar[18]; + var_75_19[19] = myVar[19]; + +} + +__global__ void kernel_76(float * var_76_0, float * var_76_1, float * var_76_2, float * var_76_3, float * var_76_4, float * var_76_5, float * var_76_6, float * var_76_7, float * var_76_8, float * var_76_9, float * var_76_10, float * var_76_11, float * var_76_12, float * var_76_13, float * var_76_14, float * var_76_15, float * var_76_16, float * var_76_17, float * var_76_18, float * var_76_19) { + __shared__ float myVar[1024]; + myVar[5] = 32.013261 * myVar[threadIdx.x]; + myVar[6] = 14.655572 * myVar[threadIdx.x]; + myVar[6] = 24.448350 * myVar[threadIdx.x]; + myVar[5] = 26.084300 * myVar[threadIdx.x]; + myVar[2] = 2.995143 * myVar[threadIdx.x]; + myVar[9] = 12.297336 * myVar[threadIdx.x]; + myVar[3] = 13.592696 * myVar[threadIdx.x]; + myVar[7] = 30.036508 * myVar[threadIdx.x]; + myVar[6] = 34.314084 * myVar[threadIdx.x]; + myVar[8] = 3.278087 * myVar[threadIdx.x]; + var_76_0[0] = myVar[0]; + var_76_1[1] = myVar[1]; + var_76_2[2] = myVar[2]; + var_76_3[3] = myVar[3]; + var_76_4[4] = myVar[4]; + var_76_5[5] = myVar[5]; + var_76_6[6] = myVar[6]; + var_76_7[7] = myVar[7]; + var_76_8[8] = myVar[8]; + var_76_9[9] = myVar[9]; + var_76_10[10] = myVar[10]; + var_76_11[11] = myVar[11]; + var_76_12[12] = myVar[12]; + var_76_13[13] = myVar[13]; + var_76_14[14] = myVar[14]; + var_76_15[15] = myVar[15]; + var_76_16[16] = myVar[16]; + var_76_17[17] = myVar[17]; + var_76_18[18] = myVar[18]; + var_76_19[19] = myVar[19]; + +} + +__global__ void kernel_77(float * var_77_0, float * var_77_1, float * var_77_2, float * var_77_3, float * var_77_4, float * var_77_5, float * var_77_6, float * var_77_7, float * var_77_8, float * var_77_9, float * var_77_10, float * var_77_11, float * var_77_12, float * var_77_13, float * var_77_14, float * var_77_15, float * var_77_16, float * var_77_17, float * var_77_18, float * var_77_19) { + __shared__ float myVar[1024]; + myVar[6] = 0.586754 * myVar[threadIdx.x]; + myVar[2] = 21.242784 * myVar[threadIdx.x]; + myVar[6] = 19.633715 * myVar[threadIdx.x]; + myVar[3] = 7.058163 * myVar[threadIdx.x]; + myVar[5] = 17.066796 * myVar[threadIdx.x]; + myVar[9] = 49.404883 * myVar[threadIdx.x]; + myVar[7] = 5.806399 * myVar[threadIdx.x]; + myVar[4] = 24.515104 * myVar[threadIdx.x]; + myVar[9] = 44.272751 * myVar[threadIdx.x]; + myVar[0] = 24.247686 * myVar[threadIdx.x]; + var_77_0[0] = myVar[0]; + var_77_1[1] = myVar[1]; + var_77_2[2] = myVar[2]; + var_77_3[3] = myVar[3]; + var_77_4[4] = myVar[4]; + var_77_5[5] = myVar[5]; + var_77_6[6] = myVar[6]; + var_77_7[7] = myVar[7]; + var_77_8[8] = myVar[8]; + var_77_9[9] = myVar[9]; + var_77_10[10] = myVar[10]; + var_77_11[11] = myVar[11]; + var_77_12[12] = myVar[12]; + var_77_13[13] = myVar[13]; + var_77_14[14] = myVar[14]; + var_77_15[15] = myVar[15]; + var_77_16[16] = myVar[16]; + var_77_17[17] = myVar[17]; + var_77_18[18] = myVar[18]; + var_77_19[19] = myVar[19]; + +} + +__global__ void kernel_78(float * var_78_0, float * var_78_1, float * var_78_2, float * var_78_3, float * var_78_4, float * var_78_5, float * var_78_6, float * var_78_7, float * var_78_8, float * var_78_9, float * var_78_10, float * var_78_11, float * var_78_12, float * var_78_13, float * var_78_14, float * var_78_15, float * var_78_16, float * var_78_17, float * var_78_18, float * var_78_19) { + __shared__ float myVar[1024]; + myVar[0] = 1.064089 * myVar[threadIdx.x]; + myVar[4] = 19.377686 * myVar[threadIdx.x]; + myVar[1] = 41.891596 * myVar[threadIdx.x]; + myVar[2] = 32.112862 * myVar[threadIdx.x]; + myVar[2] = 47.966346 * myVar[threadIdx.x]; + myVar[7] = 13.487199 * myVar[threadIdx.x]; + myVar[2] = 9.251429 * myVar[threadIdx.x]; + myVar[8] = 20.397124 * myVar[threadIdx.x]; + myVar[8] = 12.054116 * myVar[threadIdx.x]; + myVar[1] = 30.061273 * myVar[threadIdx.x]; + var_78_0[0] = myVar[0]; + var_78_1[1] = myVar[1]; + var_78_2[2] = myVar[2]; + var_78_3[3] = myVar[3]; + var_78_4[4] = myVar[4]; + var_78_5[5] = myVar[5]; + var_78_6[6] = myVar[6]; + var_78_7[7] = myVar[7]; + var_78_8[8] = myVar[8]; + var_78_9[9] = myVar[9]; + var_78_10[10] = myVar[10]; + var_78_11[11] = myVar[11]; + var_78_12[12] = myVar[12]; + var_78_13[13] = myVar[13]; + var_78_14[14] = myVar[14]; + var_78_15[15] = myVar[15]; + var_78_16[16] = myVar[16]; + var_78_17[17] = myVar[17]; + var_78_18[18] = myVar[18]; + var_78_19[19] = myVar[19]; + +} + +__global__ void kernel_79(float * var_79_0, float * var_79_1, float * var_79_2, float * var_79_3, float * var_79_4, float * var_79_5, float * var_79_6, float * var_79_7, float * var_79_8, float * var_79_9, float * var_79_10, float * var_79_11, float * var_79_12, float * var_79_13, float * var_79_14, float * var_79_15, float * var_79_16, float * var_79_17, float * var_79_18, float * var_79_19) { + __shared__ float myVar[1024]; + myVar[3] = 18.196824 * myVar[threadIdx.x]; + myVar[7] = 43.837447 * myVar[threadIdx.x]; + myVar[4] = 23.153390 * myVar[threadIdx.x]; + myVar[4] = 27.992319 * myVar[threadIdx.x]; + myVar[5] = 9.024027 * myVar[threadIdx.x]; + myVar[1] = 48.804173 * myVar[threadIdx.x]; + myVar[0] = 7.408689 * myVar[threadIdx.x]; + myVar[7] = 23.778323 * myVar[threadIdx.x]; + myVar[6] = 42.920944 * myVar[threadIdx.x]; + myVar[7] = 29.065020 * myVar[threadIdx.x]; + var_79_0[0] = myVar[0]; + var_79_1[1] = myVar[1]; + var_79_2[2] = myVar[2]; + var_79_3[3] = myVar[3]; + var_79_4[4] = myVar[4]; + var_79_5[5] = myVar[5]; + var_79_6[6] = myVar[6]; + var_79_7[7] = myVar[7]; + var_79_8[8] = myVar[8]; + var_79_9[9] = myVar[9]; + var_79_10[10] = myVar[10]; + var_79_11[11] = myVar[11]; + var_79_12[12] = myVar[12]; + var_79_13[13] = myVar[13]; + var_79_14[14] = myVar[14]; + var_79_15[15] = myVar[15]; + var_79_16[16] = myVar[16]; + var_79_17[17] = myVar[17]; + var_79_18[18] = myVar[18]; + var_79_19[19] = myVar[19]; + +} + +__global__ void kernel_80(float * var_80_0, float * var_80_1, float * var_80_2, float * var_80_3, float * var_80_4, float * var_80_5, float * var_80_6, float * var_80_7, float * var_80_8, float * var_80_9, float * var_80_10, float * var_80_11, float * var_80_12, float * var_80_13, float * var_80_14, float * var_80_15, float * var_80_16, float * var_80_17, float * var_80_18, float * var_80_19) { + __shared__ float myVar[1024]; + myVar[6] = 29.986274 * myVar[threadIdx.x]; + myVar[8] = 6.206306 * myVar[threadIdx.x]; + myVar[5] = 13.512669 * myVar[threadIdx.x]; + myVar[5] = 39.159626 * myVar[threadIdx.x]; + myVar[4] = 34.758343 * myVar[threadIdx.x]; + myVar[1] = 37.380999 * myVar[threadIdx.x]; + myVar[1] = 49.354852 * myVar[threadIdx.x]; + myVar[9] = 38.446218 * myVar[threadIdx.x]; + myVar[3] = 39.416359 * myVar[threadIdx.x]; + myVar[8] = 42.874535 * myVar[threadIdx.x]; + var_80_0[0] = myVar[0]; + var_80_1[1] = myVar[1]; + var_80_2[2] = myVar[2]; + var_80_3[3] = myVar[3]; + var_80_4[4] = myVar[4]; + var_80_5[5] = myVar[5]; + var_80_6[6] = myVar[6]; + var_80_7[7] = myVar[7]; + var_80_8[8] = myVar[8]; + var_80_9[9] = myVar[9]; + var_80_10[10] = myVar[10]; + var_80_11[11] = myVar[11]; + var_80_12[12] = myVar[12]; + var_80_13[13] = myVar[13]; + var_80_14[14] = myVar[14]; + var_80_15[15] = myVar[15]; + var_80_16[16] = myVar[16]; + var_80_17[17] = myVar[17]; + var_80_18[18] = myVar[18]; + var_80_19[19] = myVar[19]; + +} + +__global__ void kernel_81(float * var_81_0, float * var_81_1, float * var_81_2, float * var_81_3, float * var_81_4, float * var_81_5, float * var_81_6, float * var_81_7, float * var_81_8, float * var_81_9, float * var_81_10, float * var_81_11, float * var_81_12, float * var_81_13, float * var_81_14, float * var_81_15, float * var_81_16, float * var_81_17, float * var_81_18, float * var_81_19) { + __shared__ float myVar[1024]; + myVar[8] = 47.171056 * myVar[threadIdx.x]; + myVar[9] = 34.012280 * myVar[threadIdx.x]; + myVar[0] = 48.939174 * myVar[threadIdx.x]; + myVar[2] = 23.415897 * myVar[threadIdx.x]; + myVar[9] = 11.547523 * myVar[threadIdx.x]; + myVar[9] = 46.820279 * myVar[threadIdx.x]; + myVar[7] = 30.271263 * myVar[threadIdx.x]; + myVar[4] = 27.460999 * myVar[threadIdx.x]; + myVar[8] = 41.792915 * myVar[threadIdx.x]; + myVar[0] = 3.939068 * myVar[threadIdx.x]; + var_81_0[0] = myVar[0]; + var_81_1[1] = myVar[1]; + var_81_2[2] = myVar[2]; + var_81_3[3] = myVar[3]; + var_81_4[4] = myVar[4]; + var_81_5[5] = myVar[5]; + var_81_6[6] = myVar[6]; + var_81_7[7] = myVar[7]; + var_81_8[8] = myVar[8]; + var_81_9[9] = myVar[9]; + var_81_10[10] = myVar[10]; + var_81_11[11] = myVar[11]; + var_81_12[12] = myVar[12]; + var_81_13[13] = myVar[13]; + var_81_14[14] = myVar[14]; + var_81_15[15] = myVar[15]; + var_81_16[16] = myVar[16]; + var_81_17[17] = myVar[17]; + var_81_18[18] = myVar[18]; + var_81_19[19] = myVar[19]; + +} + +__global__ void kernel_82(float * var_82_0, float * var_82_1, float * var_82_2, float * var_82_3, float * var_82_4, float * var_82_5, float * var_82_6, float * var_82_7, float * var_82_8, float * var_82_9, float * var_82_10, float * var_82_11, float * var_82_12, float * var_82_13, float * var_82_14, float * var_82_15, float * var_82_16, float * var_82_17, float * var_82_18, float * var_82_19) { + __shared__ float myVar[1024]; + myVar[1] = 24.598735 * myVar[threadIdx.x]; + myVar[8] = 27.287896 * myVar[threadIdx.x]; + myVar[8] = 44.845122 * myVar[threadIdx.x]; + myVar[1] = 20.370291 * myVar[threadIdx.x]; + myVar[1] = 17.560660 * myVar[threadIdx.x]; + myVar[9] = 36.935529 * myVar[threadIdx.x]; + myVar[9] = 36.543273 * myVar[threadIdx.x]; + myVar[2] = 1.067267 * myVar[threadIdx.x]; + myVar[4] = 24.287814 * myVar[threadIdx.x]; + myVar[0] = 48.009908 * myVar[threadIdx.x]; + var_82_0[0] = myVar[0]; + var_82_1[1] = myVar[1]; + var_82_2[2] = myVar[2]; + var_82_3[3] = myVar[3]; + var_82_4[4] = myVar[4]; + var_82_5[5] = myVar[5]; + var_82_6[6] = myVar[6]; + var_82_7[7] = myVar[7]; + var_82_8[8] = myVar[8]; + var_82_9[9] = myVar[9]; + var_82_10[10] = myVar[10]; + var_82_11[11] = myVar[11]; + var_82_12[12] = myVar[12]; + var_82_13[13] = myVar[13]; + var_82_14[14] = myVar[14]; + var_82_15[15] = myVar[15]; + var_82_16[16] = myVar[16]; + var_82_17[17] = myVar[17]; + var_82_18[18] = myVar[18]; + var_82_19[19] = myVar[19]; + +} + +__global__ void kernel_83(float * var_83_0, float * var_83_1, float * var_83_2, float * var_83_3, float * var_83_4, float * var_83_5, float * var_83_6, float * var_83_7, float * var_83_8, float * var_83_9, float * var_83_10, float * var_83_11, float * var_83_12, float * var_83_13, float * var_83_14, float * var_83_15, float * var_83_16, float * var_83_17, float * var_83_18, float * var_83_19) { + __shared__ float myVar[1024]; + myVar[9] = 36.390445 * myVar[threadIdx.x]; + myVar[0] = 39.153191 * myVar[threadIdx.x]; + myVar[5] = 17.985216 * myVar[threadIdx.x]; + myVar[1] = 22.930816 * myVar[threadIdx.x]; + myVar[1] = 6.413215 * myVar[threadIdx.x]; + myVar[3] = 19.841041 * myVar[threadIdx.x]; + myVar[6] = 28.020421 * myVar[threadIdx.x]; + myVar[8] = 26.730542 * myVar[threadIdx.x]; + myVar[7] = 23.492608 * myVar[threadIdx.x]; + myVar[1] = 32.477826 * myVar[threadIdx.x]; + var_83_0[0] = myVar[0]; + var_83_1[1] = myVar[1]; + var_83_2[2] = myVar[2]; + var_83_3[3] = myVar[3]; + var_83_4[4] = myVar[4]; + var_83_5[5] = myVar[5]; + var_83_6[6] = myVar[6]; + var_83_7[7] = myVar[7]; + var_83_8[8] = myVar[8]; + var_83_9[9] = myVar[9]; + var_83_10[10] = myVar[10]; + var_83_11[11] = myVar[11]; + var_83_12[12] = myVar[12]; + var_83_13[13] = myVar[13]; + var_83_14[14] = myVar[14]; + var_83_15[15] = myVar[15]; + var_83_16[16] = myVar[16]; + var_83_17[17] = myVar[17]; + var_83_18[18] = myVar[18]; + var_83_19[19] = myVar[19]; + +} + +__global__ void kernel_84(float * var_84_0, float * var_84_1, float * var_84_2, float * var_84_3, float * var_84_4, float * var_84_5, float * var_84_6, float * var_84_7, float * var_84_8, float * var_84_9, float * var_84_10, float * var_84_11, float * var_84_12, float * var_84_13, float * var_84_14, float * var_84_15, float * var_84_16, float * var_84_17, float * var_84_18, float * var_84_19) { + __shared__ float myVar[1024]; + myVar[1] = 15.828457 * myVar[threadIdx.x]; + myVar[8] = 11.603154 * myVar[threadIdx.x]; + myVar[7] = 23.479446 * myVar[threadIdx.x]; + myVar[9] = 40.390499 * myVar[threadIdx.x]; + myVar[0] = 49.498116 * myVar[threadIdx.x]; + myVar[5] = 5.547645 * myVar[threadIdx.x]; + myVar[6] = 32.120135 * myVar[threadIdx.x]; + myVar[8] = 13.189183 * myVar[threadIdx.x]; + myVar[4] = 5.747827 * myVar[threadIdx.x]; + myVar[7] = 13.207244 * myVar[threadIdx.x]; + var_84_0[0] = myVar[0]; + var_84_1[1] = myVar[1]; + var_84_2[2] = myVar[2]; + var_84_3[3] = myVar[3]; + var_84_4[4] = myVar[4]; + var_84_5[5] = myVar[5]; + var_84_6[6] = myVar[6]; + var_84_7[7] = myVar[7]; + var_84_8[8] = myVar[8]; + var_84_9[9] = myVar[9]; + var_84_10[10] = myVar[10]; + var_84_11[11] = myVar[11]; + var_84_12[12] = myVar[12]; + var_84_13[13] = myVar[13]; + var_84_14[14] = myVar[14]; + var_84_15[15] = myVar[15]; + var_84_16[16] = myVar[16]; + var_84_17[17] = myVar[17]; + var_84_18[18] = myVar[18]; + var_84_19[19] = myVar[19]; + +} + +__global__ void kernel_85(float * var_85_0, float * var_85_1, float * var_85_2, float * var_85_3, float * var_85_4, float * var_85_5, float * var_85_6, float * var_85_7, float * var_85_8, float * var_85_9, float * var_85_10, float * var_85_11, float * var_85_12, float * var_85_13, float * var_85_14, float * var_85_15, float * var_85_16, float * var_85_17, float * var_85_18, float * var_85_19) { + __shared__ float myVar[1024]; + myVar[5] = 29.469157 * myVar[threadIdx.x]; + myVar[1] = 8.046192 * myVar[threadIdx.x]; + myVar[6] = 23.251429 * myVar[threadIdx.x]; + myVar[3] = 38.798927 * myVar[threadIdx.x]; + myVar[1] = 5.437214 * myVar[threadIdx.x]; + myVar[9] = 16.948765 * myVar[threadIdx.x]; + myVar[6] = 38.654682 * myVar[threadIdx.x]; + myVar[0] = 39.937615 * myVar[threadIdx.x]; + myVar[1] = 46.182269 * myVar[threadIdx.x]; + myVar[2] = 10.417832 * myVar[threadIdx.x]; + var_85_0[0] = myVar[0]; + var_85_1[1] = myVar[1]; + var_85_2[2] = myVar[2]; + var_85_3[3] = myVar[3]; + var_85_4[4] = myVar[4]; + var_85_5[5] = myVar[5]; + var_85_6[6] = myVar[6]; + var_85_7[7] = myVar[7]; + var_85_8[8] = myVar[8]; + var_85_9[9] = myVar[9]; + var_85_10[10] = myVar[10]; + var_85_11[11] = myVar[11]; + var_85_12[12] = myVar[12]; + var_85_13[13] = myVar[13]; + var_85_14[14] = myVar[14]; + var_85_15[15] = myVar[15]; + var_85_16[16] = myVar[16]; + var_85_17[17] = myVar[17]; + var_85_18[18] = myVar[18]; + var_85_19[19] = myVar[19]; + +} + +__global__ void kernel_86(float * var_86_0, float * var_86_1, float * var_86_2, float * var_86_3, float * var_86_4, float * var_86_5, float * var_86_6, float * var_86_7, float * var_86_8, float * var_86_9, float * var_86_10, float * var_86_11, float * var_86_12, float * var_86_13, float * var_86_14, float * var_86_15, float * var_86_16, float * var_86_17, float * var_86_18, float * var_86_19) { + __shared__ float myVar[1024]; + myVar[7] = 20.686764 * myVar[threadIdx.x]; + myVar[8] = 14.382144 * myVar[threadIdx.x]; + myVar[4] = 2.592520 * myVar[threadIdx.x]; + myVar[8] = 32.843433 * myVar[threadIdx.x]; + myVar[7] = 20.987655 * myVar[threadIdx.x]; + myVar[3] = 19.882539 * myVar[threadIdx.x]; + myVar[8] = 29.850287 * myVar[threadIdx.x]; + myVar[2] = 37.142193 * myVar[threadIdx.x]; + myVar[7] = 15.355836 * myVar[threadIdx.x]; + myVar[2] = 31.991174 * myVar[threadIdx.x]; + var_86_0[0] = myVar[0]; + var_86_1[1] = myVar[1]; + var_86_2[2] = myVar[2]; + var_86_3[3] = myVar[3]; + var_86_4[4] = myVar[4]; + var_86_5[5] = myVar[5]; + var_86_6[6] = myVar[6]; + var_86_7[7] = myVar[7]; + var_86_8[8] = myVar[8]; + var_86_9[9] = myVar[9]; + var_86_10[10] = myVar[10]; + var_86_11[11] = myVar[11]; + var_86_12[12] = myVar[12]; + var_86_13[13] = myVar[13]; + var_86_14[14] = myVar[14]; + var_86_15[15] = myVar[15]; + var_86_16[16] = myVar[16]; + var_86_17[17] = myVar[17]; + var_86_18[18] = myVar[18]; + var_86_19[19] = myVar[19]; + +} + +__global__ void kernel_87(float * var_87_0, float * var_87_1, float * var_87_2, float * var_87_3, float * var_87_4, float * var_87_5, float * var_87_6, float * var_87_7, float * var_87_8, float * var_87_9, float * var_87_10, float * var_87_11, float * var_87_12, float * var_87_13, float * var_87_14, float * var_87_15, float * var_87_16, float * var_87_17, float * var_87_18, float * var_87_19) { + __shared__ float myVar[1024]; + myVar[0] = 17.818198 * myVar[threadIdx.x]; + myVar[7] = 17.292375 * myVar[threadIdx.x]; + myVar[3] = 9.408437 * myVar[threadIdx.x]; + myVar[0] = 35.787921 * myVar[threadIdx.x]; + myVar[7] = 31.576850 * myVar[threadIdx.x]; + myVar[0] = 43.302253 * myVar[threadIdx.x]; + myVar[5] = 45.580790 * myVar[threadIdx.x]; + myVar[5] = 38.798559 * myVar[threadIdx.x]; + myVar[0] = 16.410893 * myVar[threadIdx.x]; + myVar[6] = 8.753178 * myVar[threadIdx.x]; + var_87_0[0] = myVar[0]; + var_87_1[1] = myVar[1]; + var_87_2[2] = myVar[2]; + var_87_3[3] = myVar[3]; + var_87_4[4] = myVar[4]; + var_87_5[5] = myVar[5]; + var_87_6[6] = myVar[6]; + var_87_7[7] = myVar[7]; + var_87_8[8] = myVar[8]; + var_87_9[9] = myVar[9]; + var_87_10[10] = myVar[10]; + var_87_11[11] = myVar[11]; + var_87_12[12] = myVar[12]; + var_87_13[13] = myVar[13]; + var_87_14[14] = myVar[14]; + var_87_15[15] = myVar[15]; + var_87_16[16] = myVar[16]; + var_87_17[17] = myVar[17]; + var_87_18[18] = myVar[18]; + var_87_19[19] = myVar[19]; + +} + +__global__ void kernel_88(float * var_88_0, float * var_88_1, float * var_88_2, float * var_88_3, float * var_88_4, float * var_88_5, float * var_88_6, float * var_88_7, float * var_88_8, float * var_88_9, float * var_88_10, float * var_88_11, float * var_88_12, float * var_88_13, float * var_88_14, float * var_88_15, float * var_88_16, float * var_88_17, float * var_88_18, float * var_88_19) { + __shared__ float myVar[1024]; + myVar[7] = 3.302447 * myVar[threadIdx.x]; + myVar[8] = 32.859062 * myVar[threadIdx.x]; + myVar[5] = 6.183310 * myVar[threadIdx.x]; + myVar[8] = 34.710643 * myVar[threadIdx.x]; + myVar[1] = 37.096195 * myVar[threadIdx.x]; + myVar[1] = 43.159629 * myVar[threadIdx.x]; + myVar[8] = 10.165780 * myVar[threadIdx.x]; + myVar[9] = 46.500045 * myVar[threadIdx.x]; + myVar[3] = 16.006992 * myVar[threadIdx.x]; + myVar[8] = 8.909091 * myVar[threadIdx.x]; + var_88_0[0] = myVar[0]; + var_88_1[1] = myVar[1]; + var_88_2[2] = myVar[2]; + var_88_3[3] = myVar[3]; + var_88_4[4] = myVar[4]; + var_88_5[5] = myVar[5]; + var_88_6[6] = myVar[6]; + var_88_7[7] = myVar[7]; + var_88_8[8] = myVar[8]; + var_88_9[9] = myVar[9]; + var_88_10[10] = myVar[10]; + var_88_11[11] = myVar[11]; + var_88_12[12] = myVar[12]; + var_88_13[13] = myVar[13]; + var_88_14[14] = myVar[14]; + var_88_15[15] = myVar[15]; + var_88_16[16] = myVar[16]; + var_88_17[17] = myVar[17]; + var_88_18[18] = myVar[18]; + var_88_19[19] = myVar[19]; + +} + +__global__ void kernel_89(float * var_89_0, float * var_89_1, float * var_89_2, float * var_89_3, float * var_89_4, float * var_89_5, float * var_89_6, float * var_89_7, float * var_89_8, float * var_89_9, float * var_89_10, float * var_89_11, float * var_89_12, float * var_89_13, float * var_89_14, float * var_89_15, float * var_89_16, float * var_89_17, float * var_89_18, float * var_89_19) { + __shared__ float myVar[1024]; + myVar[2] = 8.884512 * myVar[threadIdx.x]; + myVar[2] = 26.835709 * myVar[threadIdx.x]; + myVar[9] = 24.787851 * myVar[threadIdx.x]; + myVar[9] = 11.447755 * myVar[threadIdx.x]; + myVar[5] = 46.979558 * myVar[threadIdx.x]; + myVar[5] = 10.651160 * myVar[threadIdx.x]; + myVar[7] = 3.243080 * myVar[threadIdx.x]; + myVar[2] = 31.164741 * myVar[threadIdx.x]; + myVar[5] = 36.848732 * myVar[threadIdx.x]; + myVar[8] = 10.391745 * myVar[threadIdx.x]; + var_89_0[0] = myVar[0]; + var_89_1[1] = myVar[1]; + var_89_2[2] = myVar[2]; + var_89_3[3] = myVar[3]; + var_89_4[4] = myVar[4]; + var_89_5[5] = myVar[5]; + var_89_6[6] = myVar[6]; + var_89_7[7] = myVar[7]; + var_89_8[8] = myVar[8]; + var_89_9[9] = myVar[9]; + var_89_10[10] = myVar[10]; + var_89_11[11] = myVar[11]; + var_89_12[12] = myVar[12]; + var_89_13[13] = myVar[13]; + var_89_14[14] = myVar[14]; + var_89_15[15] = myVar[15]; + var_89_16[16] = myVar[16]; + var_89_17[17] = myVar[17]; + var_89_18[18] = myVar[18]; + var_89_19[19] = myVar[19]; + +} + +__global__ void kernel_90(float * var_90_0, float * var_90_1, float * var_90_2, float * var_90_3, float * var_90_4, float * var_90_5, float * var_90_6, float * var_90_7, float * var_90_8, float * var_90_9, float * var_90_10, float * var_90_11, float * var_90_12, float * var_90_13, float * var_90_14, float * var_90_15, float * var_90_16, float * var_90_17, float * var_90_18, float * var_90_19) { + __shared__ float myVar[1024]; + myVar[8] = 20.418554 * myVar[threadIdx.x]; + myVar[9] = 8.802054 * myVar[threadIdx.x]; + myVar[7] = 43.815346 * myVar[threadIdx.x]; + myVar[4] = 45.765129 * myVar[threadIdx.x]; + myVar[6] = 8.567715 * myVar[threadIdx.x]; + myVar[0] = 27.280536 * myVar[threadIdx.x]; + myVar[3] = 44.621018 * myVar[threadIdx.x]; + myVar[8] = 40.014008 * myVar[threadIdx.x]; + myVar[6] = 7.637198 * myVar[threadIdx.x]; + myVar[4] = 10.862993 * myVar[threadIdx.x]; + var_90_0[0] = myVar[0]; + var_90_1[1] = myVar[1]; + var_90_2[2] = myVar[2]; + var_90_3[3] = myVar[3]; + var_90_4[4] = myVar[4]; + var_90_5[5] = myVar[5]; + var_90_6[6] = myVar[6]; + var_90_7[7] = myVar[7]; + var_90_8[8] = myVar[8]; + var_90_9[9] = myVar[9]; + var_90_10[10] = myVar[10]; + var_90_11[11] = myVar[11]; + var_90_12[12] = myVar[12]; + var_90_13[13] = myVar[13]; + var_90_14[14] = myVar[14]; + var_90_15[15] = myVar[15]; + var_90_16[16] = myVar[16]; + var_90_17[17] = myVar[17]; + var_90_18[18] = myVar[18]; + var_90_19[19] = myVar[19]; + +} + +__global__ void kernel_91(float * var_91_0, float * var_91_1, float * var_91_2, float * var_91_3, float * var_91_4, float * var_91_5, float * var_91_6, float * var_91_7, float * var_91_8, float * var_91_9, float * var_91_10, float * var_91_11, float * var_91_12, float * var_91_13, float * var_91_14, float * var_91_15, float * var_91_16, float * var_91_17, float * var_91_18, float * var_91_19) { + __shared__ float myVar[1024]; + myVar[5] = 10.636806 * myVar[threadIdx.x]; + myVar[6] = 25.575829 * myVar[threadIdx.x]; + myVar[7] = 26.068188 * myVar[threadIdx.x]; + myVar[4] = 48.151045 * myVar[threadIdx.x]; + myVar[0] = 4.807278 * myVar[threadIdx.x]; + myVar[6] = 14.784279 * myVar[threadIdx.x]; + myVar[7] = 49.478457 * myVar[threadIdx.x]; + myVar[6] = 5.982118 * myVar[threadIdx.x]; + myVar[7] = 0.298905 * myVar[threadIdx.x]; + myVar[6] = 33.926429 * myVar[threadIdx.x]; + var_91_0[0] = myVar[0]; + var_91_1[1] = myVar[1]; + var_91_2[2] = myVar[2]; + var_91_3[3] = myVar[3]; + var_91_4[4] = myVar[4]; + var_91_5[5] = myVar[5]; + var_91_6[6] = myVar[6]; + var_91_7[7] = myVar[7]; + var_91_8[8] = myVar[8]; + var_91_9[9] = myVar[9]; + var_91_10[10] = myVar[10]; + var_91_11[11] = myVar[11]; + var_91_12[12] = myVar[12]; + var_91_13[13] = myVar[13]; + var_91_14[14] = myVar[14]; + var_91_15[15] = myVar[15]; + var_91_16[16] = myVar[16]; + var_91_17[17] = myVar[17]; + var_91_18[18] = myVar[18]; + var_91_19[19] = myVar[19]; + +} + +__global__ void kernel_92(float * var_92_0, float * var_92_1, float * var_92_2, float * var_92_3, float * var_92_4, float * var_92_5, float * var_92_6, float * var_92_7, float * var_92_8, float * var_92_9, float * var_92_10, float * var_92_11, float * var_92_12, float * var_92_13, float * var_92_14, float * var_92_15, float * var_92_16, float * var_92_17, float * var_92_18, float * var_92_19) { + __shared__ float myVar[1024]; + myVar[1] = 27.983791 * myVar[threadIdx.x]; + myVar[4] = 48.063810 * myVar[threadIdx.x]; + myVar[4] = 3.419796 * myVar[threadIdx.x]; + myVar[9] = 3.814167 * myVar[threadIdx.x]; + myVar[6] = 49.538755 * myVar[threadIdx.x]; + myVar[8] = 14.594070 * myVar[threadIdx.x]; + myVar[8] = 0.899012 * myVar[threadIdx.x]; + myVar[0] = 28.691193 * myVar[threadIdx.x]; + myVar[2] = 22.566337 * myVar[threadIdx.x]; + myVar[6] = 26.554205 * myVar[threadIdx.x]; + var_92_0[0] = myVar[0]; + var_92_1[1] = myVar[1]; + var_92_2[2] = myVar[2]; + var_92_3[3] = myVar[3]; + var_92_4[4] = myVar[4]; + var_92_5[5] = myVar[5]; + var_92_6[6] = myVar[6]; + var_92_7[7] = myVar[7]; + var_92_8[8] = myVar[8]; + var_92_9[9] = myVar[9]; + var_92_10[10] = myVar[10]; + var_92_11[11] = myVar[11]; + var_92_12[12] = myVar[12]; + var_92_13[13] = myVar[13]; + var_92_14[14] = myVar[14]; + var_92_15[15] = myVar[15]; + var_92_16[16] = myVar[16]; + var_92_17[17] = myVar[17]; + var_92_18[18] = myVar[18]; + var_92_19[19] = myVar[19]; + +} + +__global__ void kernel_93(float * var_93_0, float * var_93_1, float * var_93_2, float * var_93_3, float * var_93_4, float * var_93_5, float * var_93_6, float * var_93_7, float * var_93_8, float * var_93_9, float * var_93_10, float * var_93_11, float * var_93_12, float * var_93_13, float * var_93_14, float * var_93_15, float * var_93_16, float * var_93_17, float * var_93_18, float * var_93_19) { + __shared__ float myVar[1024]; + myVar[7] = 25.247132 * myVar[threadIdx.x]; + myVar[7] = 35.564602 * myVar[threadIdx.x]; + myVar[1] = 19.893224 * myVar[threadIdx.x]; + myVar[4] = 38.999653 * myVar[threadIdx.x]; + myVar[3] = 32.827499 * myVar[threadIdx.x]; + myVar[8] = 37.567465 * myVar[threadIdx.x]; + myVar[2] = 32.180819 * myVar[threadIdx.x]; + myVar[5] = 29.349211 * myVar[threadIdx.x]; + myVar[6] = 47.392912 * myVar[threadIdx.x]; + myVar[7] = 23.877738 * myVar[threadIdx.x]; + var_93_0[0] = myVar[0]; + var_93_1[1] = myVar[1]; + var_93_2[2] = myVar[2]; + var_93_3[3] = myVar[3]; + var_93_4[4] = myVar[4]; + var_93_5[5] = myVar[5]; + var_93_6[6] = myVar[6]; + var_93_7[7] = myVar[7]; + var_93_8[8] = myVar[8]; + var_93_9[9] = myVar[9]; + var_93_10[10] = myVar[10]; + var_93_11[11] = myVar[11]; + var_93_12[12] = myVar[12]; + var_93_13[13] = myVar[13]; + var_93_14[14] = myVar[14]; + var_93_15[15] = myVar[15]; + var_93_16[16] = myVar[16]; + var_93_17[17] = myVar[17]; + var_93_18[18] = myVar[18]; + var_93_19[19] = myVar[19]; + +} + +__global__ void kernel_94(float * var_94_0, float * var_94_1, float * var_94_2, float * var_94_3, float * var_94_4, float * var_94_5, float * var_94_6, float * var_94_7, float * var_94_8, float * var_94_9, float * var_94_10, float * var_94_11, float * var_94_12, float * var_94_13, float * var_94_14, float * var_94_15, float * var_94_16, float * var_94_17, float * var_94_18, float * var_94_19) { + __shared__ float myVar[1024]; + myVar[9] = 22.970190 * myVar[threadIdx.x]; + myVar[9] = 0.697030 * myVar[threadIdx.x]; + myVar[2] = 27.841112 * myVar[threadIdx.x]; + myVar[8] = 8.810656 * myVar[threadIdx.x]; + myVar[3] = 17.252632 * myVar[threadIdx.x]; + myVar[2] = 15.302823 * myVar[threadIdx.x]; + myVar[7] = 43.331670 * myVar[threadIdx.x]; + myVar[6] = 36.704199 * myVar[threadIdx.x]; + myVar[2] = 30.115334 * myVar[threadIdx.x]; + myVar[3] = 2.212627 * myVar[threadIdx.x]; + var_94_0[0] = myVar[0]; + var_94_1[1] = myVar[1]; + var_94_2[2] = myVar[2]; + var_94_3[3] = myVar[3]; + var_94_4[4] = myVar[4]; + var_94_5[5] = myVar[5]; + var_94_6[6] = myVar[6]; + var_94_7[7] = myVar[7]; + var_94_8[8] = myVar[8]; + var_94_9[9] = myVar[9]; + var_94_10[10] = myVar[10]; + var_94_11[11] = myVar[11]; + var_94_12[12] = myVar[12]; + var_94_13[13] = myVar[13]; + var_94_14[14] = myVar[14]; + var_94_15[15] = myVar[15]; + var_94_16[16] = myVar[16]; + var_94_17[17] = myVar[17]; + var_94_18[18] = myVar[18]; + var_94_19[19] = myVar[19]; + +} + +__global__ void kernel_95(float * var_95_0, float * var_95_1, float * var_95_2, float * var_95_3, float * var_95_4, float * var_95_5, float * var_95_6, float * var_95_7, float * var_95_8, float * var_95_9, float * var_95_10, float * var_95_11, float * var_95_12, float * var_95_13, float * var_95_14, float * var_95_15, float * var_95_16, float * var_95_17, float * var_95_18, float * var_95_19) { + __shared__ float myVar[1024]; + myVar[0] = 24.147069 * myVar[threadIdx.x]; + myVar[8] = 10.496619 * myVar[threadIdx.x]; + myVar[0] = 36.443158 * myVar[threadIdx.x]; + myVar[0] = 17.904213 * myVar[threadIdx.x]; + myVar[1] = 49.766844 * myVar[threadIdx.x]; + myVar[9] = 17.379044 * myVar[threadIdx.x]; + myVar[6] = 32.826730 * myVar[threadIdx.x]; + myVar[4] = 44.411972 * myVar[threadIdx.x]; + myVar[5] = 26.416494 * myVar[threadIdx.x]; + myVar[5] = 21.628386 * myVar[threadIdx.x]; + var_95_0[0] = myVar[0]; + var_95_1[1] = myVar[1]; + var_95_2[2] = myVar[2]; + var_95_3[3] = myVar[3]; + var_95_4[4] = myVar[4]; + var_95_5[5] = myVar[5]; + var_95_6[6] = myVar[6]; + var_95_7[7] = myVar[7]; + var_95_8[8] = myVar[8]; + var_95_9[9] = myVar[9]; + var_95_10[10] = myVar[10]; + var_95_11[11] = myVar[11]; + var_95_12[12] = myVar[12]; + var_95_13[13] = myVar[13]; + var_95_14[14] = myVar[14]; + var_95_15[15] = myVar[15]; + var_95_16[16] = myVar[16]; + var_95_17[17] = myVar[17]; + var_95_18[18] = myVar[18]; + var_95_19[19] = myVar[19]; + +} + +__global__ void kernel_96(float * var_96_0, float * var_96_1, float * var_96_2, float * var_96_3, float * var_96_4, float * var_96_5, float * var_96_6, float * var_96_7, float * var_96_8, float * var_96_9, float * var_96_10, float * var_96_11, float * var_96_12, float * var_96_13, float * var_96_14, float * var_96_15, float * var_96_16, float * var_96_17, float * var_96_18, float * var_96_19) { + __shared__ float myVar[1024]; + myVar[8] = 13.596222 * myVar[threadIdx.x]; + myVar[9] = 35.570629 * myVar[threadIdx.x]; + myVar[3] = 6.256915 * myVar[threadIdx.x]; + myVar[1] = 35.742467 * myVar[threadIdx.x]; + myVar[0] = 21.909653 * myVar[threadIdx.x]; + myVar[9] = 23.225823 * myVar[threadIdx.x]; + myVar[9] = 41.822623 * myVar[threadIdx.x]; + myVar[4] = 49.545857 * myVar[threadIdx.x]; + myVar[6] = 14.578220 * myVar[threadIdx.x]; + myVar[5] = 26.371621 * myVar[threadIdx.x]; + var_96_0[0] = myVar[0]; + var_96_1[1] = myVar[1]; + var_96_2[2] = myVar[2]; + var_96_3[3] = myVar[3]; + var_96_4[4] = myVar[4]; + var_96_5[5] = myVar[5]; + var_96_6[6] = myVar[6]; + var_96_7[7] = myVar[7]; + var_96_8[8] = myVar[8]; + var_96_9[9] = myVar[9]; + var_96_10[10] = myVar[10]; + var_96_11[11] = myVar[11]; + var_96_12[12] = myVar[12]; + var_96_13[13] = myVar[13]; + var_96_14[14] = myVar[14]; + var_96_15[15] = myVar[15]; + var_96_16[16] = myVar[16]; + var_96_17[17] = myVar[17]; + var_96_18[18] = myVar[18]; + var_96_19[19] = myVar[19]; + +} + +__global__ void kernel_97(float * var_97_0, float * var_97_1, float * var_97_2, float * var_97_3, float * var_97_4, float * var_97_5, float * var_97_6, float * var_97_7, float * var_97_8, float * var_97_9, float * var_97_10, float * var_97_11, float * var_97_12, float * var_97_13, float * var_97_14, float * var_97_15, float * var_97_16, float * var_97_17, float * var_97_18, float * var_97_19) { + __shared__ float myVar[1024]; + myVar[3] = 7.616703 * myVar[threadIdx.x]; + myVar[3] = 24.963788 * myVar[threadIdx.x]; + myVar[9] = 32.178852 * myVar[threadIdx.x]; + myVar[8] = 14.660428 * myVar[threadIdx.x]; + myVar[1] = 10.423802 * myVar[threadIdx.x]; + myVar[5] = 34.645808 * myVar[threadIdx.x]; + myVar[8] = 7.513570 * myVar[threadIdx.x]; + myVar[5] = 19.526371 * myVar[threadIdx.x]; + myVar[5] = 8.128375 * myVar[threadIdx.x]; + myVar[7] = 27.257317 * myVar[threadIdx.x]; + var_97_0[0] = myVar[0]; + var_97_1[1] = myVar[1]; + var_97_2[2] = myVar[2]; + var_97_3[3] = myVar[3]; + var_97_4[4] = myVar[4]; + var_97_5[5] = myVar[5]; + var_97_6[6] = myVar[6]; + var_97_7[7] = myVar[7]; + var_97_8[8] = myVar[8]; + var_97_9[9] = myVar[9]; + var_97_10[10] = myVar[10]; + var_97_11[11] = myVar[11]; + var_97_12[12] = myVar[12]; + var_97_13[13] = myVar[13]; + var_97_14[14] = myVar[14]; + var_97_15[15] = myVar[15]; + var_97_16[16] = myVar[16]; + var_97_17[17] = myVar[17]; + var_97_18[18] = myVar[18]; + var_97_19[19] = myVar[19]; + +} + +__global__ void kernel_98(float * var_98_0, float * var_98_1, float * var_98_2, float * var_98_3, float * var_98_4, float * var_98_5, float * var_98_6, float * var_98_7, float * var_98_8, float * var_98_9, float * var_98_10, float * var_98_11, float * var_98_12, float * var_98_13, float * var_98_14, float * var_98_15, float * var_98_16, float * var_98_17, float * var_98_18, float * var_98_19) { + __shared__ float myVar[1024]; + myVar[5] = 22.933224 * myVar[threadIdx.x]; + myVar[6] = 33.404707 * myVar[threadIdx.x]; + myVar[1] = 12.560293 * myVar[threadIdx.x]; + myVar[6] = 12.533825 * myVar[threadIdx.x]; + myVar[4] = 8.005213 * myVar[threadIdx.x]; + myVar[2] = 37.231474 * myVar[threadIdx.x]; + myVar[1] = 48.695888 * myVar[threadIdx.x]; + myVar[5] = 43.870667 * myVar[threadIdx.x]; + myVar[1] = 5.068447 * myVar[threadIdx.x]; + myVar[4] = 31.245133 * myVar[threadIdx.x]; + var_98_0[0] = myVar[0]; + var_98_1[1] = myVar[1]; + var_98_2[2] = myVar[2]; + var_98_3[3] = myVar[3]; + var_98_4[4] = myVar[4]; + var_98_5[5] = myVar[5]; + var_98_6[6] = myVar[6]; + var_98_7[7] = myVar[7]; + var_98_8[8] = myVar[8]; + var_98_9[9] = myVar[9]; + var_98_10[10] = myVar[10]; + var_98_11[11] = myVar[11]; + var_98_12[12] = myVar[12]; + var_98_13[13] = myVar[13]; + var_98_14[14] = myVar[14]; + var_98_15[15] = myVar[15]; + var_98_16[16] = myVar[16]; + var_98_17[17] = myVar[17]; + var_98_18[18] = myVar[18]; + var_98_19[19] = myVar[19]; + +} + +__global__ void kernel_99(float * var_99_0, float * var_99_1, float * var_99_2, float * var_99_3, float * var_99_4, float * var_99_5, float * var_99_6, float * var_99_7, float * var_99_8, float * var_99_9, float * var_99_10, float * var_99_11, float * var_99_12, float * var_99_13, float * var_99_14, float * var_99_15, float * var_99_16, float * var_99_17, float * var_99_18, float * var_99_19) { + __shared__ float myVar[1024]; + myVar[6] = 27.205712 * myVar[threadIdx.x]; + myVar[2] = 3.981201 * myVar[threadIdx.x]; + myVar[5] = 37.854242 * myVar[threadIdx.x]; + myVar[8] = 5.116412 * myVar[threadIdx.x]; + myVar[5] = 13.977419 * myVar[threadIdx.x]; + myVar[0] = 40.107187 * myVar[threadIdx.x]; + myVar[0] = 18.660288 * myVar[threadIdx.x]; + myVar[7] = 18.056329 * myVar[threadIdx.x]; + myVar[6] = 12.940238 * myVar[threadIdx.x]; + myVar[8] = 33.224260 * myVar[threadIdx.x]; + var_99_0[0] = myVar[0]; + var_99_1[1] = myVar[1]; + var_99_2[2] = myVar[2]; + var_99_3[3] = myVar[3]; + var_99_4[4] = myVar[4]; + var_99_5[5] = myVar[5]; + var_99_6[6] = myVar[6]; + var_99_7[7] = myVar[7]; + var_99_8[8] = myVar[8]; + var_99_9[9] = myVar[9]; + var_99_10[10] = myVar[10]; + var_99_11[11] = myVar[11]; + var_99_12[12] = myVar[12]; + var_99_13[13] = myVar[13]; + var_99_14[14] = myVar[14]; + var_99_15[15] = myVar[15]; + var_99_16[16] = myVar[16]; + var_99_17[17] = myVar[17]; + var_99_18[18] = myVar[18]; + var_99_19[19] = myVar[19]; + +} + + +int main(void) { + + float * h_var_0_0 = (float *)malloc(sizeof(float *)); + float * d_var_0_0; + cudaMalloc((void **)&d_var_0_0, sizeof(float *)); + + float * h_var_0_1 = (float *)malloc(sizeof(float *)); + float * d_var_0_1; + cudaMalloc((void **)&d_var_0_1, sizeof(float *)); + + float * h_var_0_2 = (float *)malloc(sizeof(float *)); + float * d_var_0_2; + cudaMalloc((void **)&d_var_0_2, sizeof(float *)); + + float * h_var_0_3 = (float *)malloc(sizeof(float *)); + float * d_var_0_3; + cudaMalloc((void **)&d_var_0_3, sizeof(float *)); + + float * h_var_0_4 = (float *)malloc(sizeof(float *)); + float * d_var_0_4; + cudaMalloc((void **)&d_var_0_4, sizeof(float *)); + + float * h_var_0_5 = (float *)malloc(sizeof(float *)); + float * d_var_0_5; + cudaMalloc((void **)&d_var_0_5, sizeof(float *)); + + float * h_var_0_6 = (float *)malloc(sizeof(float *)); + float * d_var_0_6; + cudaMalloc((void **)&d_var_0_6, sizeof(float *)); + + float * h_var_0_7 = (float *)malloc(sizeof(float *)); + float * d_var_0_7; + cudaMalloc((void **)&d_var_0_7, sizeof(float *)); + + float * h_var_0_8 = (float *)malloc(sizeof(float *)); + float * d_var_0_8; + cudaMalloc((void **)&d_var_0_8, sizeof(float *)); + + float * h_var_0_9 = (float *)malloc(sizeof(float *)); + float * d_var_0_9; + cudaMalloc((void **)&d_var_0_9, sizeof(float *)); + + float * h_var_0_10 = (float *)malloc(sizeof(float *)); + float * d_var_0_10; + cudaMalloc((void **)&d_var_0_10, sizeof(float *)); + + float * h_var_0_11 = (float *)malloc(sizeof(float *)); + float * d_var_0_11; + cudaMalloc((void **)&d_var_0_11, sizeof(float *)); + + float * h_var_0_12 = (float *)malloc(sizeof(float *)); + float * d_var_0_12; + cudaMalloc((void **)&d_var_0_12, sizeof(float *)); + + float * h_var_0_13 = (float *)malloc(sizeof(float *)); + float * d_var_0_13; + cudaMalloc((void **)&d_var_0_13, sizeof(float *)); + + float * h_var_0_14 = (float *)malloc(sizeof(float *)); + float * d_var_0_14; + cudaMalloc((void **)&d_var_0_14, sizeof(float *)); + + float * h_var_0_15 = (float *)malloc(sizeof(float *)); + float * d_var_0_15; + cudaMalloc((void **)&d_var_0_15, sizeof(float *)); + + float * h_var_0_16 = (float *)malloc(sizeof(float *)); + float * d_var_0_16; + cudaMalloc((void **)&d_var_0_16, sizeof(float *)); + + float * h_var_0_17 = (float *)malloc(sizeof(float *)); + float * d_var_0_17; + cudaMalloc((void **)&d_var_0_17, sizeof(float *)); + + float * h_var_0_18 = (float *)malloc(sizeof(float *)); + float * d_var_0_18; + cudaMalloc((void **)&d_var_0_18, sizeof(float *)); + + float * h_var_0_19 = (float *)malloc(sizeof(float *)); + float * d_var_0_19; + cudaMalloc((void **)&d_var_0_19, sizeof(float *)); + + float * h_var_1_0 = (float *)malloc(sizeof(float *)); + float * d_var_1_0; + cudaMalloc((void **)&d_var_1_0, sizeof(float *)); + + float * h_var_1_1 = (float *)malloc(sizeof(float *)); + float * d_var_1_1; + cudaMalloc((void **)&d_var_1_1, sizeof(float *)); + + float * h_var_1_2 = (float *)malloc(sizeof(float *)); + float * d_var_1_2; + cudaMalloc((void **)&d_var_1_2, sizeof(float *)); + + float * h_var_1_3 = (float *)malloc(sizeof(float *)); + float * d_var_1_3; + cudaMalloc((void **)&d_var_1_3, sizeof(float *)); + + float * h_var_1_4 = (float *)malloc(sizeof(float *)); + float * d_var_1_4; + cudaMalloc((void **)&d_var_1_4, sizeof(float *)); + + float * h_var_1_5 = (float *)malloc(sizeof(float *)); + float * d_var_1_5; + cudaMalloc((void **)&d_var_1_5, sizeof(float *)); + + float * h_var_1_6 = (float *)malloc(sizeof(float *)); + float * d_var_1_6; + cudaMalloc((void **)&d_var_1_6, sizeof(float *)); + + float * h_var_1_7 = (float *)malloc(sizeof(float *)); + float * d_var_1_7; + cudaMalloc((void **)&d_var_1_7, sizeof(float *)); + + float * h_var_1_8 = (float *)malloc(sizeof(float *)); + float * d_var_1_8; + cudaMalloc((void **)&d_var_1_8, sizeof(float *)); + + float * h_var_1_9 = (float *)malloc(sizeof(float *)); + float * d_var_1_9; + cudaMalloc((void **)&d_var_1_9, sizeof(float *)); + + float * h_var_1_10 = (float *)malloc(sizeof(float *)); + float * d_var_1_10; + cudaMalloc((void **)&d_var_1_10, sizeof(float *)); + + float * h_var_1_11 = (float *)malloc(sizeof(float *)); + float * d_var_1_11; + cudaMalloc((void **)&d_var_1_11, sizeof(float *)); + + float * h_var_1_12 = (float *)malloc(sizeof(float *)); + float * d_var_1_12; + cudaMalloc((void **)&d_var_1_12, sizeof(float *)); + + float * h_var_1_13 = (float *)malloc(sizeof(float *)); + float * d_var_1_13; + cudaMalloc((void **)&d_var_1_13, sizeof(float *)); + + float * h_var_1_14 = (float *)malloc(sizeof(float *)); + float * d_var_1_14; + cudaMalloc((void **)&d_var_1_14, sizeof(float *)); + + float * h_var_1_15 = (float *)malloc(sizeof(float *)); + float * d_var_1_15; + cudaMalloc((void **)&d_var_1_15, sizeof(float *)); + + float * h_var_1_16 = (float *)malloc(sizeof(float *)); + float * d_var_1_16; + cudaMalloc((void **)&d_var_1_16, sizeof(float *)); + + float * h_var_1_17 = (float *)malloc(sizeof(float *)); + float * d_var_1_17; + cudaMalloc((void **)&d_var_1_17, sizeof(float *)); + + float * h_var_1_18 = (float *)malloc(sizeof(float *)); + float * d_var_1_18; + cudaMalloc((void **)&d_var_1_18, sizeof(float *)); + + float * h_var_1_19 = (float *)malloc(sizeof(float *)); + float * d_var_1_19; + cudaMalloc((void **)&d_var_1_19, sizeof(float *)); + + float * h_var_2_0 = (float *)malloc(sizeof(float *)); + float * d_var_2_0; + cudaMalloc((void **)&d_var_2_0, sizeof(float *)); + + float * h_var_2_1 = (float *)malloc(sizeof(float *)); + float * d_var_2_1; + cudaMalloc((void **)&d_var_2_1, sizeof(float *)); + + float * h_var_2_2 = (float *)malloc(sizeof(float *)); + float * d_var_2_2; + cudaMalloc((void **)&d_var_2_2, sizeof(float *)); + + float * h_var_2_3 = (float *)malloc(sizeof(float *)); + float * d_var_2_3; + cudaMalloc((void **)&d_var_2_3, sizeof(float *)); + + float * h_var_2_4 = (float *)malloc(sizeof(float *)); + float * d_var_2_4; + cudaMalloc((void **)&d_var_2_4, sizeof(float *)); + + float * h_var_2_5 = (float *)malloc(sizeof(float *)); + float * d_var_2_5; + cudaMalloc((void **)&d_var_2_5, sizeof(float *)); + + float * h_var_2_6 = (float *)malloc(sizeof(float *)); + float * d_var_2_6; + cudaMalloc((void **)&d_var_2_6, sizeof(float *)); + + float * h_var_2_7 = (float *)malloc(sizeof(float *)); + float * d_var_2_7; + cudaMalloc((void **)&d_var_2_7, sizeof(float *)); + + float * h_var_2_8 = (float *)malloc(sizeof(float *)); + float * d_var_2_8; + cudaMalloc((void **)&d_var_2_8, sizeof(float *)); + + float * h_var_2_9 = (float *)malloc(sizeof(float *)); + float * d_var_2_9; + cudaMalloc((void **)&d_var_2_9, sizeof(float *)); + + float * h_var_2_10 = (float *)malloc(sizeof(float *)); + float * d_var_2_10; + cudaMalloc((void **)&d_var_2_10, sizeof(float *)); + + float * h_var_2_11 = (float *)malloc(sizeof(float *)); + float * d_var_2_11; + cudaMalloc((void **)&d_var_2_11, sizeof(float *)); + + float * h_var_2_12 = (float *)malloc(sizeof(float *)); + float * d_var_2_12; + cudaMalloc((void **)&d_var_2_12, sizeof(float *)); + + float * h_var_2_13 = (float *)malloc(sizeof(float *)); + float * d_var_2_13; + cudaMalloc((void **)&d_var_2_13, sizeof(float *)); + + float * h_var_2_14 = (float *)malloc(sizeof(float *)); + float * d_var_2_14; + cudaMalloc((void **)&d_var_2_14, sizeof(float *)); + + float * h_var_2_15 = (float *)malloc(sizeof(float *)); + float * d_var_2_15; + cudaMalloc((void **)&d_var_2_15, sizeof(float *)); + + float * h_var_2_16 = (float *)malloc(sizeof(float *)); + float * d_var_2_16; + cudaMalloc((void **)&d_var_2_16, sizeof(float *)); + + float * h_var_2_17 = (float *)malloc(sizeof(float *)); + float * d_var_2_17; + cudaMalloc((void **)&d_var_2_17, sizeof(float *)); + + float * h_var_2_18 = (float *)malloc(sizeof(float *)); + float * d_var_2_18; + cudaMalloc((void **)&d_var_2_18, sizeof(float *)); + + float * h_var_2_19 = (float *)malloc(sizeof(float *)); + float * d_var_2_19; + cudaMalloc((void **)&d_var_2_19, sizeof(float *)); + + float * h_var_3_0 = (float *)malloc(sizeof(float *)); + float * d_var_3_0; + cudaMalloc((void **)&d_var_3_0, sizeof(float *)); + + float * h_var_3_1 = (float *)malloc(sizeof(float *)); + float * d_var_3_1; + cudaMalloc((void **)&d_var_3_1, sizeof(float *)); + + float * h_var_3_2 = (float *)malloc(sizeof(float *)); + float * d_var_3_2; + cudaMalloc((void **)&d_var_3_2, sizeof(float *)); + + float * h_var_3_3 = (float *)malloc(sizeof(float *)); + float * d_var_3_3; + cudaMalloc((void **)&d_var_3_3, sizeof(float *)); + + float * h_var_3_4 = (float *)malloc(sizeof(float *)); + float * d_var_3_4; + cudaMalloc((void **)&d_var_3_4, sizeof(float *)); + + float * h_var_3_5 = (float *)malloc(sizeof(float *)); + float * d_var_3_5; + cudaMalloc((void **)&d_var_3_5, sizeof(float *)); + + float * h_var_3_6 = (float *)malloc(sizeof(float *)); + float * d_var_3_6; + cudaMalloc((void **)&d_var_3_6, sizeof(float *)); + + float * h_var_3_7 = (float *)malloc(sizeof(float *)); + float * d_var_3_7; + cudaMalloc((void **)&d_var_3_7, sizeof(float *)); + + float * h_var_3_8 = (float *)malloc(sizeof(float *)); + float * d_var_3_8; + cudaMalloc((void **)&d_var_3_8, sizeof(float *)); + + float * h_var_3_9 = (float *)malloc(sizeof(float *)); + float * d_var_3_9; + cudaMalloc((void **)&d_var_3_9, sizeof(float *)); + + float * h_var_3_10 = (float *)malloc(sizeof(float *)); + float * d_var_3_10; + cudaMalloc((void **)&d_var_3_10, sizeof(float *)); + + float * h_var_3_11 = (float *)malloc(sizeof(float *)); + float * d_var_3_11; + cudaMalloc((void **)&d_var_3_11, sizeof(float *)); + + float * h_var_3_12 = (float *)malloc(sizeof(float *)); + float * d_var_3_12; + cudaMalloc((void **)&d_var_3_12, sizeof(float *)); + + float * h_var_3_13 = (float *)malloc(sizeof(float *)); + float * d_var_3_13; + cudaMalloc((void **)&d_var_3_13, sizeof(float *)); + + float * h_var_3_14 = (float *)malloc(sizeof(float *)); + float * d_var_3_14; + cudaMalloc((void **)&d_var_3_14, sizeof(float *)); + + float * h_var_3_15 = (float *)malloc(sizeof(float *)); + float * d_var_3_15; + cudaMalloc((void **)&d_var_3_15, sizeof(float *)); + + float * h_var_3_16 = (float *)malloc(sizeof(float *)); + float * d_var_3_16; + cudaMalloc((void **)&d_var_3_16, sizeof(float *)); + + float * h_var_3_17 = (float *)malloc(sizeof(float *)); + float * d_var_3_17; + cudaMalloc((void **)&d_var_3_17, sizeof(float *)); + + float * h_var_3_18 = (float *)malloc(sizeof(float *)); + float * d_var_3_18; + cudaMalloc((void **)&d_var_3_18, sizeof(float *)); + + float * h_var_3_19 = (float *)malloc(sizeof(float *)); + float * d_var_3_19; + cudaMalloc((void **)&d_var_3_19, sizeof(float *)); + + float * h_var_4_0 = (float *)malloc(sizeof(float *)); + float * d_var_4_0; + cudaMalloc((void **)&d_var_4_0, sizeof(float *)); + + float * h_var_4_1 = (float *)malloc(sizeof(float *)); + float * d_var_4_1; + cudaMalloc((void **)&d_var_4_1, sizeof(float *)); + + float * h_var_4_2 = (float *)malloc(sizeof(float *)); + float * d_var_4_2; + cudaMalloc((void **)&d_var_4_2, sizeof(float *)); + + float * h_var_4_3 = (float *)malloc(sizeof(float *)); + float * d_var_4_3; + cudaMalloc((void **)&d_var_4_3, sizeof(float *)); + + float * h_var_4_4 = (float *)malloc(sizeof(float *)); + float * d_var_4_4; + cudaMalloc((void **)&d_var_4_4, sizeof(float *)); + + float * h_var_4_5 = (float *)malloc(sizeof(float *)); + float * d_var_4_5; + cudaMalloc((void **)&d_var_4_5, sizeof(float *)); + + float * h_var_4_6 = (float *)malloc(sizeof(float *)); + float * d_var_4_6; + cudaMalloc((void **)&d_var_4_6, sizeof(float *)); + + float * h_var_4_7 = (float *)malloc(sizeof(float *)); + float * d_var_4_7; + cudaMalloc((void **)&d_var_4_7, sizeof(float *)); + + float * h_var_4_8 = (float *)malloc(sizeof(float *)); + float * d_var_4_8; + cudaMalloc((void **)&d_var_4_8, sizeof(float *)); + + float * h_var_4_9 = (float *)malloc(sizeof(float *)); + float * d_var_4_9; + cudaMalloc((void **)&d_var_4_9, sizeof(float *)); + + float * h_var_4_10 = (float *)malloc(sizeof(float *)); + float * d_var_4_10; + cudaMalloc((void **)&d_var_4_10, sizeof(float *)); + + float * h_var_4_11 = (float *)malloc(sizeof(float *)); + float * d_var_4_11; + cudaMalloc((void **)&d_var_4_11, sizeof(float *)); + + float * h_var_4_12 = (float *)malloc(sizeof(float *)); + float * d_var_4_12; + cudaMalloc((void **)&d_var_4_12, sizeof(float *)); + + float * h_var_4_13 = (float *)malloc(sizeof(float *)); + float * d_var_4_13; + cudaMalloc((void **)&d_var_4_13, sizeof(float *)); + + float * h_var_4_14 = (float *)malloc(sizeof(float *)); + float * d_var_4_14; + cudaMalloc((void **)&d_var_4_14, sizeof(float *)); + + float * h_var_4_15 = (float *)malloc(sizeof(float *)); + float * d_var_4_15; + cudaMalloc((void **)&d_var_4_15, sizeof(float *)); + + float * h_var_4_16 = (float *)malloc(sizeof(float *)); + float * d_var_4_16; + cudaMalloc((void **)&d_var_4_16, sizeof(float *)); + + float * h_var_4_17 = (float *)malloc(sizeof(float *)); + float * d_var_4_17; + cudaMalloc((void **)&d_var_4_17, sizeof(float *)); + + float * h_var_4_18 = (float *)malloc(sizeof(float *)); + float * d_var_4_18; + cudaMalloc((void **)&d_var_4_18, sizeof(float *)); + + float * h_var_4_19 = (float *)malloc(sizeof(float *)); + float * d_var_4_19; + cudaMalloc((void **)&d_var_4_19, sizeof(float *)); + + float * h_var_5_0 = (float *)malloc(sizeof(float *)); + float * d_var_5_0; + cudaMalloc((void **)&d_var_5_0, sizeof(float *)); + + float * h_var_5_1 = (float *)malloc(sizeof(float *)); + float * d_var_5_1; + cudaMalloc((void **)&d_var_5_1, sizeof(float *)); + + float * h_var_5_2 = (float *)malloc(sizeof(float *)); + float * d_var_5_2; + cudaMalloc((void **)&d_var_5_2, sizeof(float *)); + + float * h_var_5_3 = (float *)malloc(sizeof(float *)); + float * d_var_5_3; + cudaMalloc((void **)&d_var_5_3, sizeof(float *)); + + float * h_var_5_4 = (float *)malloc(sizeof(float *)); + float * d_var_5_4; + cudaMalloc((void **)&d_var_5_4, sizeof(float *)); + + float * h_var_5_5 = (float *)malloc(sizeof(float *)); + float * d_var_5_5; + cudaMalloc((void **)&d_var_5_5, sizeof(float *)); + + float * h_var_5_6 = (float *)malloc(sizeof(float *)); + float * d_var_5_6; + cudaMalloc((void **)&d_var_5_6, sizeof(float *)); + + float * h_var_5_7 = (float *)malloc(sizeof(float *)); + float * d_var_5_7; + cudaMalloc((void **)&d_var_5_7, sizeof(float *)); + + float * h_var_5_8 = (float *)malloc(sizeof(float *)); + float * d_var_5_8; + cudaMalloc((void **)&d_var_5_8, sizeof(float *)); + + float * h_var_5_9 = (float *)malloc(sizeof(float *)); + float * d_var_5_9; + cudaMalloc((void **)&d_var_5_9, sizeof(float *)); + + float * h_var_5_10 = (float *)malloc(sizeof(float *)); + float * d_var_5_10; + cudaMalloc((void **)&d_var_5_10, sizeof(float *)); + + float * h_var_5_11 = (float *)malloc(sizeof(float *)); + float * d_var_5_11; + cudaMalloc((void **)&d_var_5_11, sizeof(float *)); + + float * h_var_5_12 = (float *)malloc(sizeof(float *)); + float * d_var_5_12; + cudaMalloc((void **)&d_var_5_12, sizeof(float *)); + + float * h_var_5_13 = (float *)malloc(sizeof(float *)); + float * d_var_5_13; + cudaMalloc((void **)&d_var_5_13, sizeof(float *)); + + float * h_var_5_14 = (float *)malloc(sizeof(float *)); + float * d_var_5_14; + cudaMalloc((void **)&d_var_5_14, sizeof(float *)); + + float * h_var_5_15 = (float *)malloc(sizeof(float *)); + float * d_var_5_15; + cudaMalloc((void **)&d_var_5_15, sizeof(float *)); + + float * h_var_5_16 = (float *)malloc(sizeof(float *)); + float * d_var_5_16; + cudaMalloc((void **)&d_var_5_16, sizeof(float *)); + + float * h_var_5_17 = (float *)malloc(sizeof(float *)); + float * d_var_5_17; + cudaMalloc((void **)&d_var_5_17, sizeof(float *)); + + float * h_var_5_18 = (float *)malloc(sizeof(float *)); + float * d_var_5_18; + cudaMalloc((void **)&d_var_5_18, sizeof(float *)); + + float * h_var_5_19 = (float *)malloc(sizeof(float *)); + float * d_var_5_19; + cudaMalloc((void **)&d_var_5_19, sizeof(float *)); + + float * h_var_6_0 = (float *)malloc(sizeof(float *)); + float * d_var_6_0; + cudaMalloc((void **)&d_var_6_0, sizeof(float *)); + + float * h_var_6_1 = (float *)malloc(sizeof(float *)); + float * d_var_6_1; + cudaMalloc((void **)&d_var_6_1, sizeof(float *)); + + float * h_var_6_2 = (float *)malloc(sizeof(float *)); + float * d_var_6_2; + cudaMalloc((void **)&d_var_6_2, sizeof(float *)); + + float * h_var_6_3 = (float *)malloc(sizeof(float *)); + float * d_var_6_3; + cudaMalloc((void **)&d_var_6_3, sizeof(float *)); + + float * h_var_6_4 = (float *)malloc(sizeof(float *)); + float * d_var_6_4; + cudaMalloc((void **)&d_var_6_4, sizeof(float *)); + + float * h_var_6_5 = (float *)malloc(sizeof(float *)); + float * d_var_6_5; + cudaMalloc((void **)&d_var_6_5, sizeof(float *)); + + float * h_var_6_6 = (float *)malloc(sizeof(float *)); + float * d_var_6_6; + cudaMalloc((void **)&d_var_6_6, sizeof(float *)); + + float * h_var_6_7 = (float *)malloc(sizeof(float *)); + float * d_var_6_7; + cudaMalloc((void **)&d_var_6_7, sizeof(float *)); + + float * h_var_6_8 = (float *)malloc(sizeof(float *)); + float * d_var_6_8; + cudaMalloc((void **)&d_var_6_8, sizeof(float *)); + + float * h_var_6_9 = (float *)malloc(sizeof(float *)); + float * d_var_6_9; + cudaMalloc((void **)&d_var_6_9, sizeof(float *)); + + float * h_var_6_10 = (float *)malloc(sizeof(float *)); + float * d_var_6_10; + cudaMalloc((void **)&d_var_6_10, sizeof(float *)); + + float * h_var_6_11 = (float *)malloc(sizeof(float *)); + float * d_var_6_11; + cudaMalloc((void **)&d_var_6_11, sizeof(float *)); + + float * h_var_6_12 = (float *)malloc(sizeof(float *)); + float * d_var_6_12; + cudaMalloc((void **)&d_var_6_12, sizeof(float *)); + + float * h_var_6_13 = (float *)malloc(sizeof(float *)); + float * d_var_6_13; + cudaMalloc((void **)&d_var_6_13, sizeof(float *)); + + float * h_var_6_14 = (float *)malloc(sizeof(float *)); + float * d_var_6_14; + cudaMalloc((void **)&d_var_6_14, sizeof(float *)); + + float * h_var_6_15 = (float *)malloc(sizeof(float *)); + float * d_var_6_15; + cudaMalloc((void **)&d_var_6_15, sizeof(float *)); + + float * h_var_6_16 = (float *)malloc(sizeof(float *)); + float * d_var_6_16; + cudaMalloc((void **)&d_var_6_16, sizeof(float *)); + + float * h_var_6_17 = (float *)malloc(sizeof(float *)); + float * d_var_6_17; + cudaMalloc((void **)&d_var_6_17, sizeof(float *)); + + float * h_var_6_18 = (float *)malloc(sizeof(float *)); + float * d_var_6_18; + cudaMalloc((void **)&d_var_6_18, sizeof(float *)); + + float * h_var_6_19 = (float *)malloc(sizeof(float *)); + float * d_var_6_19; + cudaMalloc((void **)&d_var_6_19, sizeof(float *)); + + float * h_var_7_0 = (float *)malloc(sizeof(float *)); + float * d_var_7_0; + cudaMalloc((void **)&d_var_7_0, sizeof(float *)); + + float * h_var_7_1 = (float *)malloc(sizeof(float *)); + float * d_var_7_1; + cudaMalloc((void **)&d_var_7_1, sizeof(float *)); + + float * h_var_7_2 = (float *)malloc(sizeof(float *)); + float * d_var_7_2; + cudaMalloc((void **)&d_var_7_2, sizeof(float *)); + + float * h_var_7_3 = (float *)malloc(sizeof(float *)); + float * d_var_7_3; + cudaMalloc((void **)&d_var_7_3, sizeof(float *)); + + float * h_var_7_4 = (float *)malloc(sizeof(float *)); + float * d_var_7_4; + cudaMalloc((void **)&d_var_7_4, sizeof(float *)); + + float * h_var_7_5 = (float *)malloc(sizeof(float *)); + float * d_var_7_5; + cudaMalloc((void **)&d_var_7_5, sizeof(float *)); + + float * h_var_7_6 = (float *)malloc(sizeof(float *)); + float * d_var_7_6; + cudaMalloc((void **)&d_var_7_6, sizeof(float *)); + + float * h_var_7_7 = (float *)malloc(sizeof(float *)); + float * d_var_7_7; + cudaMalloc((void **)&d_var_7_7, sizeof(float *)); + + float * h_var_7_8 = (float *)malloc(sizeof(float *)); + float * d_var_7_8; + cudaMalloc((void **)&d_var_7_8, sizeof(float *)); + + float * h_var_7_9 = (float *)malloc(sizeof(float *)); + float * d_var_7_9; + cudaMalloc((void **)&d_var_7_9, sizeof(float *)); + + float * h_var_7_10 = (float *)malloc(sizeof(float *)); + float * d_var_7_10; + cudaMalloc((void **)&d_var_7_10, sizeof(float *)); + + float * h_var_7_11 = (float *)malloc(sizeof(float *)); + float * d_var_7_11; + cudaMalloc((void **)&d_var_7_11, sizeof(float *)); + + float * h_var_7_12 = (float *)malloc(sizeof(float *)); + float * d_var_7_12; + cudaMalloc((void **)&d_var_7_12, sizeof(float *)); + + float * h_var_7_13 = (float *)malloc(sizeof(float *)); + float * d_var_7_13; + cudaMalloc((void **)&d_var_7_13, sizeof(float *)); + + float * h_var_7_14 = (float *)malloc(sizeof(float *)); + float * d_var_7_14; + cudaMalloc((void **)&d_var_7_14, sizeof(float *)); + + float * h_var_7_15 = (float *)malloc(sizeof(float *)); + float * d_var_7_15; + cudaMalloc((void **)&d_var_7_15, sizeof(float *)); + + float * h_var_7_16 = (float *)malloc(sizeof(float *)); + float * d_var_7_16; + cudaMalloc((void **)&d_var_7_16, sizeof(float *)); + + float * h_var_7_17 = (float *)malloc(sizeof(float *)); + float * d_var_7_17; + cudaMalloc((void **)&d_var_7_17, sizeof(float *)); + + float * h_var_7_18 = (float *)malloc(sizeof(float *)); + float * d_var_7_18; + cudaMalloc((void **)&d_var_7_18, sizeof(float *)); + + float * h_var_7_19 = (float *)malloc(sizeof(float *)); + float * d_var_7_19; + cudaMalloc((void **)&d_var_7_19, sizeof(float *)); + + float * h_var_8_0 = (float *)malloc(sizeof(float *)); + float * d_var_8_0; + cudaMalloc((void **)&d_var_8_0, sizeof(float *)); + + float * h_var_8_1 = (float *)malloc(sizeof(float *)); + float * d_var_8_1; + cudaMalloc((void **)&d_var_8_1, sizeof(float *)); + + float * h_var_8_2 = (float *)malloc(sizeof(float *)); + float * d_var_8_2; + cudaMalloc((void **)&d_var_8_2, sizeof(float *)); + + float * h_var_8_3 = (float *)malloc(sizeof(float *)); + float * d_var_8_3; + cudaMalloc((void **)&d_var_8_3, sizeof(float *)); + + float * h_var_8_4 = (float *)malloc(sizeof(float *)); + float * d_var_8_4; + cudaMalloc((void **)&d_var_8_4, sizeof(float *)); + + float * h_var_8_5 = (float *)malloc(sizeof(float *)); + float * d_var_8_5; + cudaMalloc((void **)&d_var_8_5, sizeof(float *)); + + float * h_var_8_6 = (float *)malloc(sizeof(float *)); + float * d_var_8_6; + cudaMalloc((void **)&d_var_8_6, sizeof(float *)); + + float * h_var_8_7 = (float *)malloc(sizeof(float *)); + float * d_var_8_7; + cudaMalloc((void **)&d_var_8_7, sizeof(float *)); + + float * h_var_8_8 = (float *)malloc(sizeof(float *)); + float * d_var_8_8; + cudaMalloc((void **)&d_var_8_8, sizeof(float *)); + + float * h_var_8_9 = (float *)malloc(sizeof(float *)); + float * d_var_8_9; + cudaMalloc((void **)&d_var_8_9, sizeof(float *)); + + float * h_var_8_10 = (float *)malloc(sizeof(float *)); + float * d_var_8_10; + cudaMalloc((void **)&d_var_8_10, sizeof(float *)); + + float * h_var_8_11 = (float *)malloc(sizeof(float *)); + float * d_var_8_11; + cudaMalloc((void **)&d_var_8_11, sizeof(float *)); + + float * h_var_8_12 = (float *)malloc(sizeof(float *)); + float * d_var_8_12; + cudaMalloc((void **)&d_var_8_12, sizeof(float *)); + + float * h_var_8_13 = (float *)malloc(sizeof(float *)); + float * d_var_8_13; + cudaMalloc((void **)&d_var_8_13, sizeof(float *)); + + float * h_var_8_14 = (float *)malloc(sizeof(float *)); + float * d_var_8_14; + cudaMalloc((void **)&d_var_8_14, sizeof(float *)); + + float * h_var_8_15 = (float *)malloc(sizeof(float *)); + float * d_var_8_15; + cudaMalloc((void **)&d_var_8_15, sizeof(float *)); + + float * h_var_8_16 = (float *)malloc(sizeof(float *)); + float * d_var_8_16; + cudaMalloc((void **)&d_var_8_16, sizeof(float *)); + + float * h_var_8_17 = (float *)malloc(sizeof(float *)); + float * d_var_8_17; + cudaMalloc((void **)&d_var_8_17, sizeof(float *)); + + float * h_var_8_18 = (float *)malloc(sizeof(float *)); + float * d_var_8_18; + cudaMalloc((void **)&d_var_8_18, sizeof(float *)); + + float * h_var_8_19 = (float *)malloc(sizeof(float *)); + float * d_var_8_19; + cudaMalloc((void **)&d_var_8_19, sizeof(float *)); + + float * h_var_9_0 = (float *)malloc(sizeof(float *)); + float * d_var_9_0; + cudaMalloc((void **)&d_var_9_0, sizeof(float *)); + + float * h_var_9_1 = (float *)malloc(sizeof(float *)); + float * d_var_9_1; + cudaMalloc((void **)&d_var_9_1, sizeof(float *)); + + float * h_var_9_2 = (float *)malloc(sizeof(float *)); + float * d_var_9_2; + cudaMalloc((void **)&d_var_9_2, sizeof(float *)); + + float * h_var_9_3 = (float *)malloc(sizeof(float *)); + float * d_var_9_3; + cudaMalloc((void **)&d_var_9_3, sizeof(float *)); + + float * h_var_9_4 = (float *)malloc(sizeof(float *)); + float * d_var_9_4; + cudaMalloc((void **)&d_var_9_4, sizeof(float *)); + + float * h_var_9_5 = (float *)malloc(sizeof(float *)); + float * d_var_9_5; + cudaMalloc((void **)&d_var_9_5, sizeof(float *)); + + float * h_var_9_6 = (float *)malloc(sizeof(float *)); + float * d_var_9_6; + cudaMalloc((void **)&d_var_9_6, sizeof(float *)); + + float * h_var_9_7 = (float *)malloc(sizeof(float *)); + float * d_var_9_7; + cudaMalloc((void **)&d_var_9_7, sizeof(float *)); + + float * h_var_9_8 = (float *)malloc(sizeof(float *)); + float * d_var_9_8; + cudaMalloc((void **)&d_var_9_8, sizeof(float *)); + + float * h_var_9_9 = (float *)malloc(sizeof(float *)); + float * d_var_9_9; + cudaMalloc((void **)&d_var_9_9, sizeof(float *)); + + float * h_var_9_10 = (float *)malloc(sizeof(float *)); + float * d_var_9_10; + cudaMalloc((void **)&d_var_9_10, sizeof(float *)); + + float * h_var_9_11 = (float *)malloc(sizeof(float *)); + float * d_var_9_11; + cudaMalloc((void **)&d_var_9_11, sizeof(float *)); + + float * h_var_9_12 = (float *)malloc(sizeof(float *)); + float * d_var_9_12; + cudaMalloc((void **)&d_var_9_12, sizeof(float *)); + + float * h_var_9_13 = (float *)malloc(sizeof(float *)); + float * d_var_9_13; + cudaMalloc((void **)&d_var_9_13, sizeof(float *)); + + float * h_var_9_14 = (float *)malloc(sizeof(float *)); + float * d_var_9_14; + cudaMalloc((void **)&d_var_9_14, sizeof(float *)); + + float * h_var_9_15 = (float *)malloc(sizeof(float *)); + float * d_var_9_15; + cudaMalloc((void **)&d_var_9_15, sizeof(float *)); + + float * h_var_9_16 = (float *)malloc(sizeof(float *)); + float * d_var_9_16; + cudaMalloc((void **)&d_var_9_16, sizeof(float *)); + + float * h_var_9_17 = (float *)malloc(sizeof(float *)); + float * d_var_9_17; + cudaMalloc((void **)&d_var_9_17, sizeof(float *)); + + float * h_var_9_18 = (float *)malloc(sizeof(float *)); + float * d_var_9_18; + cudaMalloc((void **)&d_var_9_18, sizeof(float *)); + + float * h_var_9_19 = (float *)malloc(sizeof(float *)); + float * d_var_9_19; + cudaMalloc((void **)&d_var_9_19, sizeof(float *)); + + float * h_var_10_0 = (float *)malloc(sizeof(float *)); + float * d_var_10_0; + cudaMalloc((void **)&d_var_10_0, sizeof(float *)); + + float * h_var_10_1 = (float *)malloc(sizeof(float *)); + float * d_var_10_1; + cudaMalloc((void **)&d_var_10_1, sizeof(float *)); + + float * h_var_10_2 = (float *)malloc(sizeof(float *)); + float * d_var_10_2; + cudaMalloc((void **)&d_var_10_2, sizeof(float *)); + + float * h_var_10_3 = (float *)malloc(sizeof(float *)); + float * d_var_10_3; + cudaMalloc((void **)&d_var_10_3, sizeof(float *)); + + float * h_var_10_4 = (float *)malloc(sizeof(float *)); + float * d_var_10_4; + cudaMalloc((void **)&d_var_10_4, sizeof(float *)); + + float * h_var_10_5 = (float *)malloc(sizeof(float *)); + float * d_var_10_5; + cudaMalloc((void **)&d_var_10_5, sizeof(float *)); + + float * h_var_10_6 = (float *)malloc(sizeof(float *)); + float * d_var_10_6; + cudaMalloc((void **)&d_var_10_6, sizeof(float *)); + + float * h_var_10_7 = (float *)malloc(sizeof(float *)); + float * d_var_10_7; + cudaMalloc((void **)&d_var_10_7, sizeof(float *)); + + float * h_var_10_8 = (float *)malloc(sizeof(float *)); + float * d_var_10_8; + cudaMalloc((void **)&d_var_10_8, sizeof(float *)); + + float * h_var_10_9 = (float *)malloc(sizeof(float *)); + float * d_var_10_9; + cudaMalloc((void **)&d_var_10_9, sizeof(float *)); + + float * h_var_10_10 = (float *)malloc(sizeof(float *)); + float * d_var_10_10; + cudaMalloc((void **)&d_var_10_10, sizeof(float *)); + + float * h_var_10_11 = (float *)malloc(sizeof(float *)); + float * d_var_10_11; + cudaMalloc((void **)&d_var_10_11, sizeof(float *)); + + float * h_var_10_12 = (float *)malloc(sizeof(float *)); + float * d_var_10_12; + cudaMalloc((void **)&d_var_10_12, sizeof(float *)); + + float * h_var_10_13 = (float *)malloc(sizeof(float *)); + float * d_var_10_13; + cudaMalloc((void **)&d_var_10_13, sizeof(float *)); + + float * h_var_10_14 = (float *)malloc(sizeof(float *)); + float * d_var_10_14; + cudaMalloc((void **)&d_var_10_14, sizeof(float *)); + + float * h_var_10_15 = (float *)malloc(sizeof(float *)); + float * d_var_10_15; + cudaMalloc((void **)&d_var_10_15, sizeof(float *)); + + float * h_var_10_16 = (float *)malloc(sizeof(float *)); + float * d_var_10_16; + cudaMalloc((void **)&d_var_10_16, sizeof(float *)); + + float * h_var_10_17 = (float *)malloc(sizeof(float *)); + float * d_var_10_17; + cudaMalloc((void **)&d_var_10_17, sizeof(float *)); + + float * h_var_10_18 = (float *)malloc(sizeof(float *)); + float * d_var_10_18; + cudaMalloc((void **)&d_var_10_18, sizeof(float *)); + + float * h_var_10_19 = (float *)malloc(sizeof(float *)); + float * d_var_10_19; + cudaMalloc((void **)&d_var_10_19, sizeof(float *)); + + float * h_var_11_0 = (float *)malloc(sizeof(float *)); + float * d_var_11_0; + cudaMalloc((void **)&d_var_11_0, sizeof(float *)); + + float * h_var_11_1 = (float *)malloc(sizeof(float *)); + float * d_var_11_1; + cudaMalloc((void **)&d_var_11_1, sizeof(float *)); + + float * h_var_11_2 = (float *)malloc(sizeof(float *)); + float * d_var_11_2; + cudaMalloc((void **)&d_var_11_2, sizeof(float *)); + + float * h_var_11_3 = (float *)malloc(sizeof(float *)); + float * d_var_11_3; + cudaMalloc((void **)&d_var_11_3, sizeof(float *)); + + float * h_var_11_4 = (float *)malloc(sizeof(float *)); + float * d_var_11_4; + cudaMalloc((void **)&d_var_11_4, sizeof(float *)); + + float * h_var_11_5 = (float *)malloc(sizeof(float *)); + float * d_var_11_5; + cudaMalloc((void **)&d_var_11_5, sizeof(float *)); + + float * h_var_11_6 = (float *)malloc(sizeof(float *)); + float * d_var_11_6; + cudaMalloc((void **)&d_var_11_6, sizeof(float *)); + + float * h_var_11_7 = (float *)malloc(sizeof(float *)); + float * d_var_11_7; + cudaMalloc((void **)&d_var_11_7, sizeof(float *)); + + float * h_var_11_8 = (float *)malloc(sizeof(float *)); + float * d_var_11_8; + cudaMalloc((void **)&d_var_11_8, sizeof(float *)); + + float * h_var_11_9 = (float *)malloc(sizeof(float *)); + float * d_var_11_9; + cudaMalloc((void **)&d_var_11_9, sizeof(float *)); + + float * h_var_11_10 = (float *)malloc(sizeof(float *)); + float * d_var_11_10; + cudaMalloc((void **)&d_var_11_10, sizeof(float *)); + + float * h_var_11_11 = (float *)malloc(sizeof(float *)); + float * d_var_11_11; + cudaMalloc((void **)&d_var_11_11, sizeof(float *)); + + float * h_var_11_12 = (float *)malloc(sizeof(float *)); + float * d_var_11_12; + cudaMalloc((void **)&d_var_11_12, sizeof(float *)); + + float * h_var_11_13 = (float *)malloc(sizeof(float *)); + float * d_var_11_13; + cudaMalloc((void **)&d_var_11_13, sizeof(float *)); + + float * h_var_11_14 = (float *)malloc(sizeof(float *)); + float * d_var_11_14; + cudaMalloc((void **)&d_var_11_14, sizeof(float *)); + + float * h_var_11_15 = (float *)malloc(sizeof(float *)); + float * d_var_11_15; + cudaMalloc((void **)&d_var_11_15, sizeof(float *)); + + float * h_var_11_16 = (float *)malloc(sizeof(float *)); + float * d_var_11_16; + cudaMalloc((void **)&d_var_11_16, sizeof(float *)); + + float * h_var_11_17 = (float *)malloc(sizeof(float *)); + float * d_var_11_17; + cudaMalloc((void **)&d_var_11_17, sizeof(float *)); + + float * h_var_11_18 = (float *)malloc(sizeof(float *)); + float * d_var_11_18; + cudaMalloc((void **)&d_var_11_18, sizeof(float *)); + + float * h_var_11_19 = (float *)malloc(sizeof(float *)); + float * d_var_11_19; + cudaMalloc((void **)&d_var_11_19, sizeof(float *)); + + float * h_var_12_0 = (float *)malloc(sizeof(float *)); + float * d_var_12_0; + cudaMalloc((void **)&d_var_12_0, sizeof(float *)); + + float * h_var_12_1 = (float *)malloc(sizeof(float *)); + float * d_var_12_1; + cudaMalloc((void **)&d_var_12_1, sizeof(float *)); + + float * h_var_12_2 = (float *)malloc(sizeof(float *)); + float * d_var_12_2; + cudaMalloc((void **)&d_var_12_2, sizeof(float *)); + + float * h_var_12_3 = (float *)malloc(sizeof(float *)); + float * d_var_12_3; + cudaMalloc((void **)&d_var_12_3, sizeof(float *)); + + float * h_var_12_4 = (float *)malloc(sizeof(float *)); + float * d_var_12_4; + cudaMalloc((void **)&d_var_12_4, sizeof(float *)); + + float * h_var_12_5 = (float *)malloc(sizeof(float *)); + float * d_var_12_5; + cudaMalloc((void **)&d_var_12_5, sizeof(float *)); + + float * h_var_12_6 = (float *)malloc(sizeof(float *)); + float * d_var_12_6; + cudaMalloc((void **)&d_var_12_6, sizeof(float *)); + + float * h_var_12_7 = (float *)malloc(sizeof(float *)); + float * d_var_12_7; + cudaMalloc((void **)&d_var_12_7, sizeof(float *)); + + float * h_var_12_8 = (float *)malloc(sizeof(float *)); + float * d_var_12_8; + cudaMalloc((void **)&d_var_12_8, sizeof(float *)); + + float * h_var_12_9 = (float *)malloc(sizeof(float *)); + float * d_var_12_9; + cudaMalloc((void **)&d_var_12_9, sizeof(float *)); + + float * h_var_12_10 = (float *)malloc(sizeof(float *)); + float * d_var_12_10; + cudaMalloc((void **)&d_var_12_10, sizeof(float *)); + + float * h_var_12_11 = (float *)malloc(sizeof(float *)); + float * d_var_12_11; + cudaMalloc((void **)&d_var_12_11, sizeof(float *)); + + float * h_var_12_12 = (float *)malloc(sizeof(float *)); + float * d_var_12_12; + cudaMalloc((void **)&d_var_12_12, sizeof(float *)); + + float * h_var_12_13 = (float *)malloc(sizeof(float *)); + float * d_var_12_13; + cudaMalloc((void **)&d_var_12_13, sizeof(float *)); + + float * h_var_12_14 = (float *)malloc(sizeof(float *)); + float * d_var_12_14; + cudaMalloc((void **)&d_var_12_14, sizeof(float *)); + + float * h_var_12_15 = (float *)malloc(sizeof(float *)); + float * d_var_12_15; + cudaMalloc((void **)&d_var_12_15, sizeof(float *)); + + float * h_var_12_16 = (float *)malloc(sizeof(float *)); + float * d_var_12_16; + cudaMalloc((void **)&d_var_12_16, sizeof(float *)); + + float * h_var_12_17 = (float *)malloc(sizeof(float *)); + float * d_var_12_17; + cudaMalloc((void **)&d_var_12_17, sizeof(float *)); + + float * h_var_12_18 = (float *)malloc(sizeof(float *)); + float * d_var_12_18; + cudaMalloc((void **)&d_var_12_18, sizeof(float *)); + + float * h_var_12_19 = (float *)malloc(sizeof(float *)); + float * d_var_12_19; + cudaMalloc((void **)&d_var_12_19, sizeof(float *)); + + float * h_var_13_0 = (float *)malloc(sizeof(float *)); + float * d_var_13_0; + cudaMalloc((void **)&d_var_13_0, sizeof(float *)); + + float * h_var_13_1 = (float *)malloc(sizeof(float *)); + float * d_var_13_1; + cudaMalloc((void **)&d_var_13_1, sizeof(float *)); + + float * h_var_13_2 = (float *)malloc(sizeof(float *)); + float * d_var_13_2; + cudaMalloc((void **)&d_var_13_2, sizeof(float *)); + + float * h_var_13_3 = (float *)malloc(sizeof(float *)); + float * d_var_13_3; + cudaMalloc((void **)&d_var_13_3, sizeof(float *)); + + float * h_var_13_4 = (float *)malloc(sizeof(float *)); + float * d_var_13_4; + cudaMalloc((void **)&d_var_13_4, sizeof(float *)); + + float * h_var_13_5 = (float *)malloc(sizeof(float *)); + float * d_var_13_5; + cudaMalloc((void **)&d_var_13_5, sizeof(float *)); + + float * h_var_13_6 = (float *)malloc(sizeof(float *)); + float * d_var_13_6; + cudaMalloc((void **)&d_var_13_6, sizeof(float *)); + + float * h_var_13_7 = (float *)malloc(sizeof(float *)); + float * d_var_13_7; + cudaMalloc((void **)&d_var_13_7, sizeof(float *)); + + float * h_var_13_8 = (float *)malloc(sizeof(float *)); + float * d_var_13_8; + cudaMalloc((void **)&d_var_13_8, sizeof(float *)); + + float * h_var_13_9 = (float *)malloc(sizeof(float *)); + float * d_var_13_9; + cudaMalloc((void **)&d_var_13_9, sizeof(float *)); + + float * h_var_13_10 = (float *)malloc(sizeof(float *)); + float * d_var_13_10; + cudaMalloc((void **)&d_var_13_10, sizeof(float *)); + + float * h_var_13_11 = (float *)malloc(sizeof(float *)); + float * d_var_13_11; + cudaMalloc((void **)&d_var_13_11, sizeof(float *)); + + float * h_var_13_12 = (float *)malloc(sizeof(float *)); + float * d_var_13_12; + cudaMalloc((void **)&d_var_13_12, sizeof(float *)); + + float * h_var_13_13 = (float *)malloc(sizeof(float *)); + float * d_var_13_13; + cudaMalloc((void **)&d_var_13_13, sizeof(float *)); + + float * h_var_13_14 = (float *)malloc(sizeof(float *)); + float * d_var_13_14; + cudaMalloc((void **)&d_var_13_14, sizeof(float *)); + + float * h_var_13_15 = (float *)malloc(sizeof(float *)); + float * d_var_13_15; + cudaMalloc((void **)&d_var_13_15, sizeof(float *)); + + float * h_var_13_16 = (float *)malloc(sizeof(float *)); + float * d_var_13_16; + cudaMalloc((void **)&d_var_13_16, sizeof(float *)); + + float * h_var_13_17 = (float *)malloc(sizeof(float *)); + float * d_var_13_17; + cudaMalloc((void **)&d_var_13_17, sizeof(float *)); + + float * h_var_13_18 = (float *)malloc(sizeof(float *)); + float * d_var_13_18; + cudaMalloc((void **)&d_var_13_18, sizeof(float *)); + + float * h_var_13_19 = (float *)malloc(sizeof(float *)); + float * d_var_13_19; + cudaMalloc((void **)&d_var_13_19, sizeof(float *)); + + float * h_var_14_0 = (float *)malloc(sizeof(float *)); + float * d_var_14_0; + cudaMalloc((void **)&d_var_14_0, sizeof(float *)); + + float * h_var_14_1 = (float *)malloc(sizeof(float *)); + float * d_var_14_1; + cudaMalloc((void **)&d_var_14_1, sizeof(float *)); + + float * h_var_14_2 = (float *)malloc(sizeof(float *)); + float * d_var_14_2; + cudaMalloc((void **)&d_var_14_2, sizeof(float *)); + + float * h_var_14_3 = (float *)malloc(sizeof(float *)); + float * d_var_14_3; + cudaMalloc((void **)&d_var_14_3, sizeof(float *)); + + float * h_var_14_4 = (float *)malloc(sizeof(float *)); + float * d_var_14_4; + cudaMalloc((void **)&d_var_14_4, sizeof(float *)); + + float * h_var_14_5 = (float *)malloc(sizeof(float *)); + float * d_var_14_5; + cudaMalloc((void **)&d_var_14_5, sizeof(float *)); + + float * h_var_14_6 = (float *)malloc(sizeof(float *)); + float * d_var_14_6; + cudaMalloc((void **)&d_var_14_6, sizeof(float *)); + + float * h_var_14_7 = (float *)malloc(sizeof(float *)); + float * d_var_14_7; + cudaMalloc((void **)&d_var_14_7, sizeof(float *)); + + float * h_var_14_8 = (float *)malloc(sizeof(float *)); + float * d_var_14_8; + cudaMalloc((void **)&d_var_14_8, sizeof(float *)); + + float * h_var_14_9 = (float *)malloc(sizeof(float *)); + float * d_var_14_9; + cudaMalloc((void **)&d_var_14_9, sizeof(float *)); + + float * h_var_14_10 = (float *)malloc(sizeof(float *)); + float * d_var_14_10; + cudaMalloc((void **)&d_var_14_10, sizeof(float *)); + + float * h_var_14_11 = (float *)malloc(sizeof(float *)); + float * d_var_14_11; + cudaMalloc((void **)&d_var_14_11, sizeof(float *)); + + float * h_var_14_12 = (float *)malloc(sizeof(float *)); + float * d_var_14_12; + cudaMalloc((void **)&d_var_14_12, sizeof(float *)); + + float * h_var_14_13 = (float *)malloc(sizeof(float *)); + float * d_var_14_13; + cudaMalloc((void **)&d_var_14_13, sizeof(float *)); + + float * h_var_14_14 = (float *)malloc(sizeof(float *)); + float * d_var_14_14; + cudaMalloc((void **)&d_var_14_14, sizeof(float *)); + + float * h_var_14_15 = (float *)malloc(sizeof(float *)); + float * d_var_14_15; + cudaMalloc((void **)&d_var_14_15, sizeof(float *)); + + float * h_var_14_16 = (float *)malloc(sizeof(float *)); + float * d_var_14_16; + cudaMalloc((void **)&d_var_14_16, sizeof(float *)); + + float * h_var_14_17 = (float *)malloc(sizeof(float *)); + float * d_var_14_17; + cudaMalloc((void **)&d_var_14_17, sizeof(float *)); + + float * h_var_14_18 = (float *)malloc(sizeof(float *)); + float * d_var_14_18; + cudaMalloc((void **)&d_var_14_18, sizeof(float *)); + + float * h_var_14_19 = (float *)malloc(sizeof(float *)); + float * d_var_14_19; + cudaMalloc((void **)&d_var_14_19, sizeof(float *)); + + float * h_var_15_0 = (float *)malloc(sizeof(float *)); + float * d_var_15_0; + cudaMalloc((void **)&d_var_15_0, sizeof(float *)); + + float * h_var_15_1 = (float *)malloc(sizeof(float *)); + float * d_var_15_1; + cudaMalloc((void **)&d_var_15_1, sizeof(float *)); + + float * h_var_15_2 = (float *)malloc(sizeof(float *)); + float * d_var_15_2; + cudaMalloc((void **)&d_var_15_2, sizeof(float *)); + + float * h_var_15_3 = (float *)malloc(sizeof(float *)); + float * d_var_15_3; + cudaMalloc((void **)&d_var_15_3, sizeof(float *)); + + float * h_var_15_4 = (float *)malloc(sizeof(float *)); + float * d_var_15_4; + cudaMalloc((void **)&d_var_15_4, sizeof(float *)); + + float * h_var_15_5 = (float *)malloc(sizeof(float *)); + float * d_var_15_5; + cudaMalloc((void **)&d_var_15_5, sizeof(float *)); + + float * h_var_15_6 = (float *)malloc(sizeof(float *)); + float * d_var_15_6; + cudaMalloc((void **)&d_var_15_6, sizeof(float *)); + + float * h_var_15_7 = (float *)malloc(sizeof(float *)); + float * d_var_15_7; + cudaMalloc((void **)&d_var_15_7, sizeof(float *)); + + float * h_var_15_8 = (float *)malloc(sizeof(float *)); + float * d_var_15_8; + cudaMalloc((void **)&d_var_15_8, sizeof(float *)); + + float * h_var_15_9 = (float *)malloc(sizeof(float *)); + float * d_var_15_9; + cudaMalloc((void **)&d_var_15_9, sizeof(float *)); + + float * h_var_15_10 = (float *)malloc(sizeof(float *)); + float * d_var_15_10; + cudaMalloc((void **)&d_var_15_10, sizeof(float *)); + + float * h_var_15_11 = (float *)malloc(sizeof(float *)); + float * d_var_15_11; + cudaMalloc((void **)&d_var_15_11, sizeof(float *)); + + float * h_var_15_12 = (float *)malloc(sizeof(float *)); + float * d_var_15_12; + cudaMalloc((void **)&d_var_15_12, sizeof(float *)); + + float * h_var_15_13 = (float *)malloc(sizeof(float *)); + float * d_var_15_13; + cudaMalloc((void **)&d_var_15_13, sizeof(float *)); + + float * h_var_15_14 = (float *)malloc(sizeof(float *)); + float * d_var_15_14; + cudaMalloc((void **)&d_var_15_14, sizeof(float *)); + + float * h_var_15_15 = (float *)malloc(sizeof(float *)); + float * d_var_15_15; + cudaMalloc((void **)&d_var_15_15, sizeof(float *)); + + float * h_var_15_16 = (float *)malloc(sizeof(float *)); + float * d_var_15_16; + cudaMalloc((void **)&d_var_15_16, sizeof(float *)); + + float * h_var_15_17 = (float *)malloc(sizeof(float *)); + float * d_var_15_17; + cudaMalloc((void **)&d_var_15_17, sizeof(float *)); + + float * h_var_15_18 = (float *)malloc(sizeof(float *)); + float * d_var_15_18; + cudaMalloc((void **)&d_var_15_18, sizeof(float *)); + + float * h_var_15_19 = (float *)malloc(sizeof(float *)); + float * d_var_15_19; + cudaMalloc((void **)&d_var_15_19, sizeof(float *)); + + float * h_var_16_0 = (float *)malloc(sizeof(float *)); + float * d_var_16_0; + cudaMalloc((void **)&d_var_16_0, sizeof(float *)); + + float * h_var_16_1 = (float *)malloc(sizeof(float *)); + float * d_var_16_1; + cudaMalloc((void **)&d_var_16_1, sizeof(float *)); + + float * h_var_16_2 = (float *)malloc(sizeof(float *)); + float * d_var_16_2; + cudaMalloc((void **)&d_var_16_2, sizeof(float *)); + + float * h_var_16_3 = (float *)malloc(sizeof(float *)); + float * d_var_16_3; + cudaMalloc((void **)&d_var_16_3, sizeof(float *)); + + float * h_var_16_4 = (float *)malloc(sizeof(float *)); + float * d_var_16_4; + cudaMalloc((void **)&d_var_16_4, sizeof(float *)); + + float * h_var_16_5 = (float *)malloc(sizeof(float *)); + float * d_var_16_5; + cudaMalloc((void **)&d_var_16_5, sizeof(float *)); + + float * h_var_16_6 = (float *)malloc(sizeof(float *)); + float * d_var_16_6; + cudaMalloc((void **)&d_var_16_6, sizeof(float *)); + + float * h_var_16_7 = (float *)malloc(sizeof(float *)); + float * d_var_16_7; + cudaMalloc((void **)&d_var_16_7, sizeof(float *)); + + float * h_var_16_8 = (float *)malloc(sizeof(float *)); + float * d_var_16_8; + cudaMalloc((void **)&d_var_16_8, sizeof(float *)); + + float * h_var_16_9 = (float *)malloc(sizeof(float *)); + float * d_var_16_9; + cudaMalloc((void **)&d_var_16_9, sizeof(float *)); + + float * h_var_16_10 = (float *)malloc(sizeof(float *)); + float * d_var_16_10; + cudaMalloc((void **)&d_var_16_10, sizeof(float *)); + + float * h_var_16_11 = (float *)malloc(sizeof(float *)); + float * d_var_16_11; + cudaMalloc((void **)&d_var_16_11, sizeof(float *)); + + float * h_var_16_12 = (float *)malloc(sizeof(float *)); + float * d_var_16_12; + cudaMalloc((void **)&d_var_16_12, sizeof(float *)); + + float * h_var_16_13 = (float *)malloc(sizeof(float *)); + float * d_var_16_13; + cudaMalloc((void **)&d_var_16_13, sizeof(float *)); + + float * h_var_16_14 = (float *)malloc(sizeof(float *)); + float * d_var_16_14; + cudaMalloc((void **)&d_var_16_14, sizeof(float *)); + + float * h_var_16_15 = (float *)malloc(sizeof(float *)); + float * d_var_16_15; + cudaMalloc((void **)&d_var_16_15, sizeof(float *)); + + float * h_var_16_16 = (float *)malloc(sizeof(float *)); + float * d_var_16_16; + cudaMalloc((void **)&d_var_16_16, sizeof(float *)); + + float * h_var_16_17 = (float *)malloc(sizeof(float *)); + float * d_var_16_17; + cudaMalloc((void **)&d_var_16_17, sizeof(float *)); + + float * h_var_16_18 = (float *)malloc(sizeof(float *)); + float * d_var_16_18; + cudaMalloc((void **)&d_var_16_18, sizeof(float *)); + + float * h_var_16_19 = (float *)malloc(sizeof(float *)); + float * d_var_16_19; + cudaMalloc((void **)&d_var_16_19, sizeof(float *)); + + float * h_var_17_0 = (float *)malloc(sizeof(float *)); + float * d_var_17_0; + cudaMalloc((void **)&d_var_17_0, sizeof(float *)); + + float * h_var_17_1 = (float *)malloc(sizeof(float *)); + float * d_var_17_1; + cudaMalloc((void **)&d_var_17_1, sizeof(float *)); + + float * h_var_17_2 = (float *)malloc(sizeof(float *)); + float * d_var_17_2; + cudaMalloc((void **)&d_var_17_2, sizeof(float *)); + + float * h_var_17_3 = (float *)malloc(sizeof(float *)); + float * d_var_17_3; + cudaMalloc((void **)&d_var_17_3, sizeof(float *)); + + float * h_var_17_4 = (float *)malloc(sizeof(float *)); + float * d_var_17_4; + cudaMalloc((void **)&d_var_17_4, sizeof(float *)); + + float * h_var_17_5 = (float *)malloc(sizeof(float *)); + float * d_var_17_5; + cudaMalloc((void **)&d_var_17_5, sizeof(float *)); + + float * h_var_17_6 = (float *)malloc(sizeof(float *)); + float * d_var_17_6; + cudaMalloc((void **)&d_var_17_6, sizeof(float *)); + + float * h_var_17_7 = (float *)malloc(sizeof(float *)); + float * d_var_17_7; + cudaMalloc((void **)&d_var_17_7, sizeof(float *)); + + float * h_var_17_8 = (float *)malloc(sizeof(float *)); + float * d_var_17_8; + cudaMalloc((void **)&d_var_17_8, sizeof(float *)); + + float * h_var_17_9 = (float *)malloc(sizeof(float *)); + float * d_var_17_9; + cudaMalloc((void **)&d_var_17_9, sizeof(float *)); + + float * h_var_17_10 = (float *)malloc(sizeof(float *)); + float * d_var_17_10; + cudaMalloc((void **)&d_var_17_10, sizeof(float *)); + + float * h_var_17_11 = (float *)malloc(sizeof(float *)); + float * d_var_17_11; + cudaMalloc((void **)&d_var_17_11, sizeof(float *)); + + float * h_var_17_12 = (float *)malloc(sizeof(float *)); + float * d_var_17_12; + cudaMalloc((void **)&d_var_17_12, sizeof(float *)); + + float * h_var_17_13 = (float *)malloc(sizeof(float *)); + float * d_var_17_13; + cudaMalloc((void **)&d_var_17_13, sizeof(float *)); + + float * h_var_17_14 = (float *)malloc(sizeof(float *)); + float * d_var_17_14; + cudaMalloc((void **)&d_var_17_14, sizeof(float *)); + + float * h_var_17_15 = (float *)malloc(sizeof(float *)); + float * d_var_17_15; + cudaMalloc((void **)&d_var_17_15, sizeof(float *)); + + float * h_var_17_16 = (float *)malloc(sizeof(float *)); + float * d_var_17_16; + cudaMalloc((void **)&d_var_17_16, sizeof(float *)); + + float * h_var_17_17 = (float *)malloc(sizeof(float *)); + float * d_var_17_17; + cudaMalloc((void **)&d_var_17_17, sizeof(float *)); + + float * h_var_17_18 = (float *)malloc(sizeof(float *)); + float * d_var_17_18; + cudaMalloc((void **)&d_var_17_18, sizeof(float *)); + + float * h_var_17_19 = (float *)malloc(sizeof(float *)); + float * d_var_17_19; + cudaMalloc((void **)&d_var_17_19, sizeof(float *)); + + float * h_var_18_0 = (float *)malloc(sizeof(float *)); + float * d_var_18_0; + cudaMalloc((void **)&d_var_18_0, sizeof(float *)); + + float * h_var_18_1 = (float *)malloc(sizeof(float *)); + float * d_var_18_1; + cudaMalloc((void **)&d_var_18_1, sizeof(float *)); + + float * h_var_18_2 = (float *)malloc(sizeof(float *)); + float * d_var_18_2; + cudaMalloc((void **)&d_var_18_2, sizeof(float *)); + + float * h_var_18_3 = (float *)malloc(sizeof(float *)); + float * d_var_18_3; + cudaMalloc((void **)&d_var_18_3, sizeof(float *)); + + float * h_var_18_4 = (float *)malloc(sizeof(float *)); + float * d_var_18_4; + cudaMalloc((void **)&d_var_18_4, sizeof(float *)); + + float * h_var_18_5 = (float *)malloc(sizeof(float *)); + float * d_var_18_5; + cudaMalloc((void **)&d_var_18_5, sizeof(float *)); + + float * h_var_18_6 = (float *)malloc(sizeof(float *)); + float * d_var_18_6; + cudaMalloc((void **)&d_var_18_6, sizeof(float *)); + + float * h_var_18_7 = (float *)malloc(sizeof(float *)); + float * d_var_18_7; + cudaMalloc((void **)&d_var_18_7, sizeof(float *)); + + float * h_var_18_8 = (float *)malloc(sizeof(float *)); + float * d_var_18_8; + cudaMalloc((void **)&d_var_18_8, sizeof(float *)); + + float * h_var_18_9 = (float *)malloc(sizeof(float *)); + float * d_var_18_9; + cudaMalloc((void **)&d_var_18_9, sizeof(float *)); + + float * h_var_18_10 = (float *)malloc(sizeof(float *)); + float * d_var_18_10; + cudaMalloc((void **)&d_var_18_10, sizeof(float *)); + + float * h_var_18_11 = (float *)malloc(sizeof(float *)); + float * d_var_18_11; + cudaMalloc((void **)&d_var_18_11, sizeof(float *)); + + float * h_var_18_12 = (float *)malloc(sizeof(float *)); + float * d_var_18_12; + cudaMalloc((void **)&d_var_18_12, sizeof(float *)); + + float * h_var_18_13 = (float *)malloc(sizeof(float *)); + float * d_var_18_13; + cudaMalloc((void **)&d_var_18_13, sizeof(float *)); + + float * h_var_18_14 = (float *)malloc(sizeof(float *)); + float * d_var_18_14; + cudaMalloc((void **)&d_var_18_14, sizeof(float *)); + + float * h_var_18_15 = (float *)malloc(sizeof(float *)); + float * d_var_18_15; + cudaMalloc((void **)&d_var_18_15, sizeof(float *)); + + float * h_var_18_16 = (float *)malloc(sizeof(float *)); + float * d_var_18_16; + cudaMalloc((void **)&d_var_18_16, sizeof(float *)); + + float * h_var_18_17 = (float *)malloc(sizeof(float *)); + float * d_var_18_17; + cudaMalloc((void **)&d_var_18_17, sizeof(float *)); + + float * h_var_18_18 = (float *)malloc(sizeof(float *)); + float * d_var_18_18; + cudaMalloc((void **)&d_var_18_18, sizeof(float *)); + + float * h_var_18_19 = (float *)malloc(sizeof(float *)); + float * d_var_18_19; + cudaMalloc((void **)&d_var_18_19, sizeof(float *)); + + float * h_var_19_0 = (float *)malloc(sizeof(float *)); + float * d_var_19_0; + cudaMalloc((void **)&d_var_19_0, sizeof(float *)); + + float * h_var_19_1 = (float *)malloc(sizeof(float *)); + float * d_var_19_1; + cudaMalloc((void **)&d_var_19_1, sizeof(float *)); + + float * h_var_19_2 = (float *)malloc(sizeof(float *)); + float * d_var_19_2; + cudaMalloc((void **)&d_var_19_2, sizeof(float *)); + + float * h_var_19_3 = (float *)malloc(sizeof(float *)); + float * d_var_19_3; + cudaMalloc((void **)&d_var_19_3, sizeof(float *)); + + float * h_var_19_4 = (float *)malloc(sizeof(float *)); + float * d_var_19_4; + cudaMalloc((void **)&d_var_19_4, sizeof(float *)); + + float * h_var_19_5 = (float *)malloc(sizeof(float *)); + float * d_var_19_5; + cudaMalloc((void **)&d_var_19_5, sizeof(float *)); + + float * h_var_19_6 = (float *)malloc(sizeof(float *)); + float * d_var_19_6; + cudaMalloc((void **)&d_var_19_6, sizeof(float *)); + + float * h_var_19_7 = (float *)malloc(sizeof(float *)); + float * d_var_19_7; + cudaMalloc((void **)&d_var_19_7, sizeof(float *)); + + float * h_var_19_8 = (float *)malloc(sizeof(float *)); + float * d_var_19_8; + cudaMalloc((void **)&d_var_19_8, sizeof(float *)); + + float * h_var_19_9 = (float *)malloc(sizeof(float *)); + float * d_var_19_9; + cudaMalloc((void **)&d_var_19_9, sizeof(float *)); + + float * h_var_19_10 = (float *)malloc(sizeof(float *)); + float * d_var_19_10; + cudaMalloc((void **)&d_var_19_10, sizeof(float *)); + + float * h_var_19_11 = (float *)malloc(sizeof(float *)); + float * d_var_19_11; + cudaMalloc((void **)&d_var_19_11, sizeof(float *)); + + float * h_var_19_12 = (float *)malloc(sizeof(float *)); + float * d_var_19_12; + cudaMalloc((void **)&d_var_19_12, sizeof(float *)); + + float * h_var_19_13 = (float *)malloc(sizeof(float *)); + float * d_var_19_13; + cudaMalloc((void **)&d_var_19_13, sizeof(float *)); + + float * h_var_19_14 = (float *)malloc(sizeof(float *)); + float * d_var_19_14; + cudaMalloc((void **)&d_var_19_14, sizeof(float *)); + + float * h_var_19_15 = (float *)malloc(sizeof(float *)); + float * d_var_19_15; + cudaMalloc((void **)&d_var_19_15, sizeof(float *)); + + float * h_var_19_16 = (float *)malloc(sizeof(float *)); + float * d_var_19_16; + cudaMalloc((void **)&d_var_19_16, sizeof(float *)); + + float * h_var_19_17 = (float *)malloc(sizeof(float *)); + float * d_var_19_17; + cudaMalloc((void **)&d_var_19_17, sizeof(float *)); + + float * h_var_19_18 = (float *)malloc(sizeof(float *)); + float * d_var_19_18; + cudaMalloc((void **)&d_var_19_18, sizeof(float *)); + + float * h_var_19_19 = (float *)malloc(sizeof(float *)); + float * d_var_19_19; + cudaMalloc((void **)&d_var_19_19, sizeof(float *)); + + float * h_var_20_0 = (float *)malloc(sizeof(float *)); + float * d_var_20_0; + cudaMalloc((void **)&d_var_20_0, sizeof(float *)); + + float * h_var_20_1 = (float *)malloc(sizeof(float *)); + float * d_var_20_1; + cudaMalloc((void **)&d_var_20_1, sizeof(float *)); + + float * h_var_20_2 = (float *)malloc(sizeof(float *)); + float * d_var_20_2; + cudaMalloc((void **)&d_var_20_2, sizeof(float *)); + + float * h_var_20_3 = (float *)malloc(sizeof(float *)); + float * d_var_20_3; + cudaMalloc((void **)&d_var_20_3, sizeof(float *)); + + float * h_var_20_4 = (float *)malloc(sizeof(float *)); + float * d_var_20_4; + cudaMalloc((void **)&d_var_20_4, sizeof(float *)); + + float * h_var_20_5 = (float *)malloc(sizeof(float *)); + float * d_var_20_5; + cudaMalloc((void **)&d_var_20_5, sizeof(float *)); + + float * h_var_20_6 = (float *)malloc(sizeof(float *)); + float * d_var_20_6; + cudaMalloc((void **)&d_var_20_6, sizeof(float *)); + + float * h_var_20_7 = (float *)malloc(sizeof(float *)); + float * d_var_20_7; + cudaMalloc((void **)&d_var_20_7, sizeof(float *)); + + float * h_var_20_8 = (float *)malloc(sizeof(float *)); + float * d_var_20_8; + cudaMalloc((void **)&d_var_20_8, sizeof(float *)); + + float * h_var_20_9 = (float *)malloc(sizeof(float *)); + float * d_var_20_9; + cudaMalloc((void **)&d_var_20_9, sizeof(float *)); + + float * h_var_20_10 = (float *)malloc(sizeof(float *)); + float * d_var_20_10; + cudaMalloc((void **)&d_var_20_10, sizeof(float *)); + + float * h_var_20_11 = (float *)malloc(sizeof(float *)); + float * d_var_20_11; + cudaMalloc((void **)&d_var_20_11, sizeof(float *)); + + float * h_var_20_12 = (float *)malloc(sizeof(float *)); + float * d_var_20_12; + cudaMalloc((void **)&d_var_20_12, sizeof(float *)); + + float * h_var_20_13 = (float *)malloc(sizeof(float *)); + float * d_var_20_13; + cudaMalloc((void **)&d_var_20_13, sizeof(float *)); + + float * h_var_20_14 = (float *)malloc(sizeof(float *)); + float * d_var_20_14; + cudaMalloc((void **)&d_var_20_14, sizeof(float *)); + + float * h_var_20_15 = (float *)malloc(sizeof(float *)); + float * d_var_20_15; + cudaMalloc((void **)&d_var_20_15, sizeof(float *)); + + float * h_var_20_16 = (float *)malloc(sizeof(float *)); + float * d_var_20_16; + cudaMalloc((void **)&d_var_20_16, sizeof(float *)); + + float * h_var_20_17 = (float *)malloc(sizeof(float *)); + float * d_var_20_17; + cudaMalloc((void **)&d_var_20_17, sizeof(float *)); + + float * h_var_20_18 = (float *)malloc(sizeof(float *)); + float * d_var_20_18; + cudaMalloc((void **)&d_var_20_18, sizeof(float *)); + + float * h_var_20_19 = (float *)malloc(sizeof(float *)); + float * d_var_20_19; + cudaMalloc((void **)&d_var_20_19, sizeof(float *)); + + float * h_var_21_0 = (float *)malloc(sizeof(float *)); + float * d_var_21_0; + cudaMalloc((void **)&d_var_21_0, sizeof(float *)); + + float * h_var_21_1 = (float *)malloc(sizeof(float *)); + float * d_var_21_1; + cudaMalloc((void **)&d_var_21_1, sizeof(float *)); + + float * h_var_21_2 = (float *)malloc(sizeof(float *)); + float * d_var_21_2; + cudaMalloc((void **)&d_var_21_2, sizeof(float *)); + + float * h_var_21_3 = (float *)malloc(sizeof(float *)); + float * d_var_21_3; + cudaMalloc((void **)&d_var_21_3, sizeof(float *)); + + float * h_var_21_4 = (float *)malloc(sizeof(float *)); + float * d_var_21_4; + cudaMalloc((void **)&d_var_21_4, sizeof(float *)); + + float * h_var_21_5 = (float *)malloc(sizeof(float *)); + float * d_var_21_5; + cudaMalloc((void **)&d_var_21_5, sizeof(float *)); + + float * h_var_21_6 = (float *)malloc(sizeof(float *)); + float * d_var_21_6; + cudaMalloc((void **)&d_var_21_6, sizeof(float *)); + + float * h_var_21_7 = (float *)malloc(sizeof(float *)); + float * d_var_21_7; + cudaMalloc((void **)&d_var_21_7, sizeof(float *)); + + float * h_var_21_8 = (float *)malloc(sizeof(float *)); + float * d_var_21_8; + cudaMalloc((void **)&d_var_21_8, sizeof(float *)); + + float * h_var_21_9 = (float *)malloc(sizeof(float *)); + float * d_var_21_9; + cudaMalloc((void **)&d_var_21_9, sizeof(float *)); + + float * h_var_21_10 = (float *)malloc(sizeof(float *)); + float * d_var_21_10; + cudaMalloc((void **)&d_var_21_10, sizeof(float *)); + + float * h_var_21_11 = (float *)malloc(sizeof(float *)); + float * d_var_21_11; + cudaMalloc((void **)&d_var_21_11, sizeof(float *)); + + float * h_var_21_12 = (float *)malloc(sizeof(float *)); + float * d_var_21_12; + cudaMalloc((void **)&d_var_21_12, sizeof(float *)); + + float * h_var_21_13 = (float *)malloc(sizeof(float *)); + float * d_var_21_13; + cudaMalloc((void **)&d_var_21_13, sizeof(float *)); + + float * h_var_21_14 = (float *)malloc(sizeof(float *)); + float * d_var_21_14; + cudaMalloc((void **)&d_var_21_14, sizeof(float *)); + + float * h_var_21_15 = (float *)malloc(sizeof(float *)); + float * d_var_21_15; + cudaMalloc((void **)&d_var_21_15, sizeof(float *)); + + float * h_var_21_16 = (float *)malloc(sizeof(float *)); + float * d_var_21_16; + cudaMalloc((void **)&d_var_21_16, sizeof(float *)); + + float * h_var_21_17 = (float *)malloc(sizeof(float *)); + float * d_var_21_17; + cudaMalloc((void **)&d_var_21_17, sizeof(float *)); + + float * h_var_21_18 = (float *)malloc(sizeof(float *)); + float * d_var_21_18; + cudaMalloc((void **)&d_var_21_18, sizeof(float *)); + + float * h_var_21_19 = (float *)malloc(sizeof(float *)); + float * d_var_21_19; + cudaMalloc((void **)&d_var_21_19, sizeof(float *)); + + float * h_var_22_0 = (float *)malloc(sizeof(float *)); + float * d_var_22_0; + cudaMalloc((void **)&d_var_22_0, sizeof(float *)); + + float * h_var_22_1 = (float *)malloc(sizeof(float *)); + float * d_var_22_1; + cudaMalloc((void **)&d_var_22_1, sizeof(float *)); + + float * h_var_22_2 = (float *)malloc(sizeof(float *)); + float * d_var_22_2; + cudaMalloc((void **)&d_var_22_2, sizeof(float *)); + + float * h_var_22_3 = (float *)malloc(sizeof(float *)); + float * d_var_22_3; + cudaMalloc((void **)&d_var_22_3, sizeof(float *)); + + float * h_var_22_4 = (float *)malloc(sizeof(float *)); + float * d_var_22_4; + cudaMalloc((void **)&d_var_22_4, sizeof(float *)); + + float * h_var_22_5 = (float *)malloc(sizeof(float *)); + float * d_var_22_5; + cudaMalloc((void **)&d_var_22_5, sizeof(float *)); + + float * h_var_22_6 = (float *)malloc(sizeof(float *)); + float * d_var_22_6; + cudaMalloc((void **)&d_var_22_6, sizeof(float *)); + + float * h_var_22_7 = (float *)malloc(sizeof(float *)); + float * d_var_22_7; + cudaMalloc((void **)&d_var_22_7, sizeof(float *)); + + float * h_var_22_8 = (float *)malloc(sizeof(float *)); + float * d_var_22_8; + cudaMalloc((void **)&d_var_22_8, sizeof(float *)); + + float * h_var_22_9 = (float *)malloc(sizeof(float *)); + float * d_var_22_9; + cudaMalloc((void **)&d_var_22_9, sizeof(float *)); + + float * h_var_22_10 = (float *)malloc(sizeof(float *)); + float * d_var_22_10; + cudaMalloc((void **)&d_var_22_10, sizeof(float *)); + + float * h_var_22_11 = (float *)malloc(sizeof(float *)); + float * d_var_22_11; + cudaMalloc((void **)&d_var_22_11, sizeof(float *)); + + float * h_var_22_12 = (float *)malloc(sizeof(float *)); + float * d_var_22_12; + cudaMalloc((void **)&d_var_22_12, sizeof(float *)); + + float * h_var_22_13 = (float *)malloc(sizeof(float *)); + float * d_var_22_13; + cudaMalloc((void **)&d_var_22_13, sizeof(float *)); + + float * h_var_22_14 = (float *)malloc(sizeof(float *)); + float * d_var_22_14; + cudaMalloc((void **)&d_var_22_14, sizeof(float *)); + + float * h_var_22_15 = (float *)malloc(sizeof(float *)); + float * d_var_22_15; + cudaMalloc((void **)&d_var_22_15, sizeof(float *)); + + float * h_var_22_16 = (float *)malloc(sizeof(float *)); + float * d_var_22_16; + cudaMalloc((void **)&d_var_22_16, sizeof(float *)); + + float * h_var_22_17 = (float *)malloc(sizeof(float *)); + float * d_var_22_17; + cudaMalloc((void **)&d_var_22_17, sizeof(float *)); + + float * h_var_22_18 = (float *)malloc(sizeof(float *)); + float * d_var_22_18; + cudaMalloc((void **)&d_var_22_18, sizeof(float *)); + + float * h_var_22_19 = (float *)malloc(sizeof(float *)); + float * d_var_22_19; + cudaMalloc((void **)&d_var_22_19, sizeof(float *)); + + float * h_var_23_0 = (float *)malloc(sizeof(float *)); + float * d_var_23_0; + cudaMalloc((void **)&d_var_23_0, sizeof(float *)); + + float * h_var_23_1 = (float *)malloc(sizeof(float *)); + float * d_var_23_1; + cudaMalloc((void **)&d_var_23_1, sizeof(float *)); + + float * h_var_23_2 = (float *)malloc(sizeof(float *)); + float * d_var_23_2; + cudaMalloc((void **)&d_var_23_2, sizeof(float *)); + + float * h_var_23_3 = (float *)malloc(sizeof(float *)); + float * d_var_23_3; + cudaMalloc((void **)&d_var_23_3, sizeof(float *)); + + float * h_var_23_4 = (float *)malloc(sizeof(float *)); + float * d_var_23_4; + cudaMalloc((void **)&d_var_23_4, sizeof(float *)); + + float * h_var_23_5 = (float *)malloc(sizeof(float *)); + float * d_var_23_5; + cudaMalloc((void **)&d_var_23_5, sizeof(float *)); + + float * h_var_23_6 = (float *)malloc(sizeof(float *)); + float * d_var_23_6; + cudaMalloc((void **)&d_var_23_6, sizeof(float *)); + + float * h_var_23_7 = (float *)malloc(sizeof(float *)); + float * d_var_23_7; + cudaMalloc((void **)&d_var_23_7, sizeof(float *)); + + float * h_var_23_8 = (float *)malloc(sizeof(float *)); + float * d_var_23_8; + cudaMalloc((void **)&d_var_23_8, sizeof(float *)); + + float * h_var_23_9 = (float *)malloc(sizeof(float *)); + float * d_var_23_9; + cudaMalloc((void **)&d_var_23_9, sizeof(float *)); + + float * h_var_23_10 = (float *)malloc(sizeof(float *)); + float * d_var_23_10; + cudaMalloc((void **)&d_var_23_10, sizeof(float *)); + + float * h_var_23_11 = (float *)malloc(sizeof(float *)); + float * d_var_23_11; + cudaMalloc((void **)&d_var_23_11, sizeof(float *)); + + float * h_var_23_12 = (float *)malloc(sizeof(float *)); + float * d_var_23_12; + cudaMalloc((void **)&d_var_23_12, sizeof(float *)); + + float * h_var_23_13 = (float *)malloc(sizeof(float *)); + float * d_var_23_13; + cudaMalloc((void **)&d_var_23_13, sizeof(float *)); + + float * h_var_23_14 = (float *)malloc(sizeof(float *)); + float * d_var_23_14; + cudaMalloc((void **)&d_var_23_14, sizeof(float *)); + + float * h_var_23_15 = (float *)malloc(sizeof(float *)); + float * d_var_23_15; + cudaMalloc((void **)&d_var_23_15, sizeof(float *)); + + float * h_var_23_16 = (float *)malloc(sizeof(float *)); + float * d_var_23_16; + cudaMalloc((void **)&d_var_23_16, sizeof(float *)); + + float * h_var_23_17 = (float *)malloc(sizeof(float *)); + float * d_var_23_17; + cudaMalloc((void **)&d_var_23_17, sizeof(float *)); + + float * h_var_23_18 = (float *)malloc(sizeof(float *)); + float * d_var_23_18; + cudaMalloc((void **)&d_var_23_18, sizeof(float *)); + + float * h_var_23_19 = (float *)malloc(sizeof(float *)); + float * d_var_23_19; + cudaMalloc((void **)&d_var_23_19, sizeof(float *)); + + float * h_var_24_0 = (float *)malloc(sizeof(float *)); + float * d_var_24_0; + cudaMalloc((void **)&d_var_24_0, sizeof(float *)); + + float * h_var_24_1 = (float *)malloc(sizeof(float *)); + float * d_var_24_1; + cudaMalloc((void **)&d_var_24_1, sizeof(float *)); + + float * h_var_24_2 = (float *)malloc(sizeof(float *)); + float * d_var_24_2; + cudaMalloc((void **)&d_var_24_2, sizeof(float *)); + + float * h_var_24_3 = (float *)malloc(sizeof(float *)); + float * d_var_24_3; + cudaMalloc((void **)&d_var_24_3, sizeof(float *)); + + float * h_var_24_4 = (float *)malloc(sizeof(float *)); + float * d_var_24_4; + cudaMalloc((void **)&d_var_24_4, sizeof(float *)); + + float * h_var_24_5 = (float *)malloc(sizeof(float *)); + float * d_var_24_5; + cudaMalloc((void **)&d_var_24_5, sizeof(float *)); + + float * h_var_24_6 = (float *)malloc(sizeof(float *)); + float * d_var_24_6; + cudaMalloc((void **)&d_var_24_6, sizeof(float *)); + + float * h_var_24_7 = (float *)malloc(sizeof(float *)); + float * d_var_24_7; + cudaMalloc((void **)&d_var_24_7, sizeof(float *)); + + float * h_var_24_8 = (float *)malloc(sizeof(float *)); + float * d_var_24_8; + cudaMalloc((void **)&d_var_24_8, sizeof(float *)); + + float * h_var_24_9 = (float *)malloc(sizeof(float *)); + float * d_var_24_9; + cudaMalloc((void **)&d_var_24_9, sizeof(float *)); + + float * h_var_24_10 = (float *)malloc(sizeof(float *)); + float * d_var_24_10; + cudaMalloc((void **)&d_var_24_10, sizeof(float *)); + + float * h_var_24_11 = (float *)malloc(sizeof(float *)); + float * d_var_24_11; + cudaMalloc((void **)&d_var_24_11, sizeof(float *)); + + float * h_var_24_12 = (float *)malloc(sizeof(float *)); + float * d_var_24_12; + cudaMalloc((void **)&d_var_24_12, sizeof(float *)); + + float * h_var_24_13 = (float *)malloc(sizeof(float *)); + float * d_var_24_13; + cudaMalloc((void **)&d_var_24_13, sizeof(float *)); + + float * h_var_24_14 = (float *)malloc(sizeof(float *)); + float * d_var_24_14; + cudaMalloc((void **)&d_var_24_14, sizeof(float *)); + + float * h_var_24_15 = (float *)malloc(sizeof(float *)); + float * d_var_24_15; + cudaMalloc((void **)&d_var_24_15, sizeof(float *)); + + float * h_var_24_16 = (float *)malloc(sizeof(float *)); + float * d_var_24_16; + cudaMalloc((void **)&d_var_24_16, sizeof(float *)); + + float * h_var_24_17 = (float *)malloc(sizeof(float *)); + float * d_var_24_17; + cudaMalloc((void **)&d_var_24_17, sizeof(float *)); + + float * h_var_24_18 = (float *)malloc(sizeof(float *)); + float * d_var_24_18; + cudaMalloc((void **)&d_var_24_18, sizeof(float *)); + + float * h_var_24_19 = (float *)malloc(sizeof(float *)); + float * d_var_24_19; + cudaMalloc((void **)&d_var_24_19, sizeof(float *)); + + float * h_var_25_0 = (float *)malloc(sizeof(float *)); + float * d_var_25_0; + cudaMalloc((void **)&d_var_25_0, sizeof(float *)); + + float * h_var_25_1 = (float *)malloc(sizeof(float *)); + float * d_var_25_1; + cudaMalloc((void **)&d_var_25_1, sizeof(float *)); + + float * h_var_25_2 = (float *)malloc(sizeof(float *)); + float * d_var_25_2; + cudaMalloc((void **)&d_var_25_2, sizeof(float *)); + + float * h_var_25_3 = (float *)malloc(sizeof(float *)); + float * d_var_25_3; + cudaMalloc((void **)&d_var_25_3, sizeof(float *)); + + float * h_var_25_4 = (float *)malloc(sizeof(float *)); + float * d_var_25_4; + cudaMalloc((void **)&d_var_25_4, sizeof(float *)); + + float * h_var_25_5 = (float *)malloc(sizeof(float *)); + float * d_var_25_5; + cudaMalloc((void **)&d_var_25_5, sizeof(float *)); + + float * h_var_25_6 = (float *)malloc(sizeof(float *)); + float * d_var_25_6; + cudaMalloc((void **)&d_var_25_6, sizeof(float *)); + + float * h_var_25_7 = (float *)malloc(sizeof(float *)); + float * d_var_25_7; + cudaMalloc((void **)&d_var_25_7, sizeof(float *)); + + float * h_var_25_8 = (float *)malloc(sizeof(float *)); + float * d_var_25_8; + cudaMalloc((void **)&d_var_25_8, sizeof(float *)); + + float * h_var_25_9 = (float *)malloc(sizeof(float *)); + float * d_var_25_9; + cudaMalloc((void **)&d_var_25_9, sizeof(float *)); + + float * h_var_25_10 = (float *)malloc(sizeof(float *)); + float * d_var_25_10; + cudaMalloc((void **)&d_var_25_10, sizeof(float *)); + + float * h_var_25_11 = (float *)malloc(sizeof(float *)); + float * d_var_25_11; + cudaMalloc((void **)&d_var_25_11, sizeof(float *)); + + float * h_var_25_12 = (float *)malloc(sizeof(float *)); + float * d_var_25_12; + cudaMalloc((void **)&d_var_25_12, sizeof(float *)); + + float * h_var_25_13 = (float *)malloc(sizeof(float *)); + float * d_var_25_13; + cudaMalloc((void **)&d_var_25_13, sizeof(float *)); + + float * h_var_25_14 = (float *)malloc(sizeof(float *)); + float * d_var_25_14; + cudaMalloc((void **)&d_var_25_14, sizeof(float *)); + + float * h_var_25_15 = (float *)malloc(sizeof(float *)); + float * d_var_25_15; + cudaMalloc((void **)&d_var_25_15, sizeof(float *)); + + float * h_var_25_16 = (float *)malloc(sizeof(float *)); + float * d_var_25_16; + cudaMalloc((void **)&d_var_25_16, sizeof(float *)); + + float * h_var_25_17 = (float *)malloc(sizeof(float *)); + float * d_var_25_17; + cudaMalloc((void **)&d_var_25_17, sizeof(float *)); + + float * h_var_25_18 = (float *)malloc(sizeof(float *)); + float * d_var_25_18; + cudaMalloc((void **)&d_var_25_18, sizeof(float *)); + + float * h_var_25_19 = (float *)malloc(sizeof(float *)); + float * d_var_25_19; + cudaMalloc((void **)&d_var_25_19, sizeof(float *)); + + float * h_var_26_0 = (float *)malloc(sizeof(float *)); + float * d_var_26_0; + cudaMalloc((void **)&d_var_26_0, sizeof(float *)); + + float * h_var_26_1 = (float *)malloc(sizeof(float *)); + float * d_var_26_1; + cudaMalloc((void **)&d_var_26_1, sizeof(float *)); + + float * h_var_26_2 = (float *)malloc(sizeof(float *)); + float * d_var_26_2; + cudaMalloc((void **)&d_var_26_2, sizeof(float *)); + + float * h_var_26_3 = (float *)malloc(sizeof(float *)); + float * d_var_26_3; + cudaMalloc((void **)&d_var_26_3, sizeof(float *)); + + float * h_var_26_4 = (float *)malloc(sizeof(float *)); + float * d_var_26_4; + cudaMalloc((void **)&d_var_26_4, sizeof(float *)); + + float * h_var_26_5 = (float *)malloc(sizeof(float *)); + float * d_var_26_5; + cudaMalloc((void **)&d_var_26_5, sizeof(float *)); + + float * h_var_26_6 = (float *)malloc(sizeof(float *)); + float * d_var_26_6; + cudaMalloc((void **)&d_var_26_6, sizeof(float *)); + + float * h_var_26_7 = (float *)malloc(sizeof(float *)); + float * d_var_26_7; + cudaMalloc((void **)&d_var_26_7, sizeof(float *)); + + float * h_var_26_8 = (float *)malloc(sizeof(float *)); + float * d_var_26_8; + cudaMalloc((void **)&d_var_26_8, sizeof(float *)); + + float * h_var_26_9 = (float *)malloc(sizeof(float *)); + float * d_var_26_9; + cudaMalloc((void **)&d_var_26_9, sizeof(float *)); + + float * h_var_26_10 = (float *)malloc(sizeof(float *)); + float * d_var_26_10; + cudaMalloc((void **)&d_var_26_10, sizeof(float *)); + + float * h_var_26_11 = (float *)malloc(sizeof(float *)); + float * d_var_26_11; + cudaMalloc((void **)&d_var_26_11, sizeof(float *)); + + float * h_var_26_12 = (float *)malloc(sizeof(float *)); + float * d_var_26_12; + cudaMalloc((void **)&d_var_26_12, sizeof(float *)); + + float * h_var_26_13 = (float *)malloc(sizeof(float *)); + float * d_var_26_13; + cudaMalloc((void **)&d_var_26_13, sizeof(float *)); + + float * h_var_26_14 = (float *)malloc(sizeof(float *)); + float * d_var_26_14; + cudaMalloc((void **)&d_var_26_14, sizeof(float *)); + + float * h_var_26_15 = (float *)malloc(sizeof(float *)); + float * d_var_26_15; + cudaMalloc((void **)&d_var_26_15, sizeof(float *)); + + float * h_var_26_16 = (float *)malloc(sizeof(float *)); + float * d_var_26_16; + cudaMalloc((void **)&d_var_26_16, sizeof(float *)); + + float * h_var_26_17 = (float *)malloc(sizeof(float *)); + float * d_var_26_17; + cudaMalloc((void **)&d_var_26_17, sizeof(float *)); + + float * h_var_26_18 = (float *)malloc(sizeof(float *)); + float * d_var_26_18; + cudaMalloc((void **)&d_var_26_18, sizeof(float *)); + + float * h_var_26_19 = (float *)malloc(sizeof(float *)); + float * d_var_26_19; + cudaMalloc((void **)&d_var_26_19, sizeof(float *)); + + float * h_var_27_0 = (float *)malloc(sizeof(float *)); + float * d_var_27_0; + cudaMalloc((void **)&d_var_27_0, sizeof(float *)); + + float * h_var_27_1 = (float *)malloc(sizeof(float *)); + float * d_var_27_1; + cudaMalloc((void **)&d_var_27_1, sizeof(float *)); + + float * h_var_27_2 = (float *)malloc(sizeof(float *)); + float * d_var_27_2; + cudaMalloc((void **)&d_var_27_2, sizeof(float *)); + + float * h_var_27_3 = (float *)malloc(sizeof(float *)); + float * d_var_27_3; + cudaMalloc((void **)&d_var_27_3, sizeof(float *)); + + float * h_var_27_4 = (float *)malloc(sizeof(float *)); + float * d_var_27_4; + cudaMalloc((void **)&d_var_27_4, sizeof(float *)); + + float * h_var_27_5 = (float *)malloc(sizeof(float *)); + float * d_var_27_5; + cudaMalloc((void **)&d_var_27_5, sizeof(float *)); + + float * h_var_27_6 = (float *)malloc(sizeof(float *)); + float * d_var_27_6; + cudaMalloc((void **)&d_var_27_6, sizeof(float *)); + + float * h_var_27_7 = (float *)malloc(sizeof(float *)); + float * d_var_27_7; + cudaMalloc((void **)&d_var_27_7, sizeof(float *)); + + float * h_var_27_8 = (float *)malloc(sizeof(float *)); + float * d_var_27_8; + cudaMalloc((void **)&d_var_27_8, sizeof(float *)); + + float * h_var_27_9 = (float *)malloc(sizeof(float *)); + float * d_var_27_9; + cudaMalloc((void **)&d_var_27_9, sizeof(float *)); + + float * h_var_27_10 = (float *)malloc(sizeof(float *)); + float * d_var_27_10; + cudaMalloc((void **)&d_var_27_10, sizeof(float *)); + + float * h_var_27_11 = (float *)malloc(sizeof(float *)); + float * d_var_27_11; + cudaMalloc((void **)&d_var_27_11, sizeof(float *)); + + float * h_var_27_12 = (float *)malloc(sizeof(float *)); + float * d_var_27_12; + cudaMalloc((void **)&d_var_27_12, sizeof(float *)); + + float * h_var_27_13 = (float *)malloc(sizeof(float *)); + float * d_var_27_13; + cudaMalloc((void **)&d_var_27_13, sizeof(float *)); + + float * h_var_27_14 = (float *)malloc(sizeof(float *)); + float * d_var_27_14; + cudaMalloc((void **)&d_var_27_14, sizeof(float *)); + + float * h_var_27_15 = (float *)malloc(sizeof(float *)); + float * d_var_27_15; + cudaMalloc((void **)&d_var_27_15, sizeof(float *)); + + float * h_var_27_16 = (float *)malloc(sizeof(float *)); + float * d_var_27_16; + cudaMalloc((void **)&d_var_27_16, sizeof(float *)); + + float * h_var_27_17 = (float *)malloc(sizeof(float *)); + float * d_var_27_17; + cudaMalloc((void **)&d_var_27_17, sizeof(float *)); + + float * h_var_27_18 = (float *)malloc(sizeof(float *)); + float * d_var_27_18; + cudaMalloc((void **)&d_var_27_18, sizeof(float *)); + + float * h_var_27_19 = (float *)malloc(sizeof(float *)); + float * d_var_27_19; + cudaMalloc((void **)&d_var_27_19, sizeof(float *)); + + float * h_var_28_0 = (float *)malloc(sizeof(float *)); + float * d_var_28_0; + cudaMalloc((void **)&d_var_28_0, sizeof(float *)); + + float * h_var_28_1 = (float *)malloc(sizeof(float *)); + float * d_var_28_1; + cudaMalloc((void **)&d_var_28_1, sizeof(float *)); + + float * h_var_28_2 = (float *)malloc(sizeof(float *)); + float * d_var_28_2; + cudaMalloc((void **)&d_var_28_2, sizeof(float *)); + + float * h_var_28_3 = (float *)malloc(sizeof(float *)); + float * d_var_28_3; + cudaMalloc((void **)&d_var_28_3, sizeof(float *)); + + float * h_var_28_4 = (float *)malloc(sizeof(float *)); + float * d_var_28_4; + cudaMalloc((void **)&d_var_28_4, sizeof(float *)); + + float * h_var_28_5 = (float *)malloc(sizeof(float *)); + float * d_var_28_5; + cudaMalloc((void **)&d_var_28_5, sizeof(float *)); + + float * h_var_28_6 = (float *)malloc(sizeof(float *)); + float * d_var_28_6; + cudaMalloc((void **)&d_var_28_6, sizeof(float *)); + + float * h_var_28_7 = (float *)malloc(sizeof(float *)); + float * d_var_28_7; + cudaMalloc((void **)&d_var_28_7, sizeof(float *)); + + float * h_var_28_8 = (float *)malloc(sizeof(float *)); + float * d_var_28_8; + cudaMalloc((void **)&d_var_28_8, sizeof(float *)); + + float * h_var_28_9 = (float *)malloc(sizeof(float *)); + float * d_var_28_9; + cudaMalloc((void **)&d_var_28_9, sizeof(float *)); + + float * h_var_28_10 = (float *)malloc(sizeof(float *)); + float * d_var_28_10; + cudaMalloc((void **)&d_var_28_10, sizeof(float *)); + + float * h_var_28_11 = (float *)malloc(sizeof(float *)); + float * d_var_28_11; + cudaMalloc((void **)&d_var_28_11, sizeof(float *)); + + float * h_var_28_12 = (float *)malloc(sizeof(float *)); + float * d_var_28_12; + cudaMalloc((void **)&d_var_28_12, sizeof(float *)); + + float * h_var_28_13 = (float *)malloc(sizeof(float *)); + float * d_var_28_13; + cudaMalloc((void **)&d_var_28_13, sizeof(float *)); + + float * h_var_28_14 = (float *)malloc(sizeof(float *)); + float * d_var_28_14; + cudaMalloc((void **)&d_var_28_14, sizeof(float *)); + + float * h_var_28_15 = (float *)malloc(sizeof(float *)); + float * d_var_28_15; + cudaMalloc((void **)&d_var_28_15, sizeof(float *)); + + float * h_var_28_16 = (float *)malloc(sizeof(float *)); + float * d_var_28_16; + cudaMalloc((void **)&d_var_28_16, sizeof(float *)); + + float * h_var_28_17 = (float *)malloc(sizeof(float *)); + float * d_var_28_17; + cudaMalloc((void **)&d_var_28_17, sizeof(float *)); + + float * h_var_28_18 = (float *)malloc(sizeof(float *)); + float * d_var_28_18; + cudaMalloc((void **)&d_var_28_18, sizeof(float *)); + + float * h_var_28_19 = (float *)malloc(sizeof(float *)); + float * d_var_28_19; + cudaMalloc((void **)&d_var_28_19, sizeof(float *)); + + float * h_var_29_0 = (float *)malloc(sizeof(float *)); + float * d_var_29_0; + cudaMalloc((void **)&d_var_29_0, sizeof(float *)); + + float * h_var_29_1 = (float *)malloc(sizeof(float *)); + float * d_var_29_1; + cudaMalloc((void **)&d_var_29_1, sizeof(float *)); + + float * h_var_29_2 = (float *)malloc(sizeof(float *)); + float * d_var_29_2; + cudaMalloc((void **)&d_var_29_2, sizeof(float *)); + + float * h_var_29_3 = (float *)malloc(sizeof(float *)); + float * d_var_29_3; + cudaMalloc((void **)&d_var_29_3, sizeof(float *)); + + float * h_var_29_4 = (float *)malloc(sizeof(float *)); + float * d_var_29_4; + cudaMalloc((void **)&d_var_29_4, sizeof(float *)); + + float * h_var_29_5 = (float *)malloc(sizeof(float *)); + float * d_var_29_5; + cudaMalloc((void **)&d_var_29_5, sizeof(float *)); + + float * h_var_29_6 = (float *)malloc(sizeof(float *)); + float * d_var_29_6; + cudaMalloc((void **)&d_var_29_6, sizeof(float *)); + + float * h_var_29_7 = (float *)malloc(sizeof(float *)); + float * d_var_29_7; + cudaMalloc((void **)&d_var_29_7, sizeof(float *)); + + float * h_var_29_8 = (float *)malloc(sizeof(float *)); + float * d_var_29_8; + cudaMalloc((void **)&d_var_29_8, sizeof(float *)); + + float * h_var_29_9 = (float *)malloc(sizeof(float *)); + float * d_var_29_9; + cudaMalloc((void **)&d_var_29_9, sizeof(float *)); + + float * h_var_29_10 = (float *)malloc(sizeof(float *)); + float * d_var_29_10; + cudaMalloc((void **)&d_var_29_10, sizeof(float *)); + + float * h_var_29_11 = (float *)malloc(sizeof(float *)); + float * d_var_29_11; + cudaMalloc((void **)&d_var_29_11, sizeof(float *)); + + float * h_var_29_12 = (float *)malloc(sizeof(float *)); + float * d_var_29_12; + cudaMalloc((void **)&d_var_29_12, sizeof(float *)); + + float * h_var_29_13 = (float *)malloc(sizeof(float *)); + float * d_var_29_13; + cudaMalloc((void **)&d_var_29_13, sizeof(float *)); + + float * h_var_29_14 = (float *)malloc(sizeof(float *)); + float * d_var_29_14; + cudaMalloc((void **)&d_var_29_14, sizeof(float *)); + + float * h_var_29_15 = (float *)malloc(sizeof(float *)); + float * d_var_29_15; + cudaMalloc((void **)&d_var_29_15, sizeof(float *)); + + float * h_var_29_16 = (float *)malloc(sizeof(float *)); + float * d_var_29_16; + cudaMalloc((void **)&d_var_29_16, sizeof(float *)); + + float * h_var_29_17 = (float *)malloc(sizeof(float *)); + float * d_var_29_17; + cudaMalloc((void **)&d_var_29_17, sizeof(float *)); + + float * h_var_29_18 = (float *)malloc(sizeof(float *)); + float * d_var_29_18; + cudaMalloc((void **)&d_var_29_18, sizeof(float *)); + + float * h_var_29_19 = (float *)malloc(sizeof(float *)); + float * d_var_29_19; + cudaMalloc((void **)&d_var_29_19, sizeof(float *)); + + float * h_var_30_0 = (float *)malloc(sizeof(float *)); + float * d_var_30_0; + cudaMalloc((void **)&d_var_30_0, sizeof(float *)); + + float * h_var_30_1 = (float *)malloc(sizeof(float *)); + float * d_var_30_1; + cudaMalloc((void **)&d_var_30_1, sizeof(float *)); + + float * h_var_30_2 = (float *)malloc(sizeof(float *)); + float * d_var_30_2; + cudaMalloc((void **)&d_var_30_2, sizeof(float *)); + + float * h_var_30_3 = (float *)malloc(sizeof(float *)); + float * d_var_30_3; + cudaMalloc((void **)&d_var_30_3, sizeof(float *)); + + float * h_var_30_4 = (float *)malloc(sizeof(float *)); + float * d_var_30_4; + cudaMalloc((void **)&d_var_30_4, sizeof(float *)); + + float * h_var_30_5 = (float *)malloc(sizeof(float *)); + float * d_var_30_5; + cudaMalloc((void **)&d_var_30_5, sizeof(float *)); + + float * h_var_30_6 = (float *)malloc(sizeof(float *)); + float * d_var_30_6; + cudaMalloc((void **)&d_var_30_6, sizeof(float *)); + + float * h_var_30_7 = (float *)malloc(sizeof(float *)); + float * d_var_30_7; + cudaMalloc((void **)&d_var_30_7, sizeof(float *)); + + float * h_var_30_8 = (float *)malloc(sizeof(float *)); + float * d_var_30_8; + cudaMalloc((void **)&d_var_30_8, sizeof(float *)); + + float * h_var_30_9 = (float *)malloc(sizeof(float *)); + float * d_var_30_9; + cudaMalloc((void **)&d_var_30_9, sizeof(float *)); + + float * h_var_30_10 = (float *)malloc(sizeof(float *)); + float * d_var_30_10; + cudaMalloc((void **)&d_var_30_10, sizeof(float *)); + + float * h_var_30_11 = (float *)malloc(sizeof(float *)); + float * d_var_30_11; + cudaMalloc((void **)&d_var_30_11, sizeof(float *)); + + float * h_var_30_12 = (float *)malloc(sizeof(float *)); + float * d_var_30_12; + cudaMalloc((void **)&d_var_30_12, sizeof(float *)); + + float * h_var_30_13 = (float *)malloc(sizeof(float *)); + float * d_var_30_13; + cudaMalloc((void **)&d_var_30_13, sizeof(float *)); + + float * h_var_30_14 = (float *)malloc(sizeof(float *)); + float * d_var_30_14; + cudaMalloc((void **)&d_var_30_14, sizeof(float *)); + + float * h_var_30_15 = (float *)malloc(sizeof(float *)); + float * d_var_30_15; + cudaMalloc((void **)&d_var_30_15, sizeof(float *)); + + float * h_var_30_16 = (float *)malloc(sizeof(float *)); + float * d_var_30_16; + cudaMalloc((void **)&d_var_30_16, sizeof(float *)); + + float * h_var_30_17 = (float *)malloc(sizeof(float *)); + float * d_var_30_17; + cudaMalloc((void **)&d_var_30_17, sizeof(float *)); + + float * h_var_30_18 = (float *)malloc(sizeof(float *)); + float * d_var_30_18; + cudaMalloc((void **)&d_var_30_18, sizeof(float *)); + + float * h_var_30_19 = (float *)malloc(sizeof(float *)); + float * d_var_30_19; + cudaMalloc((void **)&d_var_30_19, sizeof(float *)); + + float * h_var_31_0 = (float *)malloc(sizeof(float *)); + float * d_var_31_0; + cudaMalloc((void **)&d_var_31_0, sizeof(float *)); + + float * h_var_31_1 = (float *)malloc(sizeof(float *)); + float * d_var_31_1; + cudaMalloc((void **)&d_var_31_1, sizeof(float *)); + + float * h_var_31_2 = (float *)malloc(sizeof(float *)); + float * d_var_31_2; + cudaMalloc((void **)&d_var_31_2, sizeof(float *)); + + float * h_var_31_3 = (float *)malloc(sizeof(float *)); + float * d_var_31_3; + cudaMalloc((void **)&d_var_31_3, sizeof(float *)); + + float * h_var_31_4 = (float *)malloc(sizeof(float *)); + float * d_var_31_4; + cudaMalloc((void **)&d_var_31_4, sizeof(float *)); + + float * h_var_31_5 = (float *)malloc(sizeof(float *)); + float * d_var_31_5; + cudaMalloc((void **)&d_var_31_5, sizeof(float *)); + + float * h_var_31_6 = (float *)malloc(sizeof(float *)); + float * d_var_31_6; + cudaMalloc((void **)&d_var_31_6, sizeof(float *)); + + float * h_var_31_7 = (float *)malloc(sizeof(float *)); + float * d_var_31_7; + cudaMalloc((void **)&d_var_31_7, sizeof(float *)); + + float * h_var_31_8 = (float *)malloc(sizeof(float *)); + float * d_var_31_8; + cudaMalloc((void **)&d_var_31_8, sizeof(float *)); + + float * h_var_31_9 = (float *)malloc(sizeof(float *)); + float * d_var_31_9; + cudaMalloc((void **)&d_var_31_9, sizeof(float *)); + + float * h_var_31_10 = (float *)malloc(sizeof(float *)); + float * d_var_31_10; + cudaMalloc((void **)&d_var_31_10, sizeof(float *)); + + float * h_var_31_11 = (float *)malloc(sizeof(float *)); + float * d_var_31_11; + cudaMalloc((void **)&d_var_31_11, sizeof(float *)); + + float * h_var_31_12 = (float *)malloc(sizeof(float *)); + float * d_var_31_12; + cudaMalloc((void **)&d_var_31_12, sizeof(float *)); + + float * h_var_31_13 = (float *)malloc(sizeof(float *)); + float * d_var_31_13; + cudaMalloc((void **)&d_var_31_13, sizeof(float *)); + + float * h_var_31_14 = (float *)malloc(sizeof(float *)); + float * d_var_31_14; + cudaMalloc((void **)&d_var_31_14, sizeof(float *)); + + float * h_var_31_15 = (float *)malloc(sizeof(float *)); + float * d_var_31_15; + cudaMalloc((void **)&d_var_31_15, sizeof(float *)); + + float * h_var_31_16 = (float *)malloc(sizeof(float *)); + float * d_var_31_16; + cudaMalloc((void **)&d_var_31_16, sizeof(float *)); + + float * h_var_31_17 = (float *)malloc(sizeof(float *)); + float * d_var_31_17; + cudaMalloc((void **)&d_var_31_17, sizeof(float *)); + + float * h_var_31_18 = (float *)malloc(sizeof(float *)); + float * d_var_31_18; + cudaMalloc((void **)&d_var_31_18, sizeof(float *)); + + float * h_var_31_19 = (float *)malloc(sizeof(float *)); + float * d_var_31_19; + cudaMalloc((void **)&d_var_31_19, sizeof(float *)); + + float * h_var_32_0 = (float *)malloc(sizeof(float *)); + float * d_var_32_0; + cudaMalloc((void **)&d_var_32_0, sizeof(float *)); + + float * h_var_32_1 = (float *)malloc(sizeof(float *)); + float * d_var_32_1; + cudaMalloc((void **)&d_var_32_1, sizeof(float *)); + + float * h_var_32_2 = (float *)malloc(sizeof(float *)); + float * d_var_32_2; + cudaMalloc((void **)&d_var_32_2, sizeof(float *)); + + float * h_var_32_3 = (float *)malloc(sizeof(float *)); + float * d_var_32_3; + cudaMalloc((void **)&d_var_32_3, sizeof(float *)); + + float * h_var_32_4 = (float *)malloc(sizeof(float *)); + float * d_var_32_4; + cudaMalloc((void **)&d_var_32_4, sizeof(float *)); + + float * h_var_32_5 = (float *)malloc(sizeof(float *)); + float * d_var_32_5; + cudaMalloc((void **)&d_var_32_5, sizeof(float *)); + + float * h_var_32_6 = (float *)malloc(sizeof(float *)); + float * d_var_32_6; + cudaMalloc((void **)&d_var_32_6, sizeof(float *)); + + float * h_var_32_7 = (float *)malloc(sizeof(float *)); + float * d_var_32_7; + cudaMalloc((void **)&d_var_32_7, sizeof(float *)); + + float * h_var_32_8 = (float *)malloc(sizeof(float *)); + float * d_var_32_8; + cudaMalloc((void **)&d_var_32_8, sizeof(float *)); + + float * h_var_32_9 = (float *)malloc(sizeof(float *)); + float * d_var_32_9; + cudaMalloc((void **)&d_var_32_9, sizeof(float *)); + + float * h_var_32_10 = (float *)malloc(sizeof(float *)); + float * d_var_32_10; + cudaMalloc((void **)&d_var_32_10, sizeof(float *)); + + float * h_var_32_11 = (float *)malloc(sizeof(float *)); + float * d_var_32_11; + cudaMalloc((void **)&d_var_32_11, sizeof(float *)); + + float * h_var_32_12 = (float *)malloc(sizeof(float *)); + float * d_var_32_12; + cudaMalloc((void **)&d_var_32_12, sizeof(float *)); + + float * h_var_32_13 = (float *)malloc(sizeof(float *)); + float * d_var_32_13; + cudaMalloc((void **)&d_var_32_13, sizeof(float *)); + + float * h_var_32_14 = (float *)malloc(sizeof(float *)); + float * d_var_32_14; + cudaMalloc((void **)&d_var_32_14, sizeof(float *)); + + float * h_var_32_15 = (float *)malloc(sizeof(float *)); + float * d_var_32_15; + cudaMalloc((void **)&d_var_32_15, sizeof(float *)); + + float * h_var_32_16 = (float *)malloc(sizeof(float *)); + float * d_var_32_16; + cudaMalloc((void **)&d_var_32_16, sizeof(float *)); + + float * h_var_32_17 = (float *)malloc(sizeof(float *)); + float * d_var_32_17; + cudaMalloc((void **)&d_var_32_17, sizeof(float *)); + + float * h_var_32_18 = (float *)malloc(sizeof(float *)); + float * d_var_32_18; + cudaMalloc((void **)&d_var_32_18, sizeof(float *)); + + float * h_var_32_19 = (float *)malloc(sizeof(float *)); + float * d_var_32_19; + cudaMalloc((void **)&d_var_32_19, sizeof(float *)); + + float * h_var_33_0 = (float *)malloc(sizeof(float *)); + float * d_var_33_0; + cudaMalloc((void **)&d_var_33_0, sizeof(float *)); + + float * h_var_33_1 = (float *)malloc(sizeof(float *)); + float * d_var_33_1; + cudaMalloc((void **)&d_var_33_1, sizeof(float *)); + + float * h_var_33_2 = (float *)malloc(sizeof(float *)); + float * d_var_33_2; + cudaMalloc((void **)&d_var_33_2, sizeof(float *)); + + float * h_var_33_3 = (float *)malloc(sizeof(float *)); + float * d_var_33_3; + cudaMalloc((void **)&d_var_33_3, sizeof(float *)); + + float * h_var_33_4 = (float *)malloc(sizeof(float *)); + float * d_var_33_4; + cudaMalloc((void **)&d_var_33_4, sizeof(float *)); + + float * h_var_33_5 = (float *)malloc(sizeof(float *)); + float * d_var_33_5; + cudaMalloc((void **)&d_var_33_5, sizeof(float *)); + + float * h_var_33_6 = (float *)malloc(sizeof(float *)); + float * d_var_33_6; + cudaMalloc((void **)&d_var_33_6, sizeof(float *)); + + float * h_var_33_7 = (float *)malloc(sizeof(float *)); + float * d_var_33_7; + cudaMalloc((void **)&d_var_33_7, sizeof(float *)); + + float * h_var_33_8 = (float *)malloc(sizeof(float *)); + float * d_var_33_8; + cudaMalloc((void **)&d_var_33_8, sizeof(float *)); + + float * h_var_33_9 = (float *)malloc(sizeof(float *)); + float * d_var_33_9; + cudaMalloc((void **)&d_var_33_9, sizeof(float *)); + + float * h_var_33_10 = (float *)malloc(sizeof(float *)); + float * d_var_33_10; + cudaMalloc((void **)&d_var_33_10, sizeof(float *)); + + float * h_var_33_11 = (float *)malloc(sizeof(float *)); + float * d_var_33_11; + cudaMalloc((void **)&d_var_33_11, sizeof(float *)); + + float * h_var_33_12 = (float *)malloc(sizeof(float *)); + float * d_var_33_12; + cudaMalloc((void **)&d_var_33_12, sizeof(float *)); + + float * h_var_33_13 = (float *)malloc(sizeof(float *)); + float * d_var_33_13; + cudaMalloc((void **)&d_var_33_13, sizeof(float *)); + + float * h_var_33_14 = (float *)malloc(sizeof(float *)); + float * d_var_33_14; + cudaMalloc((void **)&d_var_33_14, sizeof(float *)); + + float * h_var_33_15 = (float *)malloc(sizeof(float *)); + float * d_var_33_15; + cudaMalloc((void **)&d_var_33_15, sizeof(float *)); + + float * h_var_33_16 = (float *)malloc(sizeof(float *)); + float * d_var_33_16; + cudaMalloc((void **)&d_var_33_16, sizeof(float *)); + + float * h_var_33_17 = (float *)malloc(sizeof(float *)); + float * d_var_33_17; + cudaMalloc((void **)&d_var_33_17, sizeof(float *)); + + float * h_var_33_18 = (float *)malloc(sizeof(float *)); + float * d_var_33_18; + cudaMalloc((void **)&d_var_33_18, sizeof(float *)); + + float * h_var_33_19 = (float *)malloc(sizeof(float *)); + float * d_var_33_19; + cudaMalloc((void **)&d_var_33_19, sizeof(float *)); + + float * h_var_34_0 = (float *)malloc(sizeof(float *)); + float * d_var_34_0; + cudaMalloc((void **)&d_var_34_0, sizeof(float *)); + + float * h_var_34_1 = (float *)malloc(sizeof(float *)); + float * d_var_34_1; + cudaMalloc((void **)&d_var_34_1, sizeof(float *)); + + float * h_var_34_2 = (float *)malloc(sizeof(float *)); + float * d_var_34_2; + cudaMalloc((void **)&d_var_34_2, sizeof(float *)); + + float * h_var_34_3 = (float *)malloc(sizeof(float *)); + float * d_var_34_3; + cudaMalloc((void **)&d_var_34_3, sizeof(float *)); + + float * h_var_34_4 = (float *)malloc(sizeof(float *)); + float * d_var_34_4; + cudaMalloc((void **)&d_var_34_4, sizeof(float *)); + + float * h_var_34_5 = (float *)malloc(sizeof(float *)); + float * d_var_34_5; + cudaMalloc((void **)&d_var_34_5, sizeof(float *)); + + float * h_var_34_6 = (float *)malloc(sizeof(float *)); + float * d_var_34_6; + cudaMalloc((void **)&d_var_34_6, sizeof(float *)); + + float * h_var_34_7 = (float *)malloc(sizeof(float *)); + float * d_var_34_7; + cudaMalloc((void **)&d_var_34_7, sizeof(float *)); + + float * h_var_34_8 = (float *)malloc(sizeof(float *)); + float * d_var_34_8; + cudaMalloc((void **)&d_var_34_8, sizeof(float *)); + + float * h_var_34_9 = (float *)malloc(sizeof(float *)); + float * d_var_34_9; + cudaMalloc((void **)&d_var_34_9, sizeof(float *)); + + float * h_var_34_10 = (float *)malloc(sizeof(float *)); + float * d_var_34_10; + cudaMalloc((void **)&d_var_34_10, sizeof(float *)); + + float * h_var_34_11 = (float *)malloc(sizeof(float *)); + float * d_var_34_11; + cudaMalloc((void **)&d_var_34_11, sizeof(float *)); + + float * h_var_34_12 = (float *)malloc(sizeof(float *)); + float * d_var_34_12; + cudaMalloc((void **)&d_var_34_12, sizeof(float *)); + + float * h_var_34_13 = (float *)malloc(sizeof(float *)); + float * d_var_34_13; + cudaMalloc((void **)&d_var_34_13, sizeof(float *)); + + float * h_var_34_14 = (float *)malloc(sizeof(float *)); + float * d_var_34_14; + cudaMalloc((void **)&d_var_34_14, sizeof(float *)); + + float * h_var_34_15 = (float *)malloc(sizeof(float *)); + float * d_var_34_15; + cudaMalloc((void **)&d_var_34_15, sizeof(float *)); + + float * h_var_34_16 = (float *)malloc(sizeof(float *)); + float * d_var_34_16; + cudaMalloc((void **)&d_var_34_16, sizeof(float *)); + + float * h_var_34_17 = (float *)malloc(sizeof(float *)); + float * d_var_34_17; + cudaMalloc((void **)&d_var_34_17, sizeof(float *)); + + float * h_var_34_18 = (float *)malloc(sizeof(float *)); + float * d_var_34_18; + cudaMalloc((void **)&d_var_34_18, sizeof(float *)); + + float * h_var_34_19 = (float *)malloc(sizeof(float *)); + float * d_var_34_19; + cudaMalloc((void **)&d_var_34_19, sizeof(float *)); + + float * h_var_35_0 = (float *)malloc(sizeof(float *)); + float * d_var_35_0; + cudaMalloc((void **)&d_var_35_0, sizeof(float *)); + + float * h_var_35_1 = (float *)malloc(sizeof(float *)); + float * d_var_35_1; + cudaMalloc((void **)&d_var_35_1, sizeof(float *)); + + float * h_var_35_2 = (float *)malloc(sizeof(float *)); + float * d_var_35_2; + cudaMalloc((void **)&d_var_35_2, sizeof(float *)); + + float * h_var_35_3 = (float *)malloc(sizeof(float *)); + float * d_var_35_3; + cudaMalloc((void **)&d_var_35_3, sizeof(float *)); + + float * h_var_35_4 = (float *)malloc(sizeof(float *)); + float * d_var_35_4; + cudaMalloc((void **)&d_var_35_4, sizeof(float *)); + + float * h_var_35_5 = (float *)malloc(sizeof(float *)); + float * d_var_35_5; + cudaMalloc((void **)&d_var_35_5, sizeof(float *)); + + float * h_var_35_6 = (float *)malloc(sizeof(float *)); + float * d_var_35_6; + cudaMalloc((void **)&d_var_35_6, sizeof(float *)); + + float * h_var_35_7 = (float *)malloc(sizeof(float *)); + float * d_var_35_7; + cudaMalloc((void **)&d_var_35_7, sizeof(float *)); + + float * h_var_35_8 = (float *)malloc(sizeof(float *)); + float * d_var_35_8; + cudaMalloc((void **)&d_var_35_8, sizeof(float *)); + + float * h_var_35_9 = (float *)malloc(sizeof(float *)); + float * d_var_35_9; + cudaMalloc((void **)&d_var_35_9, sizeof(float *)); + + float * h_var_35_10 = (float *)malloc(sizeof(float *)); + float * d_var_35_10; + cudaMalloc((void **)&d_var_35_10, sizeof(float *)); + + float * h_var_35_11 = (float *)malloc(sizeof(float *)); + float * d_var_35_11; + cudaMalloc((void **)&d_var_35_11, sizeof(float *)); + + float * h_var_35_12 = (float *)malloc(sizeof(float *)); + float * d_var_35_12; + cudaMalloc((void **)&d_var_35_12, sizeof(float *)); + + float * h_var_35_13 = (float *)malloc(sizeof(float *)); + float * d_var_35_13; + cudaMalloc((void **)&d_var_35_13, sizeof(float *)); + + float * h_var_35_14 = (float *)malloc(sizeof(float *)); + float * d_var_35_14; + cudaMalloc((void **)&d_var_35_14, sizeof(float *)); + + float * h_var_35_15 = (float *)malloc(sizeof(float *)); + float * d_var_35_15; + cudaMalloc((void **)&d_var_35_15, sizeof(float *)); + + float * h_var_35_16 = (float *)malloc(sizeof(float *)); + float * d_var_35_16; + cudaMalloc((void **)&d_var_35_16, sizeof(float *)); + + float * h_var_35_17 = (float *)malloc(sizeof(float *)); + float * d_var_35_17; + cudaMalloc((void **)&d_var_35_17, sizeof(float *)); + + float * h_var_35_18 = (float *)malloc(sizeof(float *)); + float * d_var_35_18; + cudaMalloc((void **)&d_var_35_18, sizeof(float *)); + + float * h_var_35_19 = (float *)malloc(sizeof(float *)); + float * d_var_35_19; + cudaMalloc((void **)&d_var_35_19, sizeof(float *)); + + float * h_var_36_0 = (float *)malloc(sizeof(float *)); + float * d_var_36_0; + cudaMalloc((void **)&d_var_36_0, sizeof(float *)); + + float * h_var_36_1 = (float *)malloc(sizeof(float *)); + float * d_var_36_1; + cudaMalloc((void **)&d_var_36_1, sizeof(float *)); + + float * h_var_36_2 = (float *)malloc(sizeof(float *)); + float * d_var_36_2; + cudaMalloc((void **)&d_var_36_2, sizeof(float *)); + + float * h_var_36_3 = (float *)malloc(sizeof(float *)); + float * d_var_36_3; + cudaMalloc((void **)&d_var_36_3, sizeof(float *)); + + float * h_var_36_4 = (float *)malloc(sizeof(float *)); + float * d_var_36_4; + cudaMalloc((void **)&d_var_36_4, sizeof(float *)); + + float * h_var_36_5 = (float *)malloc(sizeof(float *)); + float * d_var_36_5; + cudaMalloc((void **)&d_var_36_5, sizeof(float *)); + + float * h_var_36_6 = (float *)malloc(sizeof(float *)); + float * d_var_36_6; + cudaMalloc((void **)&d_var_36_6, sizeof(float *)); + + float * h_var_36_7 = (float *)malloc(sizeof(float *)); + float * d_var_36_7; + cudaMalloc((void **)&d_var_36_7, sizeof(float *)); + + float * h_var_36_8 = (float *)malloc(sizeof(float *)); + float * d_var_36_8; + cudaMalloc((void **)&d_var_36_8, sizeof(float *)); + + float * h_var_36_9 = (float *)malloc(sizeof(float *)); + float * d_var_36_9; + cudaMalloc((void **)&d_var_36_9, sizeof(float *)); + + float * h_var_36_10 = (float *)malloc(sizeof(float *)); + float * d_var_36_10; + cudaMalloc((void **)&d_var_36_10, sizeof(float *)); + + float * h_var_36_11 = (float *)malloc(sizeof(float *)); + float * d_var_36_11; + cudaMalloc((void **)&d_var_36_11, sizeof(float *)); + + float * h_var_36_12 = (float *)malloc(sizeof(float *)); + float * d_var_36_12; + cudaMalloc((void **)&d_var_36_12, sizeof(float *)); + + float * h_var_36_13 = (float *)malloc(sizeof(float *)); + float * d_var_36_13; + cudaMalloc((void **)&d_var_36_13, sizeof(float *)); + + float * h_var_36_14 = (float *)malloc(sizeof(float *)); + float * d_var_36_14; + cudaMalloc((void **)&d_var_36_14, sizeof(float *)); + + float * h_var_36_15 = (float *)malloc(sizeof(float *)); + float * d_var_36_15; + cudaMalloc((void **)&d_var_36_15, sizeof(float *)); + + float * h_var_36_16 = (float *)malloc(sizeof(float *)); + float * d_var_36_16; + cudaMalloc((void **)&d_var_36_16, sizeof(float *)); + + float * h_var_36_17 = (float *)malloc(sizeof(float *)); + float * d_var_36_17; + cudaMalloc((void **)&d_var_36_17, sizeof(float *)); + + float * h_var_36_18 = (float *)malloc(sizeof(float *)); + float * d_var_36_18; + cudaMalloc((void **)&d_var_36_18, sizeof(float *)); + + float * h_var_36_19 = (float *)malloc(sizeof(float *)); + float * d_var_36_19; + cudaMalloc((void **)&d_var_36_19, sizeof(float *)); + + float * h_var_37_0 = (float *)malloc(sizeof(float *)); + float * d_var_37_0; + cudaMalloc((void **)&d_var_37_0, sizeof(float *)); + + float * h_var_37_1 = (float *)malloc(sizeof(float *)); + float * d_var_37_1; + cudaMalloc((void **)&d_var_37_1, sizeof(float *)); + + float * h_var_37_2 = (float *)malloc(sizeof(float *)); + float * d_var_37_2; + cudaMalloc((void **)&d_var_37_2, sizeof(float *)); + + float * h_var_37_3 = (float *)malloc(sizeof(float *)); + float * d_var_37_3; + cudaMalloc((void **)&d_var_37_3, sizeof(float *)); + + float * h_var_37_4 = (float *)malloc(sizeof(float *)); + float * d_var_37_4; + cudaMalloc((void **)&d_var_37_4, sizeof(float *)); + + float * h_var_37_5 = (float *)malloc(sizeof(float *)); + float * d_var_37_5; + cudaMalloc((void **)&d_var_37_5, sizeof(float *)); + + float * h_var_37_6 = (float *)malloc(sizeof(float *)); + float * d_var_37_6; + cudaMalloc((void **)&d_var_37_6, sizeof(float *)); + + float * h_var_37_7 = (float *)malloc(sizeof(float *)); + float * d_var_37_7; + cudaMalloc((void **)&d_var_37_7, sizeof(float *)); + + float * h_var_37_8 = (float *)malloc(sizeof(float *)); + float * d_var_37_8; + cudaMalloc((void **)&d_var_37_8, sizeof(float *)); + + float * h_var_37_9 = (float *)malloc(sizeof(float *)); + float * d_var_37_9; + cudaMalloc((void **)&d_var_37_9, sizeof(float *)); + + float * h_var_37_10 = (float *)malloc(sizeof(float *)); + float * d_var_37_10; + cudaMalloc((void **)&d_var_37_10, sizeof(float *)); + + float * h_var_37_11 = (float *)malloc(sizeof(float *)); + float * d_var_37_11; + cudaMalloc((void **)&d_var_37_11, sizeof(float *)); + + float * h_var_37_12 = (float *)malloc(sizeof(float *)); + float * d_var_37_12; + cudaMalloc((void **)&d_var_37_12, sizeof(float *)); + + float * h_var_37_13 = (float *)malloc(sizeof(float *)); + float * d_var_37_13; + cudaMalloc((void **)&d_var_37_13, sizeof(float *)); + + float * h_var_37_14 = (float *)malloc(sizeof(float *)); + float * d_var_37_14; + cudaMalloc((void **)&d_var_37_14, sizeof(float *)); + + float * h_var_37_15 = (float *)malloc(sizeof(float *)); + float * d_var_37_15; + cudaMalloc((void **)&d_var_37_15, sizeof(float *)); + + float * h_var_37_16 = (float *)malloc(sizeof(float *)); + float * d_var_37_16; + cudaMalloc((void **)&d_var_37_16, sizeof(float *)); + + float * h_var_37_17 = (float *)malloc(sizeof(float *)); + float * d_var_37_17; + cudaMalloc((void **)&d_var_37_17, sizeof(float *)); + + float * h_var_37_18 = (float *)malloc(sizeof(float *)); + float * d_var_37_18; + cudaMalloc((void **)&d_var_37_18, sizeof(float *)); + + float * h_var_37_19 = (float *)malloc(sizeof(float *)); + float * d_var_37_19; + cudaMalloc((void **)&d_var_37_19, sizeof(float *)); + + float * h_var_38_0 = (float *)malloc(sizeof(float *)); + float * d_var_38_0; + cudaMalloc((void **)&d_var_38_0, sizeof(float *)); + + float * h_var_38_1 = (float *)malloc(sizeof(float *)); + float * d_var_38_1; + cudaMalloc((void **)&d_var_38_1, sizeof(float *)); + + float * h_var_38_2 = (float *)malloc(sizeof(float *)); + float * d_var_38_2; + cudaMalloc((void **)&d_var_38_2, sizeof(float *)); + + float * h_var_38_3 = (float *)malloc(sizeof(float *)); + float * d_var_38_3; + cudaMalloc((void **)&d_var_38_3, sizeof(float *)); + + float * h_var_38_4 = (float *)malloc(sizeof(float *)); + float * d_var_38_4; + cudaMalloc((void **)&d_var_38_4, sizeof(float *)); + + float * h_var_38_5 = (float *)malloc(sizeof(float *)); + float * d_var_38_5; + cudaMalloc((void **)&d_var_38_5, sizeof(float *)); + + float * h_var_38_6 = (float *)malloc(sizeof(float *)); + float * d_var_38_6; + cudaMalloc((void **)&d_var_38_6, sizeof(float *)); + + float * h_var_38_7 = (float *)malloc(sizeof(float *)); + float * d_var_38_7; + cudaMalloc((void **)&d_var_38_7, sizeof(float *)); + + float * h_var_38_8 = (float *)malloc(sizeof(float *)); + float * d_var_38_8; + cudaMalloc((void **)&d_var_38_8, sizeof(float *)); + + float * h_var_38_9 = (float *)malloc(sizeof(float *)); + float * d_var_38_9; + cudaMalloc((void **)&d_var_38_9, sizeof(float *)); + + float * h_var_38_10 = (float *)malloc(sizeof(float *)); + float * d_var_38_10; + cudaMalloc((void **)&d_var_38_10, sizeof(float *)); + + float * h_var_38_11 = (float *)malloc(sizeof(float *)); + float * d_var_38_11; + cudaMalloc((void **)&d_var_38_11, sizeof(float *)); + + float * h_var_38_12 = (float *)malloc(sizeof(float *)); + float * d_var_38_12; + cudaMalloc((void **)&d_var_38_12, sizeof(float *)); + + float * h_var_38_13 = (float *)malloc(sizeof(float *)); + float * d_var_38_13; + cudaMalloc((void **)&d_var_38_13, sizeof(float *)); + + float * h_var_38_14 = (float *)malloc(sizeof(float *)); + float * d_var_38_14; + cudaMalloc((void **)&d_var_38_14, sizeof(float *)); + + float * h_var_38_15 = (float *)malloc(sizeof(float *)); + float * d_var_38_15; + cudaMalloc((void **)&d_var_38_15, sizeof(float *)); + + float * h_var_38_16 = (float *)malloc(sizeof(float *)); + float * d_var_38_16; + cudaMalloc((void **)&d_var_38_16, sizeof(float *)); + + float * h_var_38_17 = (float *)malloc(sizeof(float *)); + float * d_var_38_17; + cudaMalloc((void **)&d_var_38_17, sizeof(float *)); + + float * h_var_38_18 = (float *)malloc(sizeof(float *)); + float * d_var_38_18; + cudaMalloc((void **)&d_var_38_18, sizeof(float *)); + + float * h_var_38_19 = (float *)malloc(sizeof(float *)); + float * d_var_38_19; + cudaMalloc((void **)&d_var_38_19, sizeof(float *)); + + float * h_var_39_0 = (float *)malloc(sizeof(float *)); + float * d_var_39_0; + cudaMalloc((void **)&d_var_39_0, sizeof(float *)); + + float * h_var_39_1 = (float *)malloc(sizeof(float *)); + float * d_var_39_1; + cudaMalloc((void **)&d_var_39_1, sizeof(float *)); + + float * h_var_39_2 = (float *)malloc(sizeof(float *)); + float * d_var_39_2; + cudaMalloc((void **)&d_var_39_2, sizeof(float *)); + + float * h_var_39_3 = (float *)malloc(sizeof(float *)); + float * d_var_39_3; + cudaMalloc((void **)&d_var_39_3, sizeof(float *)); + + float * h_var_39_4 = (float *)malloc(sizeof(float *)); + float * d_var_39_4; + cudaMalloc((void **)&d_var_39_4, sizeof(float *)); + + float * h_var_39_5 = (float *)malloc(sizeof(float *)); + float * d_var_39_5; + cudaMalloc((void **)&d_var_39_5, sizeof(float *)); + + float * h_var_39_6 = (float *)malloc(sizeof(float *)); + float * d_var_39_6; + cudaMalloc((void **)&d_var_39_6, sizeof(float *)); + + float * h_var_39_7 = (float *)malloc(sizeof(float *)); + float * d_var_39_7; + cudaMalloc((void **)&d_var_39_7, sizeof(float *)); + + float * h_var_39_8 = (float *)malloc(sizeof(float *)); + float * d_var_39_8; + cudaMalloc((void **)&d_var_39_8, sizeof(float *)); + + float * h_var_39_9 = (float *)malloc(sizeof(float *)); + float * d_var_39_9; + cudaMalloc((void **)&d_var_39_9, sizeof(float *)); + + float * h_var_39_10 = (float *)malloc(sizeof(float *)); + float * d_var_39_10; + cudaMalloc((void **)&d_var_39_10, sizeof(float *)); + + float * h_var_39_11 = (float *)malloc(sizeof(float *)); + float * d_var_39_11; + cudaMalloc((void **)&d_var_39_11, sizeof(float *)); + + float * h_var_39_12 = (float *)malloc(sizeof(float *)); + float * d_var_39_12; + cudaMalloc((void **)&d_var_39_12, sizeof(float *)); + + float * h_var_39_13 = (float *)malloc(sizeof(float *)); + float * d_var_39_13; + cudaMalloc((void **)&d_var_39_13, sizeof(float *)); + + float * h_var_39_14 = (float *)malloc(sizeof(float *)); + float * d_var_39_14; + cudaMalloc((void **)&d_var_39_14, sizeof(float *)); + + float * h_var_39_15 = (float *)malloc(sizeof(float *)); + float * d_var_39_15; + cudaMalloc((void **)&d_var_39_15, sizeof(float *)); + + float * h_var_39_16 = (float *)malloc(sizeof(float *)); + float * d_var_39_16; + cudaMalloc((void **)&d_var_39_16, sizeof(float *)); + + float * h_var_39_17 = (float *)malloc(sizeof(float *)); + float * d_var_39_17; + cudaMalloc((void **)&d_var_39_17, sizeof(float *)); + + float * h_var_39_18 = (float *)malloc(sizeof(float *)); + float * d_var_39_18; + cudaMalloc((void **)&d_var_39_18, sizeof(float *)); + + float * h_var_39_19 = (float *)malloc(sizeof(float *)); + float * d_var_39_19; + cudaMalloc((void **)&d_var_39_19, sizeof(float *)); + + float * h_var_40_0 = (float *)malloc(sizeof(float *)); + float * d_var_40_0; + cudaMalloc((void **)&d_var_40_0, sizeof(float *)); + + float * h_var_40_1 = (float *)malloc(sizeof(float *)); + float * d_var_40_1; + cudaMalloc((void **)&d_var_40_1, sizeof(float *)); + + float * h_var_40_2 = (float *)malloc(sizeof(float *)); + float * d_var_40_2; + cudaMalloc((void **)&d_var_40_2, sizeof(float *)); + + float * h_var_40_3 = (float *)malloc(sizeof(float *)); + float * d_var_40_3; + cudaMalloc((void **)&d_var_40_3, sizeof(float *)); + + float * h_var_40_4 = (float *)malloc(sizeof(float *)); + float * d_var_40_4; + cudaMalloc((void **)&d_var_40_4, sizeof(float *)); + + float * h_var_40_5 = (float *)malloc(sizeof(float *)); + float * d_var_40_5; + cudaMalloc((void **)&d_var_40_5, sizeof(float *)); + + float * h_var_40_6 = (float *)malloc(sizeof(float *)); + float * d_var_40_6; + cudaMalloc((void **)&d_var_40_6, sizeof(float *)); + + float * h_var_40_7 = (float *)malloc(sizeof(float *)); + float * d_var_40_7; + cudaMalloc((void **)&d_var_40_7, sizeof(float *)); + + float * h_var_40_8 = (float *)malloc(sizeof(float *)); + float * d_var_40_8; + cudaMalloc((void **)&d_var_40_8, sizeof(float *)); + + float * h_var_40_9 = (float *)malloc(sizeof(float *)); + float * d_var_40_9; + cudaMalloc((void **)&d_var_40_9, sizeof(float *)); + + float * h_var_40_10 = (float *)malloc(sizeof(float *)); + float * d_var_40_10; + cudaMalloc((void **)&d_var_40_10, sizeof(float *)); + + float * h_var_40_11 = (float *)malloc(sizeof(float *)); + float * d_var_40_11; + cudaMalloc((void **)&d_var_40_11, sizeof(float *)); + + float * h_var_40_12 = (float *)malloc(sizeof(float *)); + float * d_var_40_12; + cudaMalloc((void **)&d_var_40_12, sizeof(float *)); + + float * h_var_40_13 = (float *)malloc(sizeof(float *)); + float * d_var_40_13; + cudaMalloc((void **)&d_var_40_13, sizeof(float *)); + + float * h_var_40_14 = (float *)malloc(sizeof(float *)); + float * d_var_40_14; + cudaMalloc((void **)&d_var_40_14, sizeof(float *)); + + float * h_var_40_15 = (float *)malloc(sizeof(float *)); + float * d_var_40_15; + cudaMalloc((void **)&d_var_40_15, sizeof(float *)); + + float * h_var_40_16 = (float *)malloc(sizeof(float *)); + float * d_var_40_16; + cudaMalloc((void **)&d_var_40_16, sizeof(float *)); + + float * h_var_40_17 = (float *)malloc(sizeof(float *)); + float * d_var_40_17; + cudaMalloc((void **)&d_var_40_17, sizeof(float *)); + + float * h_var_40_18 = (float *)malloc(sizeof(float *)); + float * d_var_40_18; + cudaMalloc((void **)&d_var_40_18, sizeof(float *)); + + float * h_var_40_19 = (float *)malloc(sizeof(float *)); + float * d_var_40_19; + cudaMalloc((void **)&d_var_40_19, sizeof(float *)); + + float * h_var_41_0 = (float *)malloc(sizeof(float *)); + float * d_var_41_0; + cudaMalloc((void **)&d_var_41_0, sizeof(float *)); + + float * h_var_41_1 = (float *)malloc(sizeof(float *)); + float * d_var_41_1; + cudaMalloc((void **)&d_var_41_1, sizeof(float *)); + + float * h_var_41_2 = (float *)malloc(sizeof(float *)); + float * d_var_41_2; + cudaMalloc((void **)&d_var_41_2, sizeof(float *)); + + float * h_var_41_3 = (float *)malloc(sizeof(float *)); + float * d_var_41_3; + cudaMalloc((void **)&d_var_41_3, sizeof(float *)); + + float * h_var_41_4 = (float *)malloc(sizeof(float *)); + float * d_var_41_4; + cudaMalloc((void **)&d_var_41_4, sizeof(float *)); + + float * h_var_41_5 = (float *)malloc(sizeof(float *)); + float * d_var_41_5; + cudaMalloc((void **)&d_var_41_5, sizeof(float *)); + + float * h_var_41_6 = (float *)malloc(sizeof(float *)); + float * d_var_41_6; + cudaMalloc((void **)&d_var_41_6, sizeof(float *)); + + float * h_var_41_7 = (float *)malloc(sizeof(float *)); + float * d_var_41_7; + cudaMalloc((void **)&d_var_41_7, sizeof(float *)); + + float * h_var_41_8 = (float *)malloc(sizeof(float *)); + float * d_var_41_8; + cudaMalloc((void **)&d_var_41_8, sizeof(float *)); + + float * h_var_41_9 = (float *)malloc(sizeof(float *)); + float * d_var_41_9; + cudaMalloc((void **)&d_var_41_9, sizeof(float *)); + + float * h_var_41_10 = (float *)malloc(sizeof(float *)); + float * d_var_41_10; + cudaMalloc((void **)&d_var_41_10, sizeof(float *)); + + float * h_var_41_11 = (float *)malloc(sizeof(float *)); + float * d_var_41_11; + cudaMalloc((void **)&d_var_41_11, sizeof(float *)); + + float * h_var_41_12 = (float *)malloc(sizeof(float *)); + float * d_var_41_12; + cudaMalloc((void **)&d_var_41_12, sizeof(float *)); + + float * h_var_41_13 = (float *)malloc(sizeof(float *)); + float * d_var_41_13; + cudaMalloc((void **)&d_var_41_13, sizeof(float *)); + + float * h_var_41_14 = (float *)malloc(sizeof(float *)); + float * d_var_41_14; + cudaMalloc((void **)&d_var_41_14, sizeof(float *)); + + float * h_var_41_15 = (float *)malloc(sizeof(float *)); + float * d_var_41_15; + cudaMalloc((void **)&d_var_41_15, sizeof(float *)); + + float * h_var_41_16 = (float *)malloc(sizeof(float *)); + float * d_var_41_16; + cudaMalloc((void **)&d_var_41_16, sizeof(float *)); + + float * h_var_41_17 = (float *)malloc(sizeof(float *)); + float * d_var_41_17; + cudaMalloc((void **)&d_var_41_17, sizeof(float *)); + + float * h_var_41_18 = (float *)malloc(sizeof(float *)); + float * d_var_41_18; + cudaMalloc((void **)&d_var_41_18, sizeof(float *)); + + float * h_var_41_19 = (float *)malloc(sizeof(float *)); + float * d_var_41_19; + cudaMalloc((void **)&d_var_41_19, sizeof(float *)); + + float * h_var_42_0 = (float *)malloc(sizeof(float *)); + float * d_var_42_0; + cudaMalloc((void **)&d_var_42_0, sizeof(float *)); + + float * h_var_42_1 = (float *)malloc(sizeof(float *)); + float * d_var_42_1; + cudaMalloc((void **)&d_var_42_1, sizeof(float *)); + + float * h_var_42_2 = (float *)malloc(sizeof(float *)); + float * d_var_42_2; + cudaMalloc((void **)&d_var_42_2, sizeof(float *)); + + float * h_var_42_3 = (float *)malloc(sizeof(float *)); + float * d_var_42_3; + cudaMalloc((void **)&d_var_42_3, sizeof(float *)); + + float * h_var_42_4 = (float *)malloc(sizeof(float *)); + float * d_var_42_4; + cudaMalloc((void **)&d_var_42_4, sizeof(float *)); + + float * h_var_42_5 = (float *)malloc(sizeof(float *)); + float * d_var_42_5; + cudaMalloc((void **)&d_var_42_5, sizeof(float *)); + + float * h_var_42_6 = (float *)malloc(sizeof(float *)); + float * d_var_42_6; + cudaMalloc((void **)&d_var_42_6, sizeof(float *)); + + float * h_var_42_7 = (float *)malloc(sizeof(float *)); + float * d_var_42_7; + cudaMalloc((void **)&d_var_42_7, sizeof(float *)); + + float * h_var_42_8 = (float *)malloc(sizeof(float *)); + float * d_var_42_8; + cudaMalloc((void **)&d_var_42_8, sizeof(float *)); + + float * h_var_42_9 = (float *)malloc(sizeof(float *)); + float * d_var_42_9; + cudaMalloc((void **)&d_var_42_9, sizeof(float *)); + + float * h_var_42_10 = (float *)malloc(sizeof(float *)); + float * d_var_42_10; + cudaMalloc((void **)&d_var_42_10, sizeof(float *)); + + float * h_var_42_11 = (float *)malloc(sizeof(float *)); + float * d_var_42_11; + cudaMalloc((void **)&d_var_42_11, sizeof(float *)); + + float * h_var_42_12 = (float *)malloc(sizeof(float *)); + float * d_var_42_12; + cudaMalloc((void **)&d_var_42_12, sizeof(float *)); + + float * h_var_42_13 = (float *)malloc(sizeof(float *)); + float * d_var_42_13; + cudaMalloc((void **)&d_var_42_13, sizeof(float *)); + + float * h_var_42_14 = (float *)malloc(sizeof(float *)); + float * d_var_42_14; + cudaMalloc((void **)&d_var_42_14, sizeof(float *)); + + float * h_var_42_15 = (float *)malloc(sizeof(float *)); + float * d_var_42_15; + cudaMalloc((void **)&d_var_42_15, sizeof(float *)); + + float * h_var_42_16 = (float *)malloc(sizeof(float *)); + float * d_var_42_16; + cudaMalloc((void **)&d_var_42_16, sizeof(float *)); + + float * h_var_42_17 = (float *)malloc(sizeof(float *)); + float * d_var_42_17; + cudaMalloc((void **)&d_var_42_17, sizeof(float *)); + + float * h_var_42_18 = (float *)malloc(sizeof(float *)); + float * d_var_42_18; + cudaMalloc((void **)&d_var_42_18, sizeof(float *)); + + float * h_var_42_19 = (float *)malloc(sizeof(float *)); + float * d_var_42_19; + cudaMalloc((void **)&d_var_42_19, sizeof(float *)); + + float * h_var_43_0 = (float *)malloc(sizeof(float *)); + float * d_var_43_0; + cudaMalloc((void **)&d_var_43_0, sizeof(float *)); + + float * h_var_43_1 = (float *)malloc(sizeof(float *)); + float * d_var_43_1; + cudaMalloc((void **)&d_var_43_1, sizeof(float *)); + + float * h_var_43_2 = (float *)malloc(sizeof(float *)); + float * d_var_43_2; + cudaMalloc((void **)&d_var_43_2, sizeof(float *)); + + float * h_var_43_3 = (float *)malloc(sizeof(float *)); + float * d_var_43_3; + cudaMalloc((void **)&d_var_43_3, sizeof(float *)); + + float * h_var_43_4 = (float *)malloc(sizeof(float *)); + float * d_var_43_4; + cudaMalloc((void **)&d_var_43_4, sizeof(float *)); + + float * h_var_43_5 = (float *)malloc(sizeof(float *)); + float * d_var_43_5; + cudaMalloc((void **)&d_var_43_5, sizeof(float *)); + + float * h_var_43_6 = (float *)malloc(sizeof(float *)); + float * d_var_43_6; + cudaMalloc((void **)&d_var_43_6, sizeof(float *)); + + float * h_var_43_7 = (float *)malloc(sizeof(float *)); + float * d_var_43_7; + cudaMalloc((void **)&d_var_43_7, sizeof(float *)); + + float * h_var_43_8 = (float *)malloc(sizeof(float *)); + float * d_var_43_8; + cudaMalloc((void **)&d_var_43_8, sizeof(float *)); + + float * h_var_43_9 = (float *)malloc(sizeof(float *)); + float * d_var_43_9; + cudaMalloc((void **)&d_var_43_9, sizeof(float *)); + + float * h_var_43_10 = (float *)malloc(sizeof(float *)); + float * d_var_43_10; + cudaMalloc((void **)&d_var_43_10, sizeof(float *)); + + float * h_var_43_11 = (float *)malloc(sizeof(float *)); + float * d_var_43_11; + cudaMalloc((void **)&d_var_43_11, sizeof(float *)); + + float * h_var_43_12 = (float *)malloc(sizeof(float *)); + float * d_var_43_12; + cudaMalloc((void **)&d_var_43_12, sizeof(float *)); + + float * h_var_43_13 = (float *)malloc(sizeof(float *)); + float * d_var_43_13; + cudaMalloc((void **)&d_var_43_13, sizeof(float *)); + + float * h_var_43_14 = (float *)malloc(sizeof(float *)); + float * d_var_43_14; + cudaMalloc((void **)&d_var_43_14, sizeof(float *)); + + float * h_var_43_15 = (float *)malloc(sizeof(float *)); + float * d_var_43_15; + cudaMalloc((void **)&d_var_43_15, sizeof(float *)); + + float * h_var_43_16 = (float *)malloc(sizeof(float *)); + float * d_var_43_16; + cudaMalloc((void **)&d_var_43_16, sizeof(float *)); + + float * h_var_43_17 = (float *)malloc(sizeof(float *)); + float * d_var_43_17; + cudaMalloc((void **)&d_var_43_17, sizeof(float *)); + + float * h_var_43_18 = (float *)malloc(sizeof(float *)); + float * d_var_43_18; + cudaMalloc((void **)&d_var_43_18, sizeof(float *)); + + float * h_var_43_19 = (float *)malloc(sizeof(float *)); + float * d_var_43_19; + cudaMalloc((void **)&d_var_43_19, sizeof(float *)); + + float * h_var_44_0 = (float *)malloc(sizeof(float *)); + float * d_var_44_0; + cudaMalloc((void **)&d_var_44_0, sizeof(float *)); + + float * h_var_44_1 = (float *)malloc(sizeof(float *)); + float * d_var_44_1; + cudaMalloc((void **)&d_var_44_1, sizeof(float *)); + + float * h_var_44_2 = (float *)malloc(sizeof(float *)); + float * d_var_44_2; + cudaMalloc((void **)&d_var_44_2, sizeof(float *)); + + float * h_var_44_3 = (float *)malloc(sizeof(float *)); + float * d_var_44_3; + cudaMalloc((void **)&d_var_44_3, sizeof(float *)); + + float * h_var_44_4 = (float *)malloc(sizeof(float *)); + float * d_var_44_4; + cudaMalloc((void **)&d_var_44_4, sizeof(float *)); + + float * h_var_44_5 = (float *)malloc(sizeof(float *)); + float * d_var_44_5; + cudaMalloc((void **)&d_var_44_5, sizeof(float *)); + + float * h_var_44_6 = (float *)malloc(sizeof(float *)); + float * d_var_44_6; + cudaMalloc((void **)&d_var_44_6, sizeof(float *)); + + float * h_var_44_7 = (float *)malloc(sizeof(float *)); + float * d_var_44_7; + cudaMalloc((void **)&d_var_44_7, sizeof(float *)); + + float * h_var_44_8 = (float *)malloc(sizeof(float *)); + float * d_var_44_8; + cudaMalloc((void **)&d_var_44_8, sizeof(float *)); + + float * h_var_44_9 = (float *)malloc(sizeof(float *)); + float * d_var_44_9; + cudaMalloc((void **)&d_var_44_9, sizeof(float *)); + + float * h_var_44_10 = (float *)malloc(sizeof(float *)); + float * d_var_44_10; + cudaMalloc((void **)&d_var_44_10, sizeof(float *)); + + float * h_var_44_11 = (float *)malloc(sizeof(float *)); + float * d_var_44_11; + cudaMalloc((void **)&d_var_44_11, sizeof(float *)); + + float * h_var_44_12 = (float *)malloc(sizeof(float *)); + float * d_var_44_12; + cudaMalloc((void **)&d_var_44_12, sizeof(float *)); + + float * h_var_44_13 = (float *)malloc(sizeof(float *)); + float * d_var_44_13; + cudaMalloc((void **)&d_var_44_13, sizeof(float *)); + + float * h_var_44_14 = (float *)malloc(sizeof(float *)); + float * d_var_44_14; + cudaMalloc((void **)&d_var_44_14, sizeof(float *)); + + float * h_var_44_15 = (float *)malloc(sizeof(float *)); + float * d_var_44_15; + cudaMalloc((void **)&d_var_44_15, sizeof(float *)); + + float * h_var_44_16 = (float *)malloc(sizeof(float *)); + float * d_var_44_16; + cudaMalloc((void **)&d_var_44_16, sizeof(float *)); + + float * h_var_44_17 = (float *)malloc(sizeof(float *)); + float * d_var_44_17; + cudaMalloc((void **)&d_var_44_17, sizeof(float *)); + + float * h_var_44_18 = (float *)malloc(sizeof(float *)); + float * d_var_44_18; + cudaMalloc((void **)&d_var_44_18, sizeof(float *)); + + float * h_var_44_19 = (float *)malloc(sizeof(float *)); + float * d_var_44_19; + cudaMalloc((void **)&d_var_44_19, sizeof(float *)); + + float * h_var_45_0 = (float *)malloc(sizeof(float *)); + float * d_var_45_0; + cudaMalloc((void **)&d_var_45_0, sizeof(float *)); + + float * h_var_45_1 = (float *)malloc(sizeof(float *)); + float * d_var_45_1; + cudaMalloc((void **)&d_var_45_1, sizeof(float *)); + + float * h_var_45_2 = (float *)malloc(sizeof(float *)); + float * d_var_45_2; + cudaMalloc((void **)&d_var_45_2, sizeof(float *)); + + float * h_var_45_3 = (float *)malloc(sizeof(float *)); + float * d_var_45_3; + cudaMalloc((void **)&d_var_45_3, sizeof(float *)); + + float * h_var_45_4 = (float *)malloc(sizeof(float *)); + float * d_var_45_4; + cudaMalloc((void **)&d_var_45_4, sizeof(float *)); + + float * h_var_45_5 = (float *)malloc(sizeof(float *)); + float * d_var_45_5; + cudaMalloc((void **)&d_var_45_5, sizeof(float *)); + + float * h_var_45_6 = (float *)malloc(sizeof(float *)); + float * d_var_45_6; + cudaMalloc((void **)&d_var_45_6, sizeof(float *)); + + float * h_var_45_7 = (float *)malloc(sizeof(float *)); + float * d_var_45_7; + cudaMalloc((void **)&d_var_45_7, sizeof(float *)); + + float * h_var_45_8 = (float *)malloc(sizeof(float *)); + float * d_var_45_8; + cudaMalloc((void **)&d_var_45_8, sizeof(float *)); + + float * h_var_45_9 = (float *)malloc(sizeof(float *)); + float * d_var_45_9; + cudaMalloc((void **)&d_var_45_9, sizeof(float *)); + + float * h_var_45_10 = (float *)malloc(sizeof(float *)); + float * d_var_45_10; + cudaMalloc((void **)&d_var_45_10, sizeof(float *)); + + float * h_var_45_11 = (float *)malloc(sizeof(float *)); + float * d_var_45_11; + cudaMalloc((void **)&d_var_45_11, sizeof(float *)); + + float * h_var_45_12 = (float *)malloc(sizeof(float *)); + float * d_var_45_12; + cudaMalloc((void **)&d_var_45_12, sizeof(float *)); + + float * h_var_45_13 = (float *)malloc(sizeof(float *)); + float * d_var_45_13; + cudaMalloc((void **)&d_var_45_13, sizeof(float *)); + + float * h_var_45_14 = (float *)malloc(sizeof(float *)); + float * d_var_45_14; + cudaMalloc((void **)&d_var_45_14, sizeof(float *)); + + float * h_var_45_15 = (float *)malloc(sizeof(float *)); + float * d_var_45_15; + cudaMalloc((void **)&d_var_45_15, sizeof(float *)); + + float * h_var_45_16 = (float *)malloc(sizeof(float *)); + float * d_var_45_16; + cudaMalloc((void **)&d_var_45_16, sizeof(float *)); + + float * h_var_45_17 = (float *)malloc(sizeof(float *)); + float * d_var_45_17; + cudaMalloc((void **)&d_var_45_17, sizeof(float *)); + + float * h_var_45_18 = (float *)malloc(sizeof(float *)); + float * d_var_45_18; + cudaMalloc((void **)&d_var_45_18, sizeof(float *)); + + float * h_var_45_19 = (float *)malloc(sizeof(float *)); + float * d_var_45_19; + cudaMalloc((void **)&d_var_45_19, sizeof(float *)); + + float * h_var_46_0 = (float *)malloc(sizeof(float *)); + float * d_var_46_0; + cudaMalloc((void **)&d_var_46_0, sizeof(float *)); + + float * h_var_46_1 = (float *)malloc(sizeof(float *)); + float * d_var_46_1; + cudaMalloc((void **)&d_var_46_1, sizeof(float *)); + + float * h_var_46_2 = (float *)malloc(sizeof(float *)); + float * d_var_46_2; + cudaMalloc((void **)&d_var_46_2, sizeof(float *)); + + float * h_var_46_3 = (float *)malloc(sizeof(float *)); + float * d_var_46_3; + cudaMalloc((void **)&d_var_46_3, sizeof(float *)); + + float * h_var_46_4 = (float *)malloc(sizeof(float *)); + float * d_var_46_4; + cudaMalloc((void **)&d_var_46_4, sizeof(float *)); + + float * h_var_46_5 = (float *)malloc(sizeof(float *)); + float * d_var_46_5; + cudaMalloc((void **)&d_var_46_5, sizeof(float *)); + + float * h_var_46_6 = (float *)malloc(sizeof(float *)); + float * d_var_46_6; + cudaMalloc((void **)&d_var_46_6, sizeof(float *)); + + float * h_var_46_7 = (float *)malloc(sizeof(float *)); + float * d_var_46_7; + cudaMalloc((void **)&d_var_46_7, sizeof(float *)); + + float * h_var_46_8 = (float *)malloc(sizeof(float *)); + float * d_var_46_8; + cudaMalloc((void **)&d_var_46_8, sizeof(float *)); + + float * h_var_46_9 = (float *)malloc(sizeof(float *)); + float * d_var_46_9; + cudaMalloc((void **)&d_var_46_9, sizeof(float *)); + + float * h_var_46_10 = (float *)malloc(sizeof(float *)); + float * d_var_46_10; + cudaMalloc((void **)&d_var_46_10, sizeof(float *)); + + float * h_var_46_11 = (float *)malloc(sizeof(float *)); + float * d_var_46_11; + cudaMalloc((void **)&d_var_46_11, sizeof(float *)); + + float * h_var_46_12 = (float *)malloc(sizeof(float *)); + float * d_var_46_12; + cudaMalloc((void **)&d_var_46_12, sizeof(float *)); + + float * h_var_46_13 = (float *)malloc(sizeof(float *)); + float * d_var_46_13; + cudaMalloc((void **)&d_var_46_13, sizeof(float *)); + + float * h_var_46_14 = (float *)malloc(sizeof(float *)); + float * d_var_46_14; + cudaMalloc((void **)&d_var_46_14, sizeof(float *)); + + float * h_var_46_15 = (float *)malloc(sizeof(float *)); + float * d_var_46_15; + cudaMalloc((void **)&d_var_46_15, sizeof(float *)); + + float * h_var_46_16 = (float *)malloc(sizeof(float *)); + float * d_var_46_16; + cudaMalloc((void **)&d_var_46_16, sizeof(float *)); + + float * h_var_46_17 = (float *)malloc(sizeof(float *)); + float * d_var_46_17; + cudaMalloc((void **)&d_var_46_17, sizeof(float *)); + + float * h_var_46_18 = (float *)malloc(sizeof(float *)); + float * d_var_46_18; + cudaMalloc((void **)&d_var_46_18, sizeof(float *)); + + float * h_var_46_19 = (float *)malloc(sizeof(float *)); + float * d_var_46_19; + cudaMalloc((void **)&d_var_46_19, sizeof(float *)); + + float * h_var_47_0 = (float *)malloc(sizeof(float *)); + float * d_var_47_0; + cudaMalloc((void **)&d_var_47_0, sizeof(float *)); + + float * h_var_47_1 = (float *)malloc(sizeof(float *)); + float * d_var_47_1; + cudaMalloc((void **)&d_var_47_1, sizeof(float *)); + + float * h_var_47_2 = (float *)malloc(sizeof(float *)); + float * d_var_47_2; + cudaMalloc((void **)&d_var_47_2, sizeof(float *)); + + float * h_var_47_3 = (float *)malloc(sizeof(float *)); + float * d_var_47_3; + cudaMalloc((void **)&d_var_47_3, sizeof(float *)); + + float * h_var_47_4 = (float *)malloc(sizeof(float *)); + float * d_var_47_4; + cudaMalloc((void **)&d_var_47_4, sizeof(float *)); + + float * h_var_47_5 = (float *)malloc(sizeof(float *)); + float * d_var_47_5; + cudaMalloc((void **)&d_var_47_5, sizeof(float *)); + + float * h_var_47_6 = (float *)malloc(sizeof(float *)); + float * d_var_47_6; + cudaMalloc((void **)&d_var_47_6, sizeof(float *)); + + float * h_var_47_7 = (float *)malloc(sizeof(float *)); + float * d_var_47_7; + cudaMalloc((void **)&d_var_47_7, sizeof(float *)); + + float * h_var_47_8 = (float *)malloc(sizeof(float *)); + float * d_var_47_8; + cudaMalloc((void **)&d_var_47_8, sizeof(float *)); + + float * h_var_47_9 = (float *)malloc(sizeof(float *)); + float * d_var_47_9; + cudaMalloc((void **)&d_var_47_9, sizeof(float *)); + + float * h_var_47_10 = (float *)malloc(sizeof(float *)); + float * d_var_47_10; + cudaMalloc((void **)&d_var_47_10, sizeof(float *)); + + float * h_var_47_11 = (float *)malloc(sizeof(float *)); + float * d_var_47_11; + cudaMalloc((void **)&d_var_47_11, sizeof(float *)); + + float * h_var_47_12 = (float *)malloc(sizeof(float *)); + float * d_var_47_12; + cudaMalloc((void **)&d_var_47_12, sizeof(float *)); + + float * h_var_47_13 = (float *)malloc(sizeof(float *)); + float * d_var_47_13; + cudaMalloc((void **)&d_var_47_13, sizeof(float *)); + + float * h_var_47_14 = (float *)malloc(sizeof(float *)); + float * d_var_47_14; + cudaMalloc((void **)&d_var_47_14, sizeof(float *)); + + float * h_var_47_15 = (float *)malloc(sizeof(float *)); + float * d_var_47_15; + cudaMalloc((void **)&d_var_47_15, sizeof(float *)); + + float * h_var_47_16 = (float *)malloc(sizeof(float *)); + float * d_var_47_16; + cudaMalloc((void **)&d_var_47_16, sizeof(float *)); + + float * h_var_47_17 = (float *)malloc(sizeof(float *)); + float * d_var_47_17; + cudaMalloc((void **)&d_var_47_17, sizeof(float *)); + + float * h_var_47_18 = (float *)malloc(sizeof(float *)); + float * d_var_47_18; + cudaMalloc((void **)&d_var_47_18, sizeof(float *)); + + float * h_var_47_19 = (float *)malloc(sizeof(float *)); + float * d_var_47_19; + cudaMalloc((void **)&d_var_47_19, sizeof(float *)); + + float * h_var_48_0 = (float *)malloc(sizeof(float *)); + float * d_var_48_0; + cudaMalloc((void **)&d_var_48_0, sizeof(float *)); + + float * h_var_48_1 = (float *)malloc(sizeof(float *)); + float * d_var_48_1; + cudaMalloc((void **)&d_var_48_1, sizeof(float *)); + + float * h_var_48_2 = (float *)malloc(sizeof(float *)); + float * d_var_48_2; + cudaMalloc((void **)&d_var_48_2, sizeof(float *)); + + float * h_var_48_3 = (float *)malloc(sizeof(float *)); + float * d_var_48_3; + cudaMalloc((void **)&d_var_48_3, sizeof(float *)); + + float * h_var_48_4 = (float *)malloc(sizeof(float *)); + float * d_var_48_4; + cudaMalloc((void **)&d_var_48_4, sizeof(float *)); + + float * h_var_48_5 = (float *)malloc(sizeof(float *)); + float * d_var_48_5; + cudaMalloc((void **)&d_var_48_5, sizeof(float *)); + + float * h_var_48_6 = (float *)malloc(sizeof(float *)); + float * d_var_48_6; + cudaMalloc((void **)&d_var_48_6, sizeof(float *)); + + float * h_var_48_7 = (float *)malloc(sizeof(float *)); + float * d_var_48_7; + cudaMalloc((void **)&d_var_48_7, sizeof(float *)); + + float * h_var_48_8 = (float *)malloc(sizeof(float *)); + float * d_var_48_8; + cudaMalloc((void **)&d_var_48_8, sizeof(float *)); + + float * h_var_48_9 = (float *)malloc(sizeof(float *)); + float * d_var_48_9; + cudaMalloc((void **)&d_var_48_9, sizeof(float *)); + + float * h_var_48_10 = (float *)malloc(sizeof(float *)); + float * d_var_48_10; + cudaMalloc((void **)&d_var_48_10, sizeof(float *)); + + float * h_var_48_11 = (float *)malloc(sizeof(float *)); + float * d_var_48_11; + cudaMalloc((void **)&d_var_48_11, sizeof(float *)); + + float * h_var_48_12 = (float *)malloc(sizeof(float *)); + float * d_var_48_12; + cudaMalloc((void **)&d_var_48_12, sizeof(float *)); + + float * h_var_48_13 = (float *)malloc(sizeof(float *)); + float * d_var_48_13; + cudaMalloc((void **)&d_var_48_13, sizeof(float *)); + + float * h_var_48_14 = (float *)malloc(sizeof(float *)); + float * d_var_48_14; + cudaMalloc((void **)&d_var_48_14, sizeof(float *)); + + float * h_var_48_15 = (float *)malloc(sizeof(float *)); + float * d_var_48_15; + cudaMalloc((void **)&d_var_48_15, sizeof(float *)); + + float * h_var_48_16 = (float *)malloc(sizeof(float *)); + float * d_var_48_16; + cudaMalloc((void **)&d_var_48_16, sizeof(float *)); + + float * h_var_48_17 = (float *)malloc(sizeof(float *)); + float * d_var_48_17; + cudaMalloc((void **)&d_var_48_17, sizeof(float *)); + + float * h_var_48_18 = (float *)malloc(sizeof(float *)); + float * d_var_48_18; + cudaMalloc((void **)&d_var_48_18, sizeof(float *)); + + float * h_var_48_19 = (float *)malloc(sizeof(float *)); + float * d_var_48_19; + cudaMalloc((void **)&d_var_48_19, sizeof(float *)); + + float * h_var_49_0 = (float *)malloc(sizeof(float *)); + float * d_var_49_0; + cudaMalloc((void **)&d_var_49_0, sizeof(float *)); + + float * h_var_49_1 = (float *)malloc(sizeof(float *)); + float * d_var_49_1; + cudaMalloc((void **)&d_var_49_1, sizeof(float *)); + + float * h_var_49_2 = (float *)malloc(sizeof(float *)); + float * d_var_49_2; + cudaMalloc((void **)&d_var_49_2, sizeof(float *)); + + float * h_var_49_3 = (float *)malloc(sizeof(float *)); + float * d_var_49_3; + cudaMalloc((void **)&d_var_49_3, sizeof(float *)); + + float * h_var_49_4 = (float *)malloc(sizeof(float *)); + float * d_var_49_4; + cudaMalloc((void **)&d_var_49_4, sizeof(float *)); + + float * h_var_49_5 = (float *)malloc(sizeof(float *)); + float * d_var_49_5; + cudaMalloc((void **)&d_var_49_5, sizeof(float *)); + + float * h_var_49_6 = (float *)malloc(sizeof(float *)); + float * d_var_49_6; + cudaMalloc((void **)&d_var_49_6, sizeof(float *)); + + float * h_var_49_7 = (float *)malloc(sizeof(float *)); + float * d_var_49_7; + cudaMalloc((void **)&d_var_49_7, sizeof(float *)); + + float * h_var_49_8 = (float *)malloc(sizeof(float *)); + float * d_var_49_8; + cudaMalloc((void **)&d_var_49_8, sizeof(float *)); + + float * h_var_49_9 = (float *)malloc(sizeof(float *)); + float * d_var_49_9; + cudaMalloc((void **)&d_var_49_9, sizeof(float *)); + + float * h_var_49_10 = (float *)malloc(sizeof(float *)); + float * d_var_49_10; + cudaMalloc((void **)&d_var_49_10, sizeof(float *)); + + float * h_var_49_11 = (float *)malloc(sizeof(float *)); + float * d_var_49_11; + cudaMalloc((void **)&d_var_49_11, sizeof(float *)); + + float * h_var_49_12 = (float *)malloc(sizeof(float *)); + float * d_var_49_12; + cudaMalloc((void **)&d_var_49_12, sizeof(float *)); + + float * h_var_49_13 = (float *)malloc(sizeof(float *)); + float * d_var_49_13; + cudaMalloc((void **)&d_var_49_13, sizeof(float *)); + + float * h_var_49_14 = (float *)malloc(sizeof(float *)); + float * d_var_49_14; + cudaMalloc((void **)&d_var_49_14, sizeof(float *)); + + float * h_var_49_15 = (float *)malloc(sizeof(float *)); + float * d_var_49_15; + cudaMalloc((void **)&d_var_49_15, sizeof(float *)); + + float * h_var_49_16 = (float *)malloc(sizeof(float *)); + float * d_var_49_16; + cudaMalloc((void **)&d_var_49_16, sizeof(float *)); + + float * h_var_49_17 = (float *)malloc(sizeof(float *)); + float * d_var_49_17; + cudaMalloc((void **)&d_var_49_17, sizeof(float *)); + + float * h_var_49_18 = (float *)malloc(sizeof(float *)); + float * d_var_49_18; + cudaMalloc((void **)&d_var_49_18, sizeof(float *)); + + float * h_var_49_19 = (float *)malloc(sizeof(float *)); + float * d_var_49_19; + cudaMalloc((void **)&d_var_49_19, sizeof(float *)); + + float * h_var_50_0 = (float *)malloc(sizeof(float *)); + float * d_var_50_0; + cudaMalloc((void **)&d_var_50_0, sizeof(float *)); + + float * h_var_50_1 = (float *)malloc(sizeof(float *)); + float * d_var_50_1; + cudaMalloc((void **)&d_var_50_1, sizeof(float *)); + + float * h_var_50_2 = (float *)malloc(sizeof(float *)); + float * d_var_50_2; + cudaMalloc((void **)&d_var_50_2, sizeof(float *)); + + float * h_var_50_3 = (float *)malloc(sizeof(float *)); + float * d_var_50_3; + cudaMalloc((void **)&d_var_50_3, sizeof(float *)); + + float * h_var_50_4 = (float *)malloc(sizeof(float *)); + float * d_var_50_4; + cudaMalloc((void **)&d_var_50_4, sizeof(float *)); + + float * h_var_50_5 = (float *)malloc(sizeof(float *)); + float * d_var_50_5; + cudaMalloc((void **)&d_var_50_5, sizeof(float *)); + + float * h_var_50_6 = (float *)malloc(sizeof(float *)); + float * d_var_50_6; + cudaMalloc((void **)&d_var_50_6, sizeof(float *)); + + float * h_var_50_7 = (float *)malloc(sizeof(float *)); + float * d_var_50_7; + cudaMalloc((void **)&d_var_50_7, sizeof(float *)); + + float * h_var_50_8 = (float *)malloc(sizeof(float *)); + float * d_var_50_8; + cudaMalloc((void **)&d_var_50_8, sizeof(float *)); + + float * h_var_50_9 = (float *)malloc(sizeof(float *)); + float * d_var_50_9; + cudaMalloc((void **)&d_var_50_9, sizeof(float *)); + + float * h_var_50_10 = (float *)malloc(sizeof(float *)); + float * d_var_50_10; + cudaMalloc((void **)&d_var_50_10, sizeof(float *)); + + float * h_var_50_11 = (float *)malloc(sizeof(float *)); + float * d_var_50_11; + cudaMalloc((void **)&d_var_50_11, sizeof(float *)); + + float * h_var_50_12 = (float *)malloc(sizeof(float *)); + float * d_var_50_12; + cudaMalloc((void **)&d_var_50_12, sizeof(float *)); + + float * h_var_50_13 = (float *)malloc(sizeof(float *)); + float * d_var_50_13; + cudaMalloc((void **)&d_var_50_13, sizeof(float *)); + + float * h_var_50_14 = (float *)malloc(sizeof(float *)); + float * d_var_50_14; + cudaMalloc((void **)&d_var_50_14, sizeof(float *)); + + float * h_var_50_15 = (float *)malloc(sizeof(float *)); + float * d_var_50_15; + cudaMalloc((void **)&d_var_50_15, sizeof(float *)); + + float * h_var_50_16 = (float *)malloc(sizeof(float *)); + float * d_var_50_16; + cudaMalloc((void **)&d_var_50_16, sizeof(float *)); + + float * h_var_50_17 = (float *)malloc(sizeof(float *)); + float * d_var_50_17; + cudaMalloc((void **)&d_var_50_17, sizeof(float *)); + + float * h_var_50_18 = (float *)malloc(sizeof(float *)); + float * d_var_50_18; + cudaMalloc((void **)&d_var_50_18, sizeof(float *)); + + float * h_var_50_19 = (float *)malloc(sizeof(float *)); + float * d_var_50_19; + cudaMalloc((void **)&d_var_50_19, sizeof(float *)); + + float * h_var_51_0 = (float *)malloc(sizeof(float *)); + float * d_var_51_0; + cudaMalloc((void **)&d_var_51_0, sizeof(float *)); + + float * h_var_51_1 = (float *)malloc(sizeof(float *)); + float * d_var_51_1; + cudaMalloc((void **)&d_var_51_1, sizeof(float *)); + + float * h_var_51_2 = (float *)malloc(sizeof(float *)); + float * d_var_51_2; + cudaMalloc((void **)&d_var_51_2, sizeof(float *)); + + float * h_var_51_3 = (float *)malloc(sizeof(float *)); + float * d_var_51_3; + cudaMalloc((void **)&d_var_51_3, sizeof(float *)); + + float * h_var_51_4 = (float *)malloc(sizeof(float *)); + float * d_var_51_4; + cudaMalloc((void **)&d_var_51_4, sizeof(float *)); + + float * h_var_51_5 = (float *)malloc(sizeof(float *)); + float * d_var_51_5; + cudaMalloc((void **)&d_var_51_5, sizeof(float *)); + + float * h_var_51_6 = (float *)malloc(sizeof(float *)); + float * d_var_51_6; + cudaMalloc((void **)&d_var_51_6, sizeof(float *)); + + float * h_var_51_7 = (float *)malloc(sizeof(float *)); + float * d_var_51_7; + cudaMalloc((void **)&d_var_51_7, sizeof(float *)); + + float * h_var_51_8 = (float *)malloc(sizeof(float *)); + float * d_var_51_8; + cudaMalloc((void **)&d_var_51_8, sizeof(float *)); + + float * h_var_51_9 = (float *)malloc(sizeof(float *)); + float * d_var_51_9; + cudaMalloc((void **)&d_var_51_9, sizeof(float *)); + + float * h_var_51_10 = (float *)malloc(sizeof(float *)); + float * d_var_51_10; + cudaMalloc((void **)&d_var_51_10, sizeof(float *)); + + float * h_var_51_11 = (float *)malloc(sizeof(float *)); + float * d_var_51_11; + cudaMalloc((void **)&d_var_51_11, sizeof(float *)); + + float * h_var_51_12 = (float *)malloc(sizeof(float *)); + float * d_var_51_12; + cudaMalloc((void **)&d_var_51_12, sizeof(float *)); + + float * h_var_51_13 = (float *)malloc(sizeof(float *)); + float * d_var_51_13; + cudaMalloc((void **)&d_var_51_13, sizeof(float *)); + + float * h_var_51_14 = (float *)malloc(sizeof(float *)); + float * d_var_51_14; + cudaMalloc((void **)&d_var_51_14, sizeof(float *)); + + float * h_var_51_15 = (float *)malloc(sizeof(float *)); + float * d_var_51_15; + cudaMalloc((void **)&d_var_51_15, sizeof(float *)); + + float * h_var_51_16 = (float *)malloc(sizeof(float *)); + float * d_var_51_16; + cudaMalloc((void **)&d_var_51_16, sizeof(float *)); + + float * h_var_51_17 = (float *)malloc(sizeof(float *)); + float * d_var_51_17; + cudaMalloc((void **)&d_var_51_17, sizeof(float *)); + + float * h_var_51_18 = (float *)malloc(sizeof(float *)); + float * d_var_51_18; + cudaMalloc((void **)&d_var_51_18, sizeof(float *)); + + float * h_var_51_19 = (float *)malloc(sizeof(float *)); + float * d_var_51_19; + cudaMalloc((void **)&d_var_51_19, sizeof(float *)); + + float * h_var_52_0 = (float *)malloc(sizeof(float *)); + float * d_var_52_0; + cudaMalloc((void **)&d_var_52_0, sizeof(float *)); + + float * h_var_52_1 = (float *)malloc(sizeof(float *)); + float * d_var_52_1; + cudaMalloc((void **)&d_var_52_1, sizeof(float *)); + + float * h_var_52_2 = (float *)malloc(sizeof(float *)); + float * d_var_52_2; + cudaMalloc((void **)&d_var_52_2, sizeof(float *)); + + float * h_var_52_3 = (float *)malloc(sizeof(float *)); + float * d_var_52_3; + cudaMalloc((void **)&d_var_52_3, sizeof(float *)); + + float * h_var_52_4 = (float *)malloc(sizeof(float *)); + float * d_var_52_4; + cudaMalloc((void **)&d_var_52_4, sizeof(float *)); + + float * h_var_52_5 = (float *)malloc(sizeof(float *)); + float * d_var_52_5; + cudaMalloc((void **)&d_var_52_5, sizeof(float *)); + + float * h_var_52_6 = (float *)malloc(sizeof(float *)); + float * d_var_52_6; + cudaMalloc((void **)&d_var_52_6, sizeof(float *)); + + float * h_var_52_7 = (float *)malloc(sizeof(float *)); + float * d_var_52_7; + cudaMalloc((void **)&d_var_52_7, sizeof(float *)); + + float * h_var_52_8 = (float *)malloc(sizeof(float *)); + float * d_var_52_8; + cudaMalloc((void **)&d_var_52_8, sizeof(float *)); + + float * h_var_52_9 = (float *)malloc(sizeof(float *)); + float * d_var_52_9; + cudaMalloc((void **)&d_var_52_9, sizeof(float *)); + + float * h_var_52_10 = (float *)malloc(sizeof(float *)); + float * d_var_52_10; + cudaMalloc((void **)&d_var_52_10, sizeof(float *)); + + float * h_var_52_11 = (float *)malloc(sizeof(float *)); + float * d_var_52_11; + cudaMalloc((void **)&d_var_52_11, sizeof(float *)); + + float * h_var_52_12 = (float *)malloc(sizeof(float *)); + float * d_var_52_12; + cudaMalloc((void **)&d_var_52_12, sizeof(float *)); + + float * h_var_52_13 = (float *)malloc(sizeof(float *)); + float * d_var_52_13; + cudaMalloc((void **)&d_var_52_13, sizeof(float *)); + + float * h_var_52_14 = (float *)malloc(sizeof(float *)); + float * d_var_52_14; + cudaMalloc((void **)&d_var_52_14, sizeof(float *)); + + float * h_var_52_15 = (float *)malloc(sizeof(float *)); + float * d_var_52_15; + cudaMalloc((void **)&d_var_52_15, sizeof(float *)); + + float * h_var_52_16 = (float *)malloc(sizeof(float *)); + float * d_var_52_16; + cudaMalloc((void **)&d_var_52_16, sizeof(float *)); + + float * h_var_52_17 = (float *)malloc(sizeof(float *)); + float * d_var_52_17; + cudaMalloc((void **)&d_var_52_17, sizeof(float *)); + + float * h_var_52_18 = (float *)malloc(sizeof(float *)); + float * d_var_52_18; + cudaMalloc((void **)&d_var_52_18, sizeof(float *)); + + float * h_var_52_19 = (float *)malloc(sizeof(float *)); + float * d_var_52_19; + cudaMalloc((void **)&d_var_52_19, sizeof(float *)); + + float * h_var_53_0 = (float *)malloc(sizeof(float *)); + float * d_var_53_0; + cudaMalloc((void **)&d_var_53_0, sizeof(float *)); + + float * h_var_53_1 = (float *)malloc(sizeof(float *)); + float * d_var_53_1; + cudaMalloc((void **)&d_var_53_1, sizeof(float *)); + + float * h_var_53_2 = (float *)malloc(sizeof(float *)); + float * d_var_53_2; + cudaMalloc((void **)&d_var_53_2, sizeof(float *)); + + float * h_var_53_3 = (float *)malloc(sizeof(float *)); + float * d_var_53_3; + cudaMalloc((void **)&d_var_53_3, sizeof(float *)); + + float * h_var_53_4 = (float *)malloc(sizeof(float *)); + float * d_var_53_4; + cudaMalloc((void **)&d_var_53_4, sizeof(float *)); + + float * h_var_53_5 = (float *)malloc(sizeof(float *)); + float * d_var_53_5; + cudaMalloc((void **)&d_var_53_5, sizeof(float *)); + + float * h_var_53_6 = (float *)malloc(sizeof(float *)); + float * d_var_53_6; + cudaMalloc((void **)&d_var_53_6, sizeof(float *)); + + float * h_var_53_7 = (float *)malloc(sizeof(float *)); + float * d_var_53_7; + cudaMalloc((void **)&d_var_53_7, sizeof(float *)); + + float * h_var_53_8 = (float *)malloc(sizeof(float *)); + float * d_var_53_8; + cudaMalloc((void **)&d_var_53_8, sizeof(float *)); + + float * h_var_53_9 = (float *)malloc(sizeof(float *)); + float * d_var_53_9; + cudaMalloc((void **)&d_var_53_9, sizeof(float *)); + + float * h_var_53_10 = (float *)malloc(sizeof(float *)); + float * d_var_53_10; + cudaMalloc((void **)&d_var_53_10, sizeof(float *)); + + float * h_var_53_11 = (float *)malloc(sizeof(float *)); + float * d_var_53_11; + cudaMalloc((void **)&d_var_53_11, sizeof(float *)); + + float * h_var_53_12 = (float *)malloc(sizeof(float *)); + float * d_var_53_12; + cudaMalloc((void **)&d_var_53_12, sizeof(float *)); + + float * h_var_53_13 = (float *)malloc(sizeof(float *)); + float * d_var_53_13; + cudaMalloc((void **)&d_var_53_13, sizeof(float *)); + + float * h_var_53_14 = (float *)malloc(sizeof(float *)); + float * d_var_53_14; + cudaMalloc((void **)&d_var_53_14, sizeof(float *)); + + float * h_var_53_15 = (float *)malloc(sizeof(float *)); + float * d_var_53_15; + cudaMalloc((void **)&d_var_53_15, sizeof(float *)); + + float * h_var_53_16 = (float *)malloc(sizeof(float *)); + float * d_var_53_16; + cudaMalloc((void **)&d_var_53_16, sizeof(float *)); + + float * h_var_53_17 = (float *)malloc(sizeof(float *)); + float * d_var_53_17; + cudaMalloc((void **)&d_var_53_17, sizeof(float *)); + + float * h_var_53_18 = (float *)malloc(sizeof(float *)); + float * d_var_53_18; + cudaMalloc((void **)&d_var_53_18, sizeof(float *)); + + float * h_var_53_19 = (float *)malloc(sizeof(float *)); + float * d_var_53_19; + cudaMalloc((void **)&d_var_53_19, sizeof(float *)); + + float * h_var_54_0 = (float *)malloc(sizeof(float *)); + float * d_var_54_0; + cudaMalloc((void **)&d_var_54_0, sizeof(float *)); + + float * h_var_54_1 = (float *)malloc(sizeof(float *)); + float * d_var_54_1; + cudaMalloc((void **)&d_var_54_1, sizeof(float *)); + + float * h_var_54_2 = (float *)malloc(sizeof(float *)); + float * d_var_54_2; + cudaMalloc((void **)&d_var_54_2, sizeof(float *)); + + float * h_var_54_3 = (float *)malloc(sizeof(float *)); + float * d_var_54_3; + cudaMalloc((void **)&d_var_54_3, sizeof(float *)); + + float * h_var_54_4 = (float *)malloc(sizeof(float *)); + float * d_var_54_4; + cudaMalloc((void **)&d_var_54_4, sizeof(float *)); + + float * h_var_54_5 = (float *)malloc(sizeof(float *)); + float * d_var_54_5; + cudaMalloc((void **)&d_var_54_5, sizeof(float *)); + + float * h_var_54_6 = (float *)malloc(sizeof(float *)); + float * d_var_54_6; + cudaMalloc((void **)&d_var_54_6, sizeof(float *)); + + float * h_var_54_7 = (float *)malloc(sizeof(float *)); + float * d_var_54_7; + cudaMalloc((void **)&d_var_54_7, sizeof(float *)); + + float * h_var_54_8 = (float *)malloc(sizeof(float *)); + float * d_var_54_8; + cudaMalloc((void **)&d_var_54_8, sizeof(float *)); + + float * h_var_54_9 = (float *)malloc(sizeof(float *)); + float * d_var_54_9; + cudaMalloc((void **)&d_var_54_9, sizeof(float *)); + + float * h_var_54_10 = (float *)malloc(sizeof(float *)); + float * d_var_54_10; + cudaMalloc((void **)&d_var_54_10, sizeof(float *)); + + float * h_var_54_11 = (float *)malloc(sizeof(float *)); + float * d_var_54_11; + cudaMalloc((void **)&d_var_54_11, sizeof(float *)); + + float * h_var_54_12 = (float *)malloc(sizeof(float *)); + float * d_var_54_12; + cudaMalloc((void **)&d_var_54_12, sizeof(float *)); + + float * h_var_54_13 = (float *)malloc(sizeof(float *)); + float * d_var_54_13; + cudaMalloc((void **)&d_var_54_13, sizeof(float *)); + + float * h_var_54_14 = (float *)malloc(sizeof(float *)); + float * d_var_54_14; + cudaMalloc((void **)&d_var_54_14, sizeof(float *)); + + float * h_var_54_15 = (float *)malloc(sizeof(float *)); + float * d_var_54_15; + cudaMalloc((void **)&d_var_54_15, sizeof(float *)); + + float * h_var_54_16 = (float *)malloc(sizeof(float *)); + float * d_var_54_16; + cudaMalloc((void **)&d_var_54_16, sizeof(float *)); + + float * h_var_54_17 = (float *)malloc(sizeof(float *)); + float * d_var_54_17; + cudaMalloc((void **)&d_var_54_17, sizeof(float *)); + + float * h_var_54_18 = (float *)malloc(sizeof(float *)); + float * d_var_54_18; + cudaMalloc((void **)&d_var_54_18, sizeof(float *)); + + float * h_var_54_19 = (float *)malloc(sizeof(float *)); + float * d_var_54_19; + cudaMalloc((void **)&d_var_54_19, sizeof(float *)); + + float * h_var_55_0 = (float *)malloc(sizeof(float *)); + float * d_var_55_0; + cudaMalloc((void **)&d_var_55_0, sizeof(float *)); + + float * h_var_55_1 = (float *)malloc(sizeof(float *)); + float * d_var_55_1; + cudaMalloc((void **)&d_var_55_1, sizeof(float *)); + + float * h_var_55_2 = (float *)malloc(sizeof(float *)); + float * d_var_55_2; + cudaMalloc((void **)&d_var_55_2, sizeof(float *)); + + float * h_var_55_3 = (float *)malloc(sizeof(float *)); + float * d_var_55_3; + cudaMalloc((void **)&d_var_55_3, sizeof(float *)); + + float * h_var_55_4 = (float *)malloc(sizeof(float *)); + float * d_var_55_4; + cudaMalloc((void **)&d_var_55_4, sizeof(float *)); + + float * h_var_55_5 = (float *)malloc(sizeof(float *)); + float * d_var_55_5; + cudaMalloc((void **)&d_var_55_5, sizeof(float *)); + + float * h_var_55_6 = (float *)malloc(sizeof(float *)); + float * d_var_55_6; + cudaMalloc((void **)&d_var_55_6, sizeof(float *)); + + float * h_var_55_7 = (float *)malloc(sizeof(float *)); + float * d_var_55_7; + cudaMalloc((void **)&d_var_55_7, sizeof(float *)); + + float * h_var_55_8 = (float *)malloc(sizeof(float *)); + float * d_var_55_8; + cudaMalloc((void **)&d_var_55_8, sizeof(float *)); + + float * h_var_55_9 = (float *)malloc(sizeof(float *)); + float * d_var_55_9; + cudaMalloc((void **)&d_var_55_9, sizeof(float *)); + + float * h_var_55_10 = (float *)malloc(sizeof(float *)); + float * d_var_55_10; + cudaMalloc((void **)&d_var_55_10, sizeof(float *)); + + float * h_var_55_11 = (float *)malloc(sizeof(float *)); + float * d_var_55_11; + cudaMalloc((void **)&d_var_55_11, sizeof(float *)); + + float * h_var_55_12 = (float *)malloc(sizeof(float *)); + float * d_var_55_12; + cudaMalloc((void **)&d_var_55_12, sizeof(float *)); + + float * h_var_55_13 = (float *)malloc(sizeof(float *)); + float * d_var_55_13; + cudaMalloc((void **)&d_var_55_13, sizeof(float *)); + + float * h_var_55_14 = (float *)malloc(sizeof(float *)); + float * d_var_55_14; + cudaMalloc((void **)&d_var_55_14, sizeof(float *)); + + float * h_var_55_15 = (float *)malloc(sizeof(float *)); + float * d_var_55_15; + cudaMalloc((void **)&d_var_55_15, sizeof(float *)); + + float * h_var_55_16 = (float *)malloc(sizeof(float *)); + float * d_var_55_16; + cudaMalloc((void **)&d_var_55_16, sizeof(float *)); + + float * h_var_55_17 = (float *)malloc(sizeof(float *)); + float * d_var_55_17; + cudaMalloc((void **)&d_var_55_17, sizeof(float *)); + + float * h_var_55_18 = (float *)malloc(sizeof(float *)); + float * d_var_55_18; + cudaMalloc((void **)&d_var_55_18, sizeof(float *)); + + float * h_var_55_19 = (float *)malloc(sizeof(float *)); + float * d_var_55_19; + cudaMalloc((void **)&d_var_55_19, sizeof(float *)); + + float * h_var_56_0 = (float *)malloc(sizeof(float *)); + float * d_var_56_0; + cudaMalloc((void **)&d_var_56_0, sizeof(float *)); + + float * h_var_56_1 = (float *)malloc(sizeof(float *)); + float * d_var_56_1; + cudaMalloc((void **)&d_var_56_1, sizeof(float *)); + + float * h_var_56_2 = (float *)malloc(sizeof(float *)); + float * d_var_56_2; + cudaMalloc((void **)&d_var_56_2, sizeof(float *)); + + float * h_var_56_3 = (float *)malloc(sizeof(float *)); + float * d_var_56_3; + cudaMalloc((void **)&d_var_56_3, sizeof(float *)); + + float * h_var_56_4 = (float *)malloc(sizeof(float *)); + float * d_var_56_4; + cudaMalloc((void **)&d_var_56_4, sizeof(float *)); + + float * h_var_56_5 = (float *)malloc(sizeof(float *)); + float * d_var_56_5; + cudaMalloc((void **)&d_var_56_5, sizeof(float *)); + + float * h_var_56_6 = (float *)malloc(sizeof(float *)); + float * d_var_56_6; + cudaMalloc((void **)&d_var_56_6, sizeof(float *)); + + float * h_var_56_7 = (float *)malloc(sizeof(float *)); + float * d_var_56_7; + cudaMalloc((void **)&d_var_56_7, sizeof(float *)); + + float * h_var_56_8 = (float *)malloc(sizeof(float *)); + float * d_var_56_8; + cudaMalloc((void **)&d_var_56_8, sizeof(float *)); + + float * h_var_56_9 = (float *)malloc(sizeof(float *)); + float * d_var_56_9; + cudaMalloc((void **)&d_var_56_9, sizeof(float *)); + + float * h_var_56_10 = (float *)malloc(sizeof(float *)); + float * d_var_56_10; + cudaMalloc((void **)&d_var_56_10, sizeof(float *)); + + float * h_var_56_11 = (float *)malloc(sizeof(float *)); + float * d_var_56_11; + cudaMalloc((void **)&d_var_56_11, sizeof(float *)); + + float * h_var_56_12 = (float *)malloc(sizeof(float *)); + float * d_var_56_12; + cudaMalloc((void **)&d_var_56_12, sizeof(float *)); + + float * h_var_56_13 = (float *)malloc(sizeof(float *)); + float * d_var_56_13; + cudaMalloc((void **)&d_var_56_13, sizeof(float *)); + + float * h_var_56_14 = (float *)malloc(sizeof(float *)); + float * d_var_56_14; + cudaMalloc((void **)&d_var_56_14, sizeof(float *)); + + float * h_var_56_15 = (float *)malloc(sizeof(float *)); + float * d_var_56_15; + cudaMalloc((void **)&d_var_56_15, sizeof(float *)); + + float * h_var_56_16 = (float *)malloc(sizeof(float *)); + float * d_var_56_16; + cudaMalloc((void **)&d_var_56_16, sizeof(float *)); + + float * h_var_56_17 = (float *)malloc(sizeof(float *)); + float * d_var_56_17; + cudaMalloc((void **)&d_var_56_17, sizeof(float *)); + + float * h_var_56_18 = (float *)malloc(sizeof(float *)); + float * d_var_56_18; + cudaMalloc((void **)&d_var_56_18, sizeof(float *)); + + float * h_var_56_19 = (float *)malloc(sizeof(float *)); + float * d_var_56_19; + cudaMalloc((void **)&d_var_56_19, sizeof(float *)); + + float * h_var_57_0 = (float *)malloc(sizeof(float *)); + float * d_var_57_0; + cudaMalloc((void **)&d_var_57_0, sizeof(float *)); + + float * h_var_57_1 = (float *)malloc(sizeof(float *)); + float * d_var_57_1; + cudaMalloc((void **)&d_var_57_1, sizeof(float *)); + + float * h_var_57_2 = (float *)malloc(sizeof(float *)); + float * d_var_57_2; + cudaMalloc((void **)&d_var_57_2, sizeof(float *)); + + float * h_var_57_3 = (float *)malloc(sizeof(float *)); + float * d_var_57_3; + cudaMalloc((void **)&d_var_57_3, sizeof(float *)); + + float * h_var_57_4 = (float *)malloc(sizeof(float *)); + float * d_var_57_4; + cudaMalloc((void **)&d_var_57_4, sizeof(float *)); + + float * h_var_57_5 = (float *)malloc(sizeof(float *)); + float * d_var_57_5; + cudaMalloc((void **)&d_var_57_5, sizeof(float *)); + + float * h_var_57_6 = (float *)malloc(sizeof(float *)); + float * d_var_57_6; + cudaMalloc((void **)&d_var_57_6, sizeof(float *)); + + float * h_var_57_7 = (float *)malloc(sizeof(float *)); + float * d_var_57_7; + cudaMalloc((void **)&d_var_57_7, sizeof(float *)); + + float * h_var_57_8 = (float *)malloc(sizeof(float *)); + float * d_var_57_8; + cudaMalloc((void **)&d_var_57_8, sizeof(float *)); + + float * h_var_57_9 = (float *)malloc(sizeof(float *)); + float * d_var_57_9; + cudaMalloc((void **)&d_var_57_9, sizeof(float *)); + + float * h_var_57_10 = (float *)malloc(sizeof(float *)); + float * d_var_57_10; + cudaMalloc((void **)&d_var_57_10, sizeof(float *)); + + float * h_var_57_11 = (float *)malloc(sizeof(float *)); + float * d_var_57_11; + cudaMalloc((void **)&d_var_57_11, sizeof(float *)); + + float * h_var_57_12 = (float *)malloc(sizeof(float *)); + float * d_var_57_12; + cudaMalloc((void **)&d_var_57_12, sizeof(float *)); + + float * h_var_57_13 = (float *)malloc(sizeof(float *)); + float * d_var_57_13; + cudaMalloc((void **)&d_var_57_13, sizeof(float *)); + + float * h_var_57_14 = (float *)malloc(sizeof(float *)); + float * d_var_57_14; + cudaMalloc((void **)&d_var_57_14, sizeof(float *)); + + float * h_var_57_15 = (float *)malloc(sizeof(float *)); + float * d_var_57_15; + cudaMalloc((void **)&d_var_57_15, sizeof(float *)); + + float * h_var_57_16 = (float *)malloc(sizeof(float *)); + float * d_var_57_16; + cudaMalloc((void **)&d_var_57_16, sizeof(float *)); + + float * h_var_57_17 = (float *)malloc(sizeof(float *)); + float * d_var_57_17; + cudaMalloc((void **)&d_var_57_17, sizeof(float *)); + + float * h_var_57_18 = (float *)malloc(sizeof(float *)); + float * d_var_57_18; + cudaMalloc((void **)&d_var_57_18, sizeof(float *)); + + float * h_var_57_19 = (float *)malloc(sizeof(float *)); + float * d_var_57_19; + cudaMalloc((void **)&d_var_57_19, sizeof(float *)); + + float * h_var_58_0 = (float *)malloc(sizeof(float *)); + float * d_var_58_0; + cudaMalloc((void **)&d_var_58_0, sizeof(float *)); + + float * h_var_58_1 = (float *)malloc(sizeof(float *)); + float * d_var_58_1; + cudaMalloc((void **)&d_var_58_1, sizeof(float *)); + + float * h_var_58_2 = (float *)malloc(sizeof(float *)); + float * d_var_58_2; + cudaMalloc((void **)&d_var_58_2, sizeof(float *)); + + float * h_var_58_3 = (float *)malloc(sizeof(float *)); + float * d_var_58_3; + cudaMalloc((void **)&d_var_58_3, sizeof(float *)); + + float * h_var_58_4 = (float *)malloc(sizeof(float *)); + float * d_var_58_4; + cudaMalloc((void **)&d_var_58_4, sizeof(float *)); + + float * h_var_58_5 = (float *)malloc(sizeof(float *)); + float * d_var_58_5; + cudaMalloc((void **)&d_var_58_5, sizeof(float *)); + + float * h_var_58_6 = (float *)malloc(sizeof(float *)); + float * d_var_58_6; + cudaMalloc((void **)&d_var_58_6, sizeof(float *)); + + float * h_var_58_7 = (float *)malloc(sizeof(float *)); + float * d_var_58_7; + cudaMalloc((void **)&d_var_58_7, sizeof(float *)); + + float * h_var_58_8 = (float *)malloc(sizeof(float *)); + float * d_var_58_8; + cudaMalloc((void **)&d_var_58_8, sizeof(float *)); + + float * h_var_58_9 = (float *)malloc(sizeof(float *)); + float * d_var_58_9; + cudaMalloc((void **)&d_var_58_9, sizeof(float *)); + + float * h_var_58_10 = (float *)malloc(sizeof(float *)); + float * d_var_58_10; + cudaMalloc((void **)&d_var_58_10, sizeof(float *)); + + float * h_var_58_11 = (float *)malloc(sizeof(float *)); + float * d_var_58_11; + cudaMalloc((void **)&d_var_58_11, sizeof(float *)); + + float * h_var_58_12 = (float *)malloc(sizeof(float *)); + float * d_var_58_12; + cudaMalloc((void **)&d_var_58_12, sizeof(float *)); + + float * h_var_58_13 = (float *)malloc(sizeof(float *)); + float * d_var_58_13; + cudaMalloc((void **)&d_var_58_13, sizeof(float *)); + + float * h_var_58_14 = (float *)malloc(sizeof(float *)); + float * d_var_58_14; + cudaMalloc((void **)&d_var_58_14, sizeof(float *)); + + float * h_var_58_15 = (float *)malloc(sizeof(float *)); + float * d_var_58_15; + cudaMalloc((void **)&d_var_58_15, sizeof(float *)); + + float * h_var_58_16 = (float *)malloc(sizeof(float *)); + float * d_var_58_16; + cudaMalloc((void **)&d_var_58_16, sizeof(float *)); + + float * h_var_58_17 = (float *)malloc(sizeof(float *)); + float * d_var_58_17; + cudaMalloc((void **)&d_var_58_17, sizeof(float *)); + + float * h_var_58_18 = (float *)malloc(sizeof(float *)); + float * d_var_58_18; + cudaMalloc((void **)&d_var_58_18, sizeof(float *)); + + float * h_var_58_19 = (float *)malloc(sizeof(float *)); + float * d_var_58_19; + cudaMalloc((void **)&d_var_58_19, sizeof(float *)); + + float * h_var_59_0 = (float *)malloc(sizeof(float *)); + float * d_var_59_0; + cudaMalloc((void **)&d_var_59_0, sizeof(float *)); + + float * h_var_59_1 = (float *)malloc(sizeof(float *)); + float * d_var_59_1; + cudaMalloc((void **)&d_var_59_1, sizeof(float *)); + + float * h_var_59_2 = (float *)malloc(sizeof(float *)); + float * d_var_59_2; + cudaMalloc((void **)&d_var_59_2, sizeof(float *)); + + float * h_var_59_3 = (float *)malloc(sizeof(float *)); + float * d_var_59_3; + cudaMalloc((void **)&d_var_59_3, sizeof(float *)); + + float * h_var_59_4 = (float *)malloc(sizeof(float *)); + float * d_var_59_4; + cudaMalloc((void **)&d_var_59_4, sizeof(float *)); + + float * h_var_59_5 = (float *)malloc(sizeof(float *)); + float * d_var_59_5; + cudaMalloc((void **)&d_var_59_5, sizeof(float *)); + + float * h_var_59_6 = (float *)malloc(sizeof(float *)); + float * d_var_59_6; + cudaMalloc((void **)&d_var_59_6, sizeof(float *)); + + float * h_var_59_7 = (float *)malloc(sizeof(float *)); + float * d_var_59_7; + cudaMalloc((void **)&d_var_59_7, sizeof(float *)); + + float * h_var_59_8 = (float *)malloc(sizeof(float *)); + float * d_var_59_8; + cudaMalloc((void **)&d_var_59_8, sizeof(float *)); + + float * h_var_59_9 = (float *)malloc(sizeof(float *)); + float * d_var_59_9; + cudaMalloc((void **)&d_var_59_9, sizeof(float *)); + + float * h_var_59_10 = (float *)malloc(sizeof(float *)); + float * d_var_59_10; + cudaMalloc((void **)&d_var_59_10, sizeof(float *)); + + float * h_var_59_11 = (float *)malloc(sizeof(float *)); + float * d_var_59_11; + cudaMalloc((void **)&d_var_59_11, sizeof(float *)); + + float * h_var_59_12 = (float *)malloc(sizeof(float *)); + float * d_var_59_12; + cudaMalloc((void **)&d_var_59_12, sizeof(float *)); + + float * h_var_59_13 = (float *)malloc(sizeof(float *)); + float * d_var_59_13; + cudaMalloc((void **)&d_var_59_13, sizeof(float *)); + + float * h_var_59_14 = (float *)malloc(sizeof(float *)); + float * d_var_59_14; + cudaMalloc((void **)&d_var_59_14, sizeof(float *)); + + float * h_var_59_15 = (float *)malloc(sizeof(float *)); + float * d_var_59_15; + cudaMalloc((void **)&d_var_59_15, sizeof(float *)); + + float * h_var_59_16 = (float *)malloc(sizeof(float *)); + float * d_var_59_16; + cudaMalloc((void **)&d_var_59_16, sizeof(float *)); + + float * h_var_59_17 = (float *)malloc(sizeof(float *)); + float * d_var_59_17; + cudaMalloc((void **)&d_var_59_17, sizeof(float *)); + + float * h_var_59_18 = (float *)malloc(sizeof(float *)); + float * d_var_59_18; + cudaMalloc((void **)&d_var_59_18, sizeof(float *)); + + float * h_var_59_19 = (float *)malloc(sizeof(float *)); + float * d_var_59_19; + cudaMalloc((void **)&d_var_59_19, sizeof(float *)); + + float * h_var_60_0 = (float *)malloc(sizeof(float *)); + float * d_var_60_0; + cudaMalloc((void **)&d_var_60_0, sizeof(float *)); + + float * h_var_60_1 = (float *)malloc(sizeof(float *)); + float * d_var_60_1; + cudaMalloc((void **)&d_var_60_1, sizeof(float *)); + + float * h_var_60_2 = (float *)malloc(sizeof(float *)); + float * d_var_60_2; + cudaMalloc((void **)&d_var_60_2, sizeof(float *)); + + float * h_var_60_3 = (float *)malloc(sizeof(float *)); + float * d_var_60_3; + cudaMalloc((void **)&d_var_60_3, sizeof(float *)); + + float * h_var_60_4 = (float *)malloc(sizeof(float *)); + float * d_var_60_4; + cudaMalloc((void **)&d_var_60_4, sizeof(float *)); + + float * h_var_60_5 = (float *)malloc(sizeof(float *)); + float * d_var_60_5; + cudaMalloc((void **)&d_var_60_5, sizeof(float *)); + + float * h_var_60_6 = (float *)malloc(sizeof(float *)); + float * d_var_60_6; + cudaMalloc((void **)&d_var_60_6, sizeof(float *)); + + float * h_var_60_7 = (float *)malloc(sizeof(float *)); + float * d_var_60_7; + cudaMalloc((void **)&d_var_60_7, sizeof(float *)); + + float * h_var_60_8 = (float *)malloc(sizeof(float *)); + float * d_var_60_8; + cudaMalloc((void **)&d_var_60_8, sizeof(float *)); + + float * h_var_60_9 = (float *)malloc(sizeof(float *)); + float * d_var_60_9; + cudaMalloc((void **)&d_var_60_9, sizeof(float *)); + + float * h_var_60_10 = (float *)malloc(sizeof(float *)); + float * d_var_60_10; + cudaMalloc((void **)&d_var_60_10, sizeof(float *)); + + float * h_var_60_11 = (float *)malloc(sizeof(float *)); + float * d_var_60_11; + cudaMalloc((void **)&d_var_60_11, sizeof(float *)); + + float * h_var_60_12 = (float *)malloc(sizeof(float *)); + float * d_var_60_12; + cudaMalloc((void **)&d_var_60_12, sizeof(float *)); + + float * h_var_60_13 = (float *)malloc(sizeof(float *)); + float * d_var_60_13; + cudaMalloc((void **)&d_var_60_13, sizeof(float *)); + + float * h_var_60_14 = (float *)malloc(sizeof(float *)); + float * d_var_60_14; + cudaMalloc((void **)&d_var_60_14, sizeof(float *)); + + float * h_var_60_15 = (float *)malloc(sizeof(float *)); + float * d_var_60_15; + cudaMalloc((void **)&d_var_60_15, sizeof(float *)); + + float * h_var_60_16 = (float *)malloc(sizeof(float *)); + float * d_var_60_16; + cudaMalloc((void **)&d_var_60_16, sizeof(float *)); + + float * h_var_60_17 = (float *)malloc(sizeof(float *)); + float * d_var_60_17; + cudaMalloc((void **)&d_var_60_17, sizeof(float *)); + + float * h_var_60_18 = (float *)malloc(sizeof(float *)); + float * d_var_60_18; + cudaMalloc((void **)&d_var_60_18, sizeof(float *)); + + float * h_var_60_19 = (float *)malloc(sizeof(float *)); + float * d_var_60_19; + cudaMalloc((void **)&d_var_60_19, sizeof(float *)); + + float * h_var_61_0 = (float *)malloc(sizeof(float *)); + float * d_var_61_0; + cudaMalloc((void **)&d_var_61_0, sizeof(float *)); + + float * h_var_61_1 = (float *)malloc(sizeof(float *)); + float * d_var_61_1; + cudaMalloc((void **)&d_var_61_1, sizeof(float *)); + + float * h_var_61_2 = (float *)malloc(sizeof(float *)); + float * d_var_61_2; + cudaMalloc((void **)&d_var_61_2, sizeof(float *)); + + float * h_var_61_3 = (float *)malloc(sizeof(float *)); + float * d_var_61_3; + cudaMalloc((void **)&d_var_61_3, sizeof(float *)); + + float * h_var_61_4 = (float *)malloc(sizeof(float *)); + float * d_var_61_4; + cudaMalloc((void **)&d_var_61_4, sizeof(float *)); + + float * h_var_61_5 = (float *)malloc(sizeof(float *)); + float * d_var_61_5; + cudaMalloc((void **)&d_var_61_5, sizeof(float *)); + + float * h_var_61_6 = (float *)malloc(sizeof(float *)); + float * d_var_61_6; + cudaMalloc((void **)&d_var_61_6, sizeof(float *)); + + float * h_var_61_7 = (float *)malloc(sizeof(float *)); + float * d_var_61_7; + cudaMalloc((void **)&d_var_61_7, sizeof(float *)); + + float * h_var_61_8 = (float *)malloc(sizeof(float *)); + float * d_var_61_8; + cudaMalloc((void **)&d_var_61_8, sizeof(float *)); + + float * h_var_61_9 = (float *)malloc(sizeof(float *)); + float * d_var_61_9; + cudaMalloc((void **)&d_var_61_9, sizeof(float *)); + + float * h_var_61_10 = (float *)malloc(sizeof(float *)); + float * d_var_61_10; + cudaMalloc((void **)&d_var_61_10, sizeof(float *)); + + float * h_var_61_11 = (float *)malloc(sizeof(float *)); + float * d_var_61_11; + cudaMalloc((void **)&d_var_61_11, sizeof(float *)); + + float * h_var_61_12 = (float *)malloc(sizeof(float *)); + float * d_var_61_12; + cudaMalloc((void **)&d_var_61_12, sizeof(float *)); + + float * h_var_61_13 = (float *)malloc(sizeof(float *)); + float * d_var_61_13; + cudaMalloc((void **)&d_var_61_13, sizeof(float *)); + + float * h_var_61_14 = (float *)malloc(sizeof(float *)); + float * d_var_61_14; + cudaMalloc((void **)&d_var_61_14, sizeof(float *)); + + float * h_var_61_15 = (float *)malloc(sizeof(float *)); + float * d_var_61_15; + cudaMalloc((void **)&d_var_61_15, sizeof(float *)); + + float * h_var_61_16 = (float *)malloc(sizeof(float *)); + float * d_var_61_16; + cudaMalloc((void **)&d_var_61_16, sizeof(float *)); + + float * h_var_61_17 = (float *)malloc(sizeof(float *)); + float * d_var_61_17; + cudaMalloc((void **)&d_var_61_17, sizeof(float *)); + + float * h_var_61_18 = (float *)malloc(sizeof(float *)); + float * d_var_61_18; + cudaMalloc((void **)&d_var_61_18, sizeof(float *)); + + float * h_var_61_19 = (float *)malloc(sizeof(float *)); + float * d_var_61_19; + cudaMalloc((void **)&d_var_61_19, sizeof(float *)); + + float * h_var_62_0 = (float *)malloc(sizeof(float *)); + float * d_var_62_0; + cudaMalloc((void **)&d_var_62_0, sizeof(float *)); + + float * h_var_62_1 = (float *)malloc(sizeof(float *)); + float * d_var_62_1; + cudaMalloc((void **)&d_var_62_1, sizeof(float *)); + + float * h_var_62_2 = (float *)malloc(sizeof(float *)); + float * d_var_62_2; + cudaMalloc((void **)&d_var_62_2, sizeof(float *)); + + float * h_var_62_3 = (float *)malloc(sizeof(float *)); + float * d_var_62_3; + cudaMalloc((void **)&d_var_62_3, sizeof(float *)); + + float * h_var_62_4 = (float *)malloc(sizeof(float *)); + float * d_var_62_4; + cudaMalloc((void **)&d_var_62_4, sizeof(float *)); + + float * h_var_62_5 = (float *)malloc(sizeof(float *)); + float * d_var_62_5; + cudaMalloc((void **)&d_var_62_5, sizeof(float *)); + + float * h_var_62_6 = (float *)malloc(sizeof(float *)); + float * d_var_62_6; + cudaMalloc((void **)&d_var_62_6, sizeof(float *)); + + float * h_var_62_7 = (float *)malloc(sizeof(float *)); + float * d_var_62_7; + cudaMalloc((void **)&d_var_62_7, sizeof(float *)); + + float * h_var_62_8 = (float *)malloc(sizeof(float *)); + float * d_var_62_8; + cudaMalloc((void **)&d_var_62_8, sizeof(float *)); + + float * h_var_62_9 = (float *)malloc(sizeof(float *)); + float * d_var_62_9; + cudaMalloc((void **)&d_var_62_9, sizeof(float *)); + + float * h_var_62_10 = (float *)malloc(sizeof(float *)); + float * d_var_62_10; + cudaMalloc((void **)&d_var_62_10, sizeof(float *)); + + float * h_var_62_11 = (float *)malloc(sizeof(float *)); + float * d_var_62_11; + cudaMalloc((void **)&d_var_62_11, sizeof(float *)); + + float * h_var_62_12 = (float *)malloc(sizeof(float *)); + float * d_var_62_12; + cudaMalloc((void **)&d_var_62_12, sizeof(float *)); + + float * h_var_62_13 = (float *)malloc(sizeof(float *)); + float * d_var_62_13; + cudaMalloc((void **)&d_var_62_13, sizeof(float *)); + + float * h_var_62_14 = (float *)malloc(sizeof(float *)); + float * d_var_62_14; + cudaMalloc((void **)&d_var_62_14, sizeof(float *)); + + float * h_var_62_15 = (float *)malloc(sizeof(float *)); + float * d_var_62_15; + cudaMalloc((void **)&d_var_62_15, sizeof(float *)); + + float * h_var_62_16 = (float *)malloc(sizeof(float *)); + float * d_var_62_16; + cudaMalloc((void **)&d_var_62_16, sizeof(float *)); + + float * h_var_62_17 = (float *)malloc(sizeof(float *)); + float * d_var_62_17; + cudaMalloc((void **)&d_var_62_17, sizeof(float *)); + + float * h_var_62_18 = (float *)malloc(sizeof(float *)); + float * d_var_62_18; + cudaMalloc((void **)&d_var_62_18, sizeof(float *)); + + float * h_var_62_19 = (float *)malloc(sizeof(float *)); + float * d_var_62_19; + cudaMalloc((void **)&d_var_62_19, sizeof(float *)); + + float * h_var_63_0 = (float *)malloc(sizeof(float *)); + float * d_var_63_0; + cudaMalloc((void **)&d_var_63_0, sizeof(float *)); + + float * h_var_63_1 = (float *)malloc(sizeof(float *)); + float * d_var_63_1; + cudaMalloc((void **)&d_var_63_1, sizeof(float *)); + + float * h_var_63_2 = (float *)malloc(sizeof(float *)); + float * d_var_63_2; + cudaMalloc((void **)&d_var_63_2, sizeof(float *)); + + float * h_var_63_3 = (float *)malloc(sizeof(float *)); + float * d_var_63_3; + cudaMalloc((void **)&d_var_63_3, sizeof(float *)); + + float * h_var_63_4 = (float *)malloc(sizeof(float *)); + float * d_var_63_4; + cudaMalloc((void **)&d_var_63_4, sizeof(float *)); + + float * h_var_63_5 = (float *)malloc(sizeof(float *)); + float * d_var_63_5; + cudaMalloc((void **)&d_var_63_5, sizeof(float *)); + + float * h_var_63_6 = (float *)malloc(sizeof(float *)); + float * d_var_63_6; + cudaMalloc((void **)&d_var_63_6, sizeof(float *)); + + float * h_var_63_7 = (float *)malloc(sizeof(float *)); + float * d_var_63_7; + cudaMalloc((void **)&d_var_63_7, sizeof(float *)); + + float * h_var_63_8 = (float *)malloc(sizeof(float *)); + float * d_var_63_8; + cudaMalloc((void **)&d_var_63_8, sizeof(float *)); + + float * h_var_63_9 = (float *)malloc(sizeof(float *)); + float * d_var_63_9; + cudaMalloc((void **)&d_var_63_9, sizeof(float *)); + + float * h_var_63_10 = (float *)malloc(sizeof(float *)); + float * d_var_63_10; + cudaMalloc((void **)&d_var_63_10, sizeof(float *)); + + float * h_var_63_11 = (float *)malloc(sizeof(float *)); + float * d_var_63_11; + cudaMalloc((void **)&d_var_63_11, sizeof(float *)); + + float * h_var_63_12 = (float *)malloc(sizeof(float *)); + float * d_var_63_12; + cudaMalloc((void **)&d_var_63_12, sizeof(float *)); + + float * h_var_63_13 = (float *)malloc(sizeof(float *)); + float * d_var_63_13; + cudaMalloc((void **)&d_var_63_13, sizeof(float *)); + + float * h_var_63_14 = (float *)malloc(sizeof(float *)); + float * d_var_63_14; + cudaMalloc((void **)&d_var_63_14, sizeof(float *)); + + float * h_var_63_15 = (float *)malloc(sizeof(float *)); + float * d_var_63_15; + cudaMalloc((void **)&d_var_63_15, sizeof(float *)); + + float * h_var_63_16 = (float *)malloc(sizeof(float *)); + float * d_var_63_16; + cudaMalloc((void **)&d_var_63_16, sizeof(float *)); + + float * h_var_63_17 = (float *)malloc(sizeof(float *)); + float * d_var_63_17; + cudaMalloc((void **)&d_var_63_17, sizeof(float *)); + + float * h_var_63_18 = (float *)malloc(sizeof(float *)); + float * d_var_63_18; + cudaMalloc((void **)&d_var_63_18, sizeof(float *)); + + float * h_var_63_19 = (float *)malloc(sizeof(float *)); + float * d_var_63_19; + cudaMalloc((void **)&d_var_63_19, sizeof(float *)); + + float * h_var_64_0 = (float *)malloc(sizeof(float *)); + float * d_var_64_0; + cudaMalloc((void **)&d_var_64_0, sizeof(float *)); + + float * h_var_64_1 = (float *)malloc(sizeof(float *)); + float * d_var_64_1; + cudaMalloc((void **)&d_var_64_1, sizeof(float *)); + + float * h_var_64_2 = (float *)malloc(sizeof(float *)); + float * d_var_64_2; + cudaMalloc((void **)&d_var_64_2, sizeof(float *)); + + float * h_var_64_3 = (float *)malloc(sizeof(float *)); + float * d_var_64_3; + cudaMalloc((void **)&d_var_64_3, sizeof(float *)); + + float * h_var_64_4 = (float *)malloc(sizeof(float *)); + float * d_var_64_4; + cudaMalloc((void **)&d_var_64_4, sizeof(float *)); + + float * h_var_64_5 = (float *)malloc(sizeof(float *)); + float * d_var_64_5; + cudaMalloc((void **)&d_var_64_5, sizeof(float *)); + + float * h_var_64_6 = (float *)malloc(sizeof(float *)); + float * d_var_64_6; + cudaMalloc((void **)&d_var_64_6, sizeof(float *)); + + float * h_var_64_7 = (float *)malloc(sizeof(float *)); + float * d_var_64_7; + cudaMalloc((void **)&d_var_64_7, sizeof(float *)); + + float * h_var_64_8 = (float *)malloc(sizeof(float *)); + float * d_var_64_8; + cudaMalloc((void **)&d_var_64_8, sizeof(float *)); + + float * h_var_64_9 = (float *)malloc(sizeof(float *)); + float * d_var_64_9; + cudaMalloc((void **)&d_var_64_9, sizeof(float *)); + + float * h_var_64_10 = (float *)malloc(sizeof(float *)); + float * d_var_64_10; + cudaMalloc((void **)&d_var_64_10, sizeof(float *)); + + float * h_var_64_11 = (float *)malloc(sizeof(float *)); + float * d_var_64_11; + cudaMalloc((void **)&d_var_64_11, sizeof(float *)); + + float * h_var_64_12 = (float *)malloc(sizeof(float *)); + float * d_var_64_12; + cudaMalloc((void **)&d_var_64_12, sizeof(float *)); + + float * h_var_64_13 = (float *)malloc(sizeof(float *)); + float * d_var_64_13; + cudaMalloc((void **)&d_var_64_13, sizeof(float *)); + + float * h_var_64_14 = (float *)malloc(sizeof(float *)); + float * d_var_64_14; + cudaMalloc((void **)&d_var_64_14, sizeof(float *)); + + float * h_var_64_15 = (float *)malloc(sizeof(float *)); + float * d_var_64_15; + cudaMalloc((void **)&d_var_64_15, sizeof(float *)); + + float * h_var_64_16 = (float *)malloc(sizeof(float *)); + float * d_var_64_16; + cudaMalloc((void **)&d_var_64_16, sizeof(float *)); + + float * h_var_64_17 = (float *)malloc(sizeof(float *)); + float * d_var_64_17; + cudaMalloc((void **)&d_var_64_17, sizeof(float *)); + + float * h_var_64_18 = (float *)malloc(sizeof(float *)); + float * d_var_64_18; + cudaMalloc((void **)&d_var_64_18, sizeof(float *)); + + float * h_var_64_19 = (float *)malloc(sizeof(float *)); + float * d_var_64_19; + cudaMalloc((void **)&d_var_64_19, sizeof(float *)); + + float * h_var_65_0 = (float *)malloc(sizeof(float *)); + float * d_var_65_0; + cudaMalloc((void **)&d_var_65_0, sizeof(float *)); + + float * h_var_65_1 = (float *)malloc(sizeof(float *)); + float * d_var_65_1; + cudaMalloc((void **)&d_var_65_1, sizeof(float *)); + + float * h_var_65_2 = (float *)malloc(sizeof(float *)); + float * d_var_65_2; + cudaMalloc((void **)&d_var_65_2, sizeof(float *)); + + float * h_var_65_3 = (float *)malloc(sizeof(float *)); + float * d_var_65_3; + cudaMalloc((void **)&d_var_65_3, sizeof(float *)); + + float * h_var_65_4 = (float *)malloc(sizeof(float *)); + float * d_var_65_4; + cudaMalloc((void **)&d_var_65_4, sizeof(float *)); + + float * h_var_65_5 = (float *)malloc(sizeof(float *)); + float * d_var_65_5; + cudaMalloc((void **)&d_var_65_5, sizeof(float *)); + + float * h_var_65_6 = (float *)malloc(sizeof(float *)); + float * d_var_65_6; + cudaMalloc((void **)&d_var_65_6, sizeof(float *)); + + float * h_var_65_7 = (float *)malloc(sizeof(float *)); + float * d_var_65_7; + cudaMalloc((void **)&d_var_65_7, sizeof(float *)); + + float * h_var_65_8 = (float *)malloc(sizeof(float *)); + float * d_var_65_8; + cudaMalloc((void **)&d_var_65_8, sizeof(float *)); + + float * h_var_65_9 = (float *)malloc(sizeof(float *)); + float * d_var_65_9; + cudaMalloc((void **)&d_var_65_9, sizeof(float *)); + + float * h_var_65_10 = (float *)malloc(sizeof(float *)); + float * d_var_65_10; + cudaMalloc((void **)&d_var_65_10, sizeof(float *)); + + float * h_var_65_11 = (float *)malloc(sizeof(float *)); + float * d_var_65_11; + cudaMalloc((void **)&d_var_65_11, sizeof(float *)); + + float * h_var_65_12 = (float *)malloc(sizeof(float *)); + float * d_var_65_12; + cudaMalloc((void **)&d_var_65_12, sizeof(float *)); + + float * h_var_65_13 = (float *)malloc(sizeof(float *)); + float * d_var_65_13; + cudaMalloc((void **)&d_var_65_13, sizeof(float *)); + + float * h_var_65_14 = (float *)malloc(sizeof(float *)); + float * d_var_65_14; + cudaMalloc((void **)&d_var_65_14, sizeof(float *)); + + float * h_var_65_15 = (float *)malloc(sizeof(float *)); + float * d_var_65_15; + cudaMalloc((void **)&d_var_65_15, sizeof(float *)); + + float * h_var_65_16 = (float *)malloc(sizeof(float *)); + float * d_var_65_16; + cudaMalloc((void **)&d_var_65_16, sizeof(float *)); + + float * h_var_65_17 = (float *)malloc(sizeof(float *)); + float * d_var_65_17; + cudaMalloc((void **)&d_var_65_17, sizeof(float *)); + + float * h_var_65_18 = (float *)malloc(sizeof(float *)); + float * d_var_65_18; + cudaMalloc((void **)&d_var_65_18, sizeof(float *)); + + float * h_var_65_19 = (float *)malloc(sizeof(float *)); + float * d_var_65_19; + cudaMalloc((void **)&d_var_65_19, sizeof(float *)); + + float * h_var_66_0 = (float *)malloc(sizeof(float *)); + float * d_var_66_0; + cudaMalloc((void **)&d_var_66_0, sizeof(float *)); + + float * h_var_66_1 = (float *)malloc(sizeof(float *)); + float * d_var_66_1; + cudaMalloc((void **)&d_var_66_1, sizeof(float *)); + + float * h_var_66_2 = (float *)malloc(sizeof(float *)); + float * d_var_66_2; + cudaMalloc((void **)&d_var_66_2, sizeof(float *)); + + float * h_var_66_3 = (float *)malloc(sizeof(float *)); + float * d_var_66_3; + cudaMalloc((void **)&d_var_66_3, sizeof(float *)); + + float * h_var_66_4 = (float *)malloc(sizeof(float *)); + float * d_var_66_4; + cudaMalloc((void **)&d_var_66_4, sizeof(float *)); + + float * h_var_66_5 = (float *)malloc(sizeof(float *)); + float * d_var_66_5; + cudaMalloc((void **)&d_var_66_5, sizeof(float *)); + + float * h_var_66_6 = (float *)malloc(sizeof(float *)); + float * d_var_66_6; + cudaMalloc((void **)&d_var_66_6, sizeof(float *)); + + float * h_var_66_7 = (float *)malloc(sizeof(float *)); + float * d_var_66_7; + cudaMalloc((void **)&d_var_66_7, sizeof(float *)); + + float * h_var_66_8 = (float *)malloc(sizeof(float *)); + float * d_var_66_8; + cudaMalloc((void **)&d_var_66_8, sizeof(float *)); + + float * h_var_66_9 = (float *)malloc(sizeof(float *)); + float * d_var_66_9; + cudaMalloc((void **)&d_var_66_9, sizeof(float *)); + + float * h_var_66_10 = (float *)malloc(sizeof(float *)); + float * d_var_66_10; + cudaMalloc((void **)&d_var_66_10, sizeof(float *)); + + float * h_var_66_11 = (float *)malloc(sizeof(float *)); + float * d_var_66_11; + cudaMalloc((void **)&d_var_66_11, sizeof(float *)); + + float * h_var_66_12 = (float *)malloc(sizeof(float *)); + float * d_var_66_12; + cudaMalloc((void **)&d_var_66_12, sizeof(float *)); + + float * h_var_66_13 = (float *)malloc(sizeof(float *)); + float * d_var_66_13; + cudaMalloc((void **)&d_var_66_13, sizeof(float *)); + + float * h_var_66_14 = (float *)malloc(sizeof(float *)); + float * d_var_66_14; + cudaMalloc((void **)&d_var_66_14, sizeof(float *)); + + float * h_var_66_15 = (float *)malloc(sizeof(float *)); + float * d_var_66_15; + cudaMalloc((void **)&d_var_66_15, sizeof(float *)); + + float * h_var_66_16 = (float *)malloc(sizeof(float *)); + float * d_var_66_16; + cudaMalloc((void **)&d_var_66_16, sizeof(float *)); + + float * h_var_66_17 = (float *)malloc(sizeof(float *)); + float * d_var_66_17; + cudaMalloc((void **)&d_var_66_17, sizeof(float *)); + + float * h_var_66_18 = (float *)malloc(sizeof(float *)); + float * d_var_66_18; + cudaMalloc((void **)&d_var_66_18, sizeof(float *)); + + float * h_var_66_19 = (float *)malloc(sizeof(float *)); + float * d_var_66_19; + cudaMalloc((void **)&d_var_66_19, sizeof(float *)); + + float * h_var_67_0 = (float *)malloc(sizeof(float *)); + float * d_var_67_0; + cudaMalloc((void **)&d_var_67_0, sizeof(float *)); + + float * h_var_67_1 = (float *)malloc(sizeof(float *)); + float * d_var_67_1; + cudaMalloc((void **)&d_var_67_1, sizeof(float *)); + + float * h_var_67_2 = (float *)malloc(sizeof(float *)); + float * d_var_67_2; + cudaMalloc((void **)&d_var_67_2, sizeof(float *)); + + float * h_var_67_3 = (float *)malloc(sizeof(float *)); + float * d_var_67_3; + cudaMalloc((void **)&d_var_67_3, sizeof(float *)); + + float * h_var_67_4 = (float *)malloc(sizeof(float *)); + float * d_var_67_4; + cudaMalloc((void **)&d_var_67_4, sizeof(float *)); + + float * h_var_67_5 = (float *)malloc(sizeof(float *)); + float * d_var_67_5; + cudaMalloc((void **)&d_var_67_5, sizeof(float *)); + + float * h_var_67_6 = (float *)malloc(sizeof(float *)); + float * d_var_67_6; + cudaMalloc((void **)&d_var_67_6, sizeof(float *)); + + float * h_var_67_7 = (float *)malloc(sizeof(float *)); + float * d_var_67_7; + cudaMalloc((void **)&d_var_67_7, sizeof(float *)); + + float * h_var_67_8 = (float *)malloc(sizeof(float *)); + float * d_var_67_8; + cudaMalloc((void **)&d_var_67_8, sizeof(float *)); + + float * h_var_67_9 = (float *)malloc(sizeof(float *)); + float * d_var_67_9; + cudaMalloc((void **)&d_var_67_9, sizeof(float *)); + + float * h_var_67_10 = (float *)malloc(sizeof(float *)); + float * d_var_67_10; + cudaMalloc((void **)&d_var_67_10, sizeof(float *)); + + float * h_var_67_11 = (float *)malloc(sizeof(float *)); + float * d_var_67_11; + cudaMalloc((void **)&d_var_67_11, sizeof(float *)); + + float * h_var_67_12 = (float *)malloc(sizeof(float *)); + float * d_var_67_12; + cudaMalloc((void **)&d_var_67_12, sizeof(float *)); + + float * h_var_67_13 = (float *)malloc(sizeof(float *)); + float * d_var_67_13; + cudaMalloc((void **)&d_var_67_13, sizeof(float *)); + + float * h_var_67_14 = (float *)malloc(sizeof(float *)); + float * d_var_67_14; + cudaMalloc((void **)&d_var_67_14, sizeof(float *)); + + float * h_var_67_15 = (float *)malloc(sizeof(float *)); + float * d_var_67_15; + cudaMalloc((void **)&d_var_67_15, sizeof(float *)); + + float * h_var_67_16 = (float *)malloc(sizeof(float *)); + float * d_var_67_16; + cudaMalloc((void **)&d_var_67_16, sizeof(float *)); + + float * h_var_67_17 = (float *)malloc(sizeof(float *)); + float * d_var_67_17; + cudaMalloc((void **)&d_var_67_17, sizeof(float *)); + + float * h_var_67_18 = (float *)malloc(sizeof(float *)); + float * d_var_67_18; + cudaMalloc((void **)&d_var_67_18, sizeof(float *)); + + float * h_var_67_19 = (float *)malloc(sizeof(float *)); + float * d_var_67_19; + cudaMalloc((void **)&d_var_67_19, sizeof(float *)); + + float * h_var_68_0 = (float *)malloc(sizeof(float *)); + float * d_var_68_0; + cudaMalloc((void **)&d_var_68_0, sizeof(float *)); + + float * h_var_68_1 = (float *)malloc(sizeof(float *)); + float * d_var_68_1; + cudaMalloc((void **)&d_var_68_1, sizeof(float *)); + + float * h_var_68_2 = (float *)malloc(sizeof(float *)); + float * d_var_68_2; + cudaMalloc((void **)&d_var_68_2, sizeof(float *)); + + float * h_var_68_3 = (float *)malloc(sizeof(float *)); + float * d_var_68_3; + cudaMalloc((void **)&d_var_68_3, sizeof(float *)); + + float * h_var_68_4 = (float *)malloc(sizeof(float *)); + float * d_var_68_4; + cudaMalloc((void **)&d_var_68_4, sizeof(float *)); + + float * h_var_68_5 = (float *)malloc(sizeof(float *)); + float * d_var_68_5; + cudaMalloc((void **)&d_var_68_5, sizeof(float *)); + + float * h_var_68_6 = (float *)malloc(sizeof(float *)); + float * d_var_68_6; + cudaMalloc((void **)&d_var_68_6, sizeof(float *)); + + float * h_var_68_7 = (float *)malloc(sizeof(float *)); + float * d_var_68_7; + cudaMalloc((void **)&d_var_68_7, sizeof(float *)); + + float * h_var_68_8 = (float *)malloc(sizeof(float *)); + float * d_var_68_8; + cudaMalloc((void **)&d_var_68_8, sizeof(float *)); + + float * h_var_68_9 = (float *)malloc(sizeof(float *)); + float * d_var_68_9; + cudaMalloc((void **)&d_var_68_9, sizeof(float *)); + + float * h_var_68_10 = (float *)malloc(sizeof(float *)); + float * d_var_68_10; + cudaMalloc((void **)&d_var_68_10, sizeof(float *)); + + float * h_var_68_11 = (float *)malloc(sizeof(float *)); + float * d_var_68_11; + cudaMalloc((void **)&d_var_68_11, sizeof(float *)); + + float * h_var_68_12 = (float *)malloc(sizeof(float *)); + float * d_var_68_12; + cudaMalloc((void **)&d_var_68_12, sizeof(float *)); + + float * h_var_68_13 = (float *)malloc(sizeof(float *)); + float * d_var_68_13; + cudaMalloc((void **)&d_var_68_13, sizeof(float *)); + + float * h_var_68_14 = (float *)malloc(sizeof(float *)); + float * d_var_68_14; + cudaMalloc((void **)&d_var_68_14, sizeof(float *)); + + float * h_var_68_15 = (float *)malloc(sizeof(float *)); + float * d_var_68_15; + cudaMalloc((void **)&d_var_68_15, sizeof(float *)); + + float * h_var_68_16 = (float *)malloc(sizeof(float *)); + float * d_var_68_16; + cudaMalloc((void **)&d_var_68_16, sizeof(float *)); + + float * h_var_68_17 = (float *)malloc(sizeof(float *)); + float * d_var_68_17; + cudaMalloc((void **)&d_var_68_17, sizeof(float *)); + + float * h_var_68_18 = (float *)malloc(sizeof(float *)); + float * d_var_68_18; + cudaMalloc((void **)&d_var_68_18, sizeof(float *)); + + float * h_var_68_19 = (float *)malloc(sizeof(float *)); + float * d_var_68_19; + cudaMalloc((void **)&d_var_68_19, sizeof(float *)); + + float * h_var_69_0 = (float *)malloc(sizeof(float *)); + float * d_var_69_0; + cudaMalloc((void **)&d_var_69_0, sizeof(float *)); + + float * h_var_69_1 = (float *)malloc(sizeof(float *)); + float * d_var_69_1; + cudaMalloc((void **)&d_var_69_1, sizeof(float *)); + + float * h_var_69_2 = (float *)malloc(sizeof(float *)); + float * d_var_69_2; + cudaMalloc((void **)&d_var_69_2, sizeof(float *)); + + float * h_var_69_3 = (float *)malloc(sizeof(float *)); + float * d_var_69_3; + cudaMalloc((void **)&d_var_69_3, sizeof(float *)); + + float * h_var_69_4 = (float *)malloc(sizeof(float *)); + float * d_var_69_4; + cudaMalloc((void **)&d_var_69_4, sizeof(float *)); + + float * h_var_69_5 = (float *)malloc(sizeof(float *)); + float * d_var_69_5; + cudaMalloc((void **)&d_var_69_5, sizeof(float *)); + + float * h_var_69_6 = (float *)malloc(sizeof(float *)); + float * d_var_69_6; + cudaMalloc((void **)&d_var_69_6, sizeof(float *)); + + float * h_var_69_7 = (float *)malloc(sizeof(float *)); + float * d_var_69_7; + cudaMalloc((void **)&d_var_69_7, sizeof(float *)); + + float * h_var_69_8 = (float *)malloc(sizeof(float *)); + float * d_var_69_8; + cudaMalloc((void **)&d_var_69_8, sizeof(float *)); + + float * h_var_69_9 = (float *)malloc(sizeof(float *)); + float * d_var_69_9; + cudaMalloc((void **)&d_var_69_9, sizeof(float *)); + + float * h_var_69_10 = (float *)malloc(sizeof(float *)); + float * d_var_69_10; + cudaMalloc((void **)&d_var_69_10, sizeof(float *)); + + float * h_var_69_11 = (float *)malloc(sizeof(float *)); + float * d_var_69_11; + cudaMalloc((void **)&d_var_69_11, sizeof(float *)); + + float * h_var_69_12 = (float *)malloc(sizeof(float *)); + float * d_var_69_12; + cudaMalloc((void **)&d_var_69_12, sizeof(float *)); + + float * h_var_69_13 = (float *)malloc(sizeof(float *)); + float * d_var_69_13; + cudaMalloc((void **)&d_var_69_13, sizeof(float *)); + + float * h_var_69_14 = (float *)malloc(sizeof(float *)); + float * d_var_69_14; + cudaMalloc((void **)&d_var_69_14, sizeof(float *)); + + float * h_var_69_15 = (float *)malloc(sizeof(float *)); + float * d_var_69_15; + cudaMalloc((void **)&d_var_69_15, sizeof(float *)); + + float * h_var_69_16 = (float *)malloc(sizeof(float *)); + float * d_var_69_16; + cudaMalloc((void **)&d_var_69_16, sizeof(float *)); + + float * h_var_69_17 = (float *)malloc(sizeof(float *)); + float * d_var_69_17; + cudaMalloc((void **)&d_var_69_17, sizeof(float *)); + + float * h_var_69_18 = (float *)malloc(sizeof(float *)); + float * d_var_69_18; + cudaMalloc((void **)&d_var_69_18, sizeof(float *)); + + float * h_var_69_19 = (float *)malloc(sizeof(float *)); + float * d_var_69_19; + cudaMalloc((void **)&d_var_69_19, sizeof(float *)); + + float * h_var_70_0 = (float *)malloc(sizeof(float *)); + float * d_var_70_0; + cudaMalloc((void **)&d_var_70_0, sizeof(float *)); + + float * h_var_70_1 = (float *)malloc(sizeof(float *)); + float * d_var_70_1; + cudaMalloc((void **)&d_var_70_1, sizeof(float *)); + + float * h_var_70_2 = (float *)malloc(sizeof(float *)); + float * d_var_70_2; + cudaMalloc((void **)&d_var_70_2, sizeof(float *)); + + float * h_var_70_3 = (float *)malloc(sizeof(float *)); + float * d_var_70_3; + cudaMalloc((void **)&d_var_70_3, sizeof(float *)); + + float * h_var_70_4 = (float *)malloc(sizeof(float *)); + float * d_var_70_4; + cudaMalloc((void **)&d_var_70_4, sizeof(float *)); + + float * h_var_70_5 = (float *)malloc(sizeof(float *)); + float * d_var_70_5; + cudaMalloc((void **)&d_var_70_5, sizeof(float *)); + + float * h_var_70_6 = (float *)malloc(sizeof(float *)); + float * d_var_70_6; + cudaMalloc((void **)&d_var_70_6, sizeof(float *)); + + float * h_var_70_7 = (float *)malloc(sizeof(float *)); + float * d_var_70_7; + cudaMalloc((void **)&d_var_70_7, sizeof(float *)); + + float * h_var_70_8 = (float *)malloc(sizeof(float *)); + float * d_var_70_8; + cudaMalloc((void **)&d_var_70_8, sizeof(float *)); + + float * h_var_70_9 = (float *)malloc(sizeof(float *)); + float * d_var_70_9; + cudaMalloc((void **)&d_var_70_9, sizeof(float *)); + + float * h_var_70_10 = (float *)malloc(sizeof(float *)); + float * d_var_70_10; + cudaMalloc((void **)&d_var_70_10, sizeof(float *)); + + float * h_var_70_11 = (float *)malloc(sizeof(float *)); + float * d_var_70_11; + cudaMalloc((void **)&d_var_70_11, sizeof(float *)); + + float * h_var_70_12 = (float *)malloc(sizeof(float *)); + float * d_var_70_12; + cudaMalloc((void **)&d_var_70_12, sizeof(float *)); + + float * h_var_70_13 = (float *)malloc(sizeof(float *)); + float * d_var_70_13; + cudaMalloc((void **)&d_var_70_13, sizeof(float *)); + + float * h_var_70_14 = (float *)malloc(sizeof(float *)); + float * d_var_70_14; + cudaMalloc((void **)&d_var_70_14, sizeof(float *)); + + float * h_var_70_15 = (float *)malloc(sizeof(float *)); + float * d_var_70_15; + cudaMalloc((void **)&d_var_70_15, sizeof(float *)); + + float * h_var_70_16 = (float *)malloc(sizeof(float *)); + float * d_var_70_16; + cudaMalloc((void **)&d_var_70_16, sizeof(float *)); + + float * h_var_70_17 = (float *)malloc(sizeof(float *)); + float * d_var_70_17; + cudaMalloc((void **)&d_var_70_17, sizeof(float *)); + + float * h_var_70_18 = (float *)malloc(sizeof(float *)); + float * d_var_70_18; + cudaMalloc((void **)&d_var_70_18, sizeof(float *)); + + float * h_var_70_19 = (float *)malloc(sizeof(float *)); + float * d_var_70_19; + cudaMalloc((void **)&d_var_70_19, sizeof(float *)); + + float * h_var_71_0 = (float *)malloc(sizeof(float *)); + float * d_var_71_0; + cudaMalloc((void **)&d_var_71_0, sizeof(float *)); + + float * h_var_71_1 = (float *)malloc(sizeof(float *)); + float * d_var_71_1; + cudaMalloc((void **)&d_var_71_1, sizeof(float *)); + + float * h_var_71_2 = (float *)malloc(sizeof(float *)); + float * d_var_71_2; + cudaMalloc((void **)&d_var_71_2, sizeof(float *)); + + float * h_var_71_3 = (float *)malloc(sizeof(float *)); + float * d_var_71_3; + cudaMalloc((void **)&d_var_71_3, sizeof(float *)); + + float * h_var_71_4 = (float *)malloc(sizeof(float *)); + float * d_var_71_4; + cudaMalloc((void **)&d_var_71_4, sizeof(float *)); + + float * h_var_71_5 = (float *)malloc(sizeof(float *)); + float * d_var_71_5; + cudaMalloc((void **)&d_var_71_5, sizeof(float *)); + + float * h_var_71_6 = (float *)malloc(sizeof(float *)); + float * d_var_71_6; + cudaMalloc((void **)&d_var_71_6, sizeof(float *)); + + float * h_var_71_7 = (float *)malloc(sizeof(float *)); + float * d_var_71_7; + cudaMalloc((void **)&d_var_71_7, sizeof(float *)); + + float * h_var_71_8 = (float *)malloc(sizeof(float *)); + float * d_var_71_8; + cudaMalloc((void **)&d_var_71_8, sizeof(float *)); + + float * h_var_71_9 = (float *)malloc(sizeof(float *)); + float * d_var_71_9; + cudaMalloc((void **)&d_var_71_9, sizeof(float *)); + + float * h_var_71_10 = (float *)malloc(sizeof(float *)); + float * d_var_71_10; + cudaMalloc((void **)&d_var_71_10, sizeof(float *)); + + float * h_var_71_11 = (float *)malloc(sizeof(float *)); + float * d_var_71_11; + cudaMalloc((void **)&d_var_71_11, sizeof(float *)); + + float * h_var_71_12 = (float *)malloc(sizeof(float *)); + float * d_var_71_12; + cudaMalloc((void **)&d_var_71_12, sizeof(float *)); + + float * h_var_71_13 = (float *)malloc(sizeof(float *)); + float * d_var_71_13; + cudaMalloc((void **)&d_var_71_13, sizeof(float *)); + + float * h_var_71_14 = (float *)malloc(sizeof(float *)); + float * d_var_71_14; + cudaMalloc((void **)&d_var_71_14, sizeof(float *)); + + float * h_var_71_15 = (float *)malloc(sizeof(float *)); + float * d_var_71_15; + cudaMalloc((void **)&d_var_71_15, sizeof(float *)); + + float * h_var_71_16 = (float *)malloc(sizeof(float *)); + float * d_var_71_16; + cudaMalloc((void **)&d_var_71_16, sizeof(float *)); + + float * h_var_71_17 = (float *)malloc(sizeof(float *)); + float * d_var_71_17; + cudaMalloc((void **)&d_var_71_17, sizeof(float *)); + + float * h_var_71_18 = (float *)malloc(sizeof(float *)); + float * d_var_71_18; + cudaMalloc((void **)&d_var_71_18, sizeof(float *)); + + float * h_var_71_19 = (float *)malloc(sizeof(float *)); + float * d_var_71_19; + cudaMalloc((void **)&d_var_71_19, sizeof(float *)); + + float * h_var_72_0 = (float *)malloc(sizeof(float *)); + float * d_var_72_0; + cudaMalloc((void **)&d_var_72_0, sizeof(float *)); + + float * h_var_72_1 = (float *)malloc(sizeof(float *)); + float * d_var_72_1; + cudaMalloc((void **)&d_var_72_1, sizeof(float *)); + + float * h_var_72_2 = (float *)malloc(sizeof(float *)); + float * d_var_72_2; + cudaMalloc((void **)&d_var_72_2, sizeof(float *)); + + float * h_var_72_3 = (float *)malloc(sizeof(float *)); + float * d_var_72_3; + cudaMalloc((void **)&d_var_72_3, sizeof(float *)); + + float * h_var_72_4 = (float *)malloc(sizeof(float *)); + float * d_var_72_4; + cudaMalloc((void **)&d_var_72_4, sizeof(float *)); + + float * h_var_72_5 = (float *)malloc(sizeof(float *)); + float * d_var_72_5; + cudaMalloc((void **)&d_var_72_5, sizeof(float *)); + + float * h_var_72_6 = (float *)malloc(sizeof(float *)); + float * d_var_72_6; + cudaMalloc((void **)&d_var_72_6, sizeof(float *)); + + float * h_var_72_7 = (float *)malloc(sizeof(float *)); + float * d_var_72_7; + cudaMalloc((void **)&d_var_72_7, sizeof(float *)); + + float * h_var_72_8 = (float *)malloc(sizeof(float *)); + float * d_var_72_8; + cudaMalloc((void **)&d_var_72_8, sizeof(float *)); + + float * h_var_72_9 = (float *)malloc(sizeof(float *)); + float * d_var_72_9; + cudaMalloc((void **)&d_var_72_9, sizeof(float *)); + + float * h_var_72_10 = (float *)malloc(sizeof(float *)); + float * d_var_72_10; + cudaMalloc((void **)&d_var_72_10, sizeof(float *)); + + float * h_var_72_11 = (float *)malloc(sizeof(float *)); + float * d_var_72_11; + cudaMalloc((void **)&d_var_72_11, sizeof(float *)); + + float * h_var_72_12 = (float *)malloc(sizeof(float *)); + float * d_var_72_12; + cudaMalloc((void **)&d_var_72_12, sizeof(float *)); + + float * h_var_72_13 = (float *)malloc(sizeof(float *)); + float * d_var_72_13; + cudaMalloc((void **)&d_var_72_13, sizeof(float *)); + + float * h_var_72_14 = (float *)malloc(sizeof(float *)); + float * d_var_72_14; + cudaMalloc((void **)&d_var_72_14, sizeof(float *)); + + float * h_var_72_15 = (float *)malloc(sizeof(float *)); + float * d_var_72_15; + cudaMalloc((void **)&d_var_72_15, sizeof(float *)); + + float * h_var_72_16 = (float *)malloc(sizeof(float *)); + float * d_var_72_16; + cudaMalloc((void **)&d_var_72_16, sizeof(float *)); + + float * h_var_72_17 = (float *)malloc(sizeof(float *)); + float * d_var_72_17; + cudaMalloc((void **)&d_var_72_17, sizeof(float *)); + + float * h_var_72_18 = (float *)malloc(sizeof(float *)); + float * d_var_72_18; + cudaMalloc((void **)&d_var_72_18, sizeof(float *)); + + float * h_var_72_19 = (float *)malloc(sizeof(float *)); + float * d_var_72_19; + cudaMalloc((void **)&d_var_72_19, sizeof(float *)); + + float * h_var_73_0 = (float *)malloc(sizeof(float *)); + float * d_var_73_0; + cudaMalloc((void **)&d_var_73_0, sizeof(float *)); + + float * h_var_73_1 = (float *)malloc(sizeof(float *)); + float * d_var_73_1; + cudaMalloc((void **)&d_var_73_1, sizeof(float *)); + + float * h_var_73_2 = (float *)malloc(sizeof(float *)); + float * d_var_73_2; + cudaMalloc((void **)&d_var_73_2, sizeof(float *)); + + float * h_var_73_3 = (float *)malloc(sizeof(float *)); + float * d_var_73_3; + cudaMalloc((void **)&d_var_73_3, sizeof(float *)); + + float * h_var_73_4 = (float *)malloc(sizeof(float *)); + float * d_var_73_4; + cudaMalloc((void **)&d_var_73_4, sizeof(float *)); + + float * h_var_73_5 = (float *)malloc(sizeof(float *)); + float * d_var_73_5; + cudaMalloc((void **)&d_var_73_5, sizeof(float *)); + + float * h_var_73_6 = (float *)malloc(sizeof(float *)); + float * d_var_73_6; + cudaMalloc((void **)&d_var_73_6, sizeof(float *)); + + float * h_var_73_7 = (float *)malloc(sizeof(float *)); + float * d_var_73_7; + cudaMalloc((void **)&d_var_73_7, sizeof(float *)); + + float * h_var_73_8 = (float *)malloc(sizeof(float *)); + float * d_var_73_8; + cudaMalloc((void **)&d_var_73_8, sizeof(float *)); + + float * h_var_73_9 = (float *)malloc(sizeof(float *)); + float * d_var_73_9; + cudaMalloc((void **)&d_var_73_9, sizeof(float *)); + + float * h_var_73_10 = (float *)malloc(sizeof(float *)); + float * d_var_73_10; + cudaMalloc((void **)&d_var_73_10, sizeof(float *)); + + float * h_var_73_11 = (float *)malloc(sizeof(float *)); + float * d_var_73_11; + cudaMalloc((void **)&d_var_73_11, sizeof(float *)); + + float * h_var_73_12 = (float *)malloc(sizeof(float *)); + float * d_var_73_12; + cudaMalloc((void **)&d_var_73_12, sizeof(float *)); + + float * h_var_73_13 = (float *)malloc(sizeof(float *)); + float * d_var_73_13; + cudaMalloc((void **)&d_var_73_13, sizeof(float *)); + + float * h_var_73_14 = (float *)malloc(sizeof(float *)); + float * d_var_73_14; + cudaMalloc((void **)&d_var_73_14, sizeof(float *)); + + float * h_var_73_15 = (float *)malloc(sizeof(float *)); + float * d_var_73_15; + cudaMalloc((void **)&d_var_73_15, sizeof(float *)); + + float * h_var_73_16 = (float *)malloc(sizeof(float *)); + float * d_var_73_16; + cudaMalloc((void **)&d_var_73_16, sizeof(float *)); + + float * h_var_73_17 = (float *)malloc(sizeof(float *)); + float * d_var_73_17; + cudaMalloc((void **)&d_var_73_17, sizeof(float *)); + + float * h_var_73_18 = (float *)malloc(sizeof(float *)); + float * d_var_73_18; + cudaMalloc((void **)&d_var_73_18, sizeof(float *)); + + float * h_var_73_19 = (float *)malloc(sizeof(float *)); + float * d_var_73_19; + cudaMalloc((void **)&d_var_73_19, sizeof(float *)); + + float * h_var_74_0 = (float *)malloc(sizeof(float *)); + float * d_var_74_0; + cudaMalloc((void **)&d_var_74_0, sizeof(float *)); + + float * h_var_74_1 = (float *)malloc(sizeof(float *)); + float * d_var_74_1; + cudaMalloc((void **)&d_var_74_1, sizeof(float *)); + + float * h_var_74_2 = (float *)malloc(sizeof(float *)); + float * d_var_74_2; + cudaMalloc((void **)&d_var_74_2, sizeof(float *)); + + float * h_var_74_3 = (float *)malloc(sizeof(float *)); + float * d_var_74_3; + cudaMalloc((void **)&d_var_74_3, sizeof(float *)); + + float * h_var_74_4 = (float *)malloc(sizeof(float *)); + float * d_var_74_4; + cudaMalloc((void **)&d_var_74_4, sizeof(float *)); + + float * h_var_74_5 = (float *)malloc(sizeof(float *)); + float * d_var_74_5; + cudaMalloc((void **)&d_var_74_5, sizeof(float *)); + + float * h_var_74_6 = (float *)malloc(sizeof(float *)); + float * d_var_74_6; + cudaMalloc((void **)&d_var_74_6, sizeof(float *)); + + float * h_var_74_7 = (float *)malloc(sizeof(float *)); + float * d_var_74_7; + cudaMalloc((void **)&d_var_74_7, sizeof(float *)); + + float * h_var_74_8 = (float *)malloc(sizeof(float *)); + float * d_var_74_8; + cudaMalloc((void **)&d_var_74_8, sizeof(float *)); + + float * h_var_74_9 = (float *)malloc(sizeof(float *)); + float * d_var_74_9; + cudaMalloc((void **)&d_var_74_9, sizeof(float *)); + + float * h_var_74_10 = (float *)malloc(sizeof(float *)); + float * d_var_74_10; + cudaMalloc((void **)&d_var_74_10, sizeof(float *)); + + float * h_var_74_11 = (float *)malloc(sizeof(float *)); + float * d_var_74_11; + cudaMalloc((void **)&d_var_74_11, sizeof(float *)); + + float * h_var_74_12 = (float *)malloc(sizeof(float *)); + float * d_var_74_12; + cudaMalloc((void **)&d_var_74_12, sizeof(float *)); + + float * h_var_74_13 = (float *)malloc(sizeof(float *)); + float * d_var_74_13; + cudaMalloc((void **)&d_var_74_13, sizeof(float *)); + + float * h_var_74_14 = (float *)malloc(sizeof(float *)); + float * d_var_74_14; + cudaMalloc((void **)&d_var_74_14, sizeof(float *)); + + float * h_var_74_15 = (float *)malloc(sizeof(float *)); + float * d_var_74_15; + cudaMalloc((void **)&d_var_74_15, sizeof(float *)); + + float * h_var_74_16 = (float *)malloc(sizeof(float *)); + float * d_var_74_16; + cudaMalloc((void **)&d_var_74_16, sizeof(float *)); + + float * h_var_74_17 = (float *)malloc(sizeof(float *)); + float * d_var_74_17; + cudaMalloc((void **)&d_var_74_17, sizeof(float *)); + + float * h_var_74_18 = (float *)malloc(sizeof(float *)); + float * d_var_74_18; + cudaMalloc((void **)&d_var_74_18, sizeof(float *)); + + float * h_var_74_19 = (float *)malloc(sizeof(float *)); + float * d_var_74_19; + cudaMalloc((void **)&d_var_74_19, sizeof(float *)); + + float * h_var_75_0 = (float *)malloc(sizeof(float *)); + float * d_var_75_0; + cudaMalloc((void **)&d_var_75_0, sizeof(float *)); + + float * h_var_75_1 = (float *)malloc(sizeof(float *)); + float * d_var_75_1; + cudaMalloc((void **)&d_var_75_1, sizeof(float *)); + + float * h_var_75_2 = (float *)malloc(sizeof(float *)); + float * d_var_75_2; + cudaMalloc((void **)&d_var_75_2, sizeof(float *)); + + float * h_var_75_3 = (float *)malloc(sizeof(float *)); + float * d_var_75_3; + cudaMalloc((void **)&d_var_75_3, sizeof(float *)); + + float * h_var_75_4 = (float *)malloc(sizeof(float *)); + float * d_var_75_4; + cudaMalloc((void **)&d_var_75_4, sizeof(float *)); + + float * h_var_75_5 = (float *)malloc(sizeof(float *)); + float * d_var_75_5; + cudaMalloc((void **)&d_var_75_5, sizeof(float *)); + + float * h_var_75_6 = (float *)malloc(sizeof(float *)); + float * d_var_75_6; + cudaMalloc((void **)&d_var_75_6, sizeof(float *)); + + float * h_var_75_7 = (float *)malloc(sizeof(float *)); + float * d_var_75_7; + cudaMalloc((void **)&d_var_75_7, sizeof(float *)); + + float * h_var_75_8 = (float *)malloc(sizeof(float *)); + float * d_var_75_8; + cudaMalloc((void **)&d_var_75_8, sizeof(float *)); + + float * h_var_75_9 = (float *)malloc(sizeof(float *)); + float * d_var_75_9; + cudaMalloc((void **)&d_var_75_9, sizeof(float *)); + + float * h_var_75_10 = (float *)malloc(sizeof(float *)); + float * d_var_75_10; + cudaMalloc((void **)&d_var_75_10, sizeof(float *)); + + float * h_var_75_11 = (float *)malloc(sizeof(float *)); + float * d_var_75_11; + cudaMalloc((void **)&d_var_75_11, sizeof(float *)); + + float * h_var_75_12 = (float *)malloc(sizeof(float *)); + float * d_var_75_12; + cudaMalloc((void **)&d_var_75_12, sizeof(float *)); + + float * h_var_75_13 = (float *)malloc(sizeof(float *)); + float * d_var_75_13; + cudaMalloc((void **)&d_var_75_13, sizeof(float *)); + + float * h_var_75_14 = (float *)malloc(sizeof(float *)); + float * d_var_75_14; + cudaMalloc((void **)&d_var_75_14, sizeof(float *)); + + float * h_var_75_15 = (float *)malloc(sizeof(float *)); + float * d_var_75_15; + cudaMalloc((void **)&d_var_75_15, sizeof(float *)); + + float * h_var_75_16 = (float *)malloc(sizeof(float *)); + float * d_var_75_16; + cudaMalloc((void **)&d_var_75_16, sizeof(float *)); + + float * h_var_75_17 = (float *)malloc(sizeof(float *)); + float * d_var_75_17; + cudaMalloc((void **)&d_var_75_17, sizeof(float *)); + + float * h_var_75_18 = (float *)malloc(sizeof(float *)); + float * d_var_75_18; + cudaMalloc((void **)&d_var_75_18, sizeof(float *)); + + float * h_var_75_19 = (float *)malloc(sizeof(float *)); + float * d_var_75_19; + cudaMalloc((void **)&d_var_75_19, sizeof(float *)); + + float * h_var_76_0 = (float *)malloc(sizeof(float *)); + float * d_var_76_0; + cudaMalloc((void **)&d_var_76_0, sizeof(float *)); + + float * h_var_76_1 = (float *)malloc(sizeof(float *)); + float * d_var_76_1; + cudaMalloc((void **)&d_var_76_1, sizeof(float *)); + + float * h_var_76_2 = (float *)malloc(sizeof(float *)); + float * d_var_76_2; + cudaMalloc((void **)&d_var_76_2, sizeof(float *)); + + float * h_var_76_3 = (float *)malloc(sizeof(float *)); + float * d_var_76_3; + cudaMalloc((void **)&d_var_76_3, sizeof(float *)); + + float * h_var_76_4 = (float *)malloc(sizeof(float *)); + float * d_var_76_4; + cudaMalloc((void **)&d_var_76_4, sizeof(float *)); + + float * h_var_76_5 = (float *)malloc(sizeof(float *)); + float * d_var_76_5; + cudaMalloc((void **)&d_var_76_5, sizeof(float *)); + + float * h_var_76_6 = (float *)malloc(sizeof(float *)); + float * d_var_76_6; + cudaMalloc((void **)&d_var_76_6, sizeof(float *)); + + float * h_var_76_7 = (float *)malloc(sizeof(float *)); + float * d_var_76_7; + cudaMalloc((void **)&d_var_76_7, sizeof(float *)); + + float * h_var_76_8 = (float *)malloc(sizeof(float *)); + float * d_var_76_8; + cudaMalloc((void **)&d_var_76_8, sizeof(float *)); + + float * h_var_76_9 = (float *)malloc(sizeof(float *)); + float * d_var_76_9; + cudaMalloc((void **)&d_var_76_9, sizeof(float *)); + + float * h_var_76_10 = (float *)malloc(sizeof(float *)); + float * d_var_76_10; + cudaMalloc((void **)&d_var_76_10, sizeof(float *)); + + float * h_var_76_11 = (float *)malloc(sizeof(float *)); + float * d_var_76_11; + cudaMalloc((void **)&d_var_76_11, sizeof(float *)); + + float * h_var_76_12 = (float *)malloc(sizeof(float *)); + float * d_var_76_12; + cudaMalloc((void **)&d_var_76_12, sizeof(float *)); + + float * h_var_76_13 = (float *)malloc(sizeof(float *)); + float * d_var_76_13; + cudaMalloc((void **)&d_var_76_13, sizeof(float *)); + + float * h_var_76_14 = (float *)malloc(sizeof(float *)); + float * d_var_76_14; + cudaMalloc((void **)&d_var_76_14, sizeof(float *)); + + float * h_var_76_15 = (float *)malloc(sizeof(float *)); + float * d_var_76_15; + cudaMalloc((void **)&d_var_76_15, sizeof(float *)); + + float * h_var_76_16 = (float *)malloc(sizeof(float *)); + float * d_var_76_16; + cudaMalloc((void **)&d_var_76_16, sizeof(float *)); + + float * h_var_76_17 = (float *)malloc(sizeof(float *)); + float * d_var_76_17; + cudaMalloc((void **)&d_var_76_17, sizeof(float *)); + + float * h_var_76_18 = (float *)malloc(sizeof(float *)); + float * d_var_76_18; + cudaMalloc((void **)&d_var_76_18, sizeof(float *)); + + float * h_var_76_19 = (float *)malloc(sizeof(float *)); + float * d_var_76_19; + cudaMalloc((void **)&d_var_76_19, sizeof(float *)); + + float * h_var_77_0 = (float *)malloc(sizeof(float *)); + float * d_var_77_0; + cudaMalloc((void **)&d_var_77_0, sizeof(float *)); + + float * h_var_77_1 = (float *)malloc(sizeof(float *)); + float * d_var_77_1; + cudaMalloc((void **)&d_var_77_1, sizeof(float *)); + + float * h_var_77_2 = (float *)malloc(sizeof(float *)); + float * d_var_77_2; + cudaMalloc((void **)&d_var_77_2, sizeof(float *)); + + float * h_var_77_3 = (float *)malloc(sizeof(float *)); + float * d_var_77_3; + cudaMalloc((void **)&d_var_77_3, sizeof(float *)); + + float * h_var_77_4 = (float *)malloc(sizeof(float *)); + float * d_var_77_4; + cudaMalloc((void **)&d_var_77_4, sizeof(float *)); + + float * h_var_77_5 = (float *)malloc(sizeof(float *)); + float * d_var_77_5; + cudaMalloc((void **)&d_var_77_5, sizeof(float *)); + + float * h_var_77_6 = (float *)malloc(sizeof(float *)); + float * d_var_77_6; + cudaMalloc((void **)&d_var_77_6, sizeof(float *)); + + float * h_var_77_7 = (float *)malloc(sizeof(float *)); + float * d_var_77_7; + cudaMalloc((void **)&d_var_77_7, sizeof(float *)); + + float * h_var_77_8 = (float *)malloc(sizeof(float *)); + float * d_var_77_8; + cudaMalloc((void **)&d_var_77_8, sizeof(float *)); + + float * h_var_77_9 = (float *)malloc(sizeof(float *)); + float * d_var_77_9; + cudaMalloc((void **)&d_var_77_9, sizeof(float *)); + + float * h_var_77_10 = (float *)malloc(sizeof(float *)); + float * d_var_77_10; + cudaMalloc((void **)&d_var_77_10, sizeof(float *)); + + float * h_var_77_11 = (float *)malloc(sizeof(float *)); + float * d_var_77_11; + cudaMalloc((void **)&d_var_77_11, sizeof(float *)); + + float * h_var_77_12 = (float *)malloc(sizeof(float *)); + float * d_var_77_12; + cudaMalloc((void **)&d_var_77_12, sizeof(float *)); + + float * h_var_77_13 = (float *)malloc(sizeof(float *)); + float * d_var_77_13; + cudaMalloc((void **)&d_var_77_13, sizeof(float *)); + + float * h_var_77_14 = (float *)malloc(sizeof(float *)); + float * d_var_77_14; + cudaMalloc((void **)&d_var_77_14, sizeof(float *)); + + float * h_var_77_15 = (float *)malloc(sizeof(float *)); + float * d_var_77_15; + cudaMalloc((void **)&d_var_77_15, sizeof(float *)); + + float * h_var_77_16 = (float *)malloc(sizeof(float *)); + float * d_var_77_16; + cudaMalloc((void **)&d_var_77_16, sizeof(float *)); + + float * h_var_77_17 = (float *)malloc(sizeof(float *)); + float * d_var_77_17; + cudaMalloc((void **)&d_var_77_17, sizeof(float *)); + + float * h_var_77_18 = (float *)malloc(sizeof(float *)); + float * d_var_77_18; + cudaMalloc((void **)&d_var_77_18, sizeof(float *)); + + float * h_var_77_19 = (float *)malloc(sizeof(float *)); + float * d_var_77_19; + cudaMalloc((void **)&d_var_77_19, sizeof(float *)); + + float * h_var_78_0 = (float *)malloc(sizeof(float *)); + float * d_var_78_0; + cudaMalloc((void **)&d_var_78_0, sizeof(float *)); + + float * h_var_78_1 = (float *)malloc(sizeof(float *)); + float * d_var_78_1; + cudaMalloc((void **)&d_var_78_1, sizeof(float *)); + + float * h_var_78_2 = (float *)malloc(sizeof(float *)); + float * d_var_78_2; + cudaMalloc((void **)&d_var_78_2, sizeof(float *)); + + float * h_var_78_3 = (float *)malloc(sizeof(float *)); + float * d_var_78_3; + cudaMalloc((void **)&d_var_78_3, sizeof(float *)); + + float * h_var_78_4 = (float *)malloc(sizeof(float *)); + float * d_var_78_4; + cudaMalloc((void **)&d_var_78_4, sizeof(float *)); + + float * h_var_78_5 = (float *)malloc(sizeof(float *)); + float * d_var_78_5; + cudaMalloc((void **)&d_var_78_5, sizeof(float *)); + + float * h_var_78_6 = (float *)malloc(sizeof(float *)); + float * d_var_78_6; + cudaMalloc((void **)&d_var_78_6, sizeof(float *)); + + float * h_var_78_7 = (float *)malloc(sizeof(float *)); + float * d_var_78_7; + cudaMalloc((void **)&d_var_78_7, sizeof(float *)); + + float * h_var_78_8 = (float *)malloc(sizeof(float *)); + float * d_var_78_8; + cudaMalloc((void **)&d_var_78_8, sizeof(float *)); + + float * h_var_78_9 = (float *)malloc(sizeof(float *)); + float * d_var_78_9; + cudaMalloc((void **)&d_var_78_9, sizeof(float *)); + + float * h_var_78_10 = (float *)malloc(sizeof(float *)); + float * d_var_78_10; + cudaMalloc((void **)&d_var_78_10, sizeof(float *)); + + float * h_var_78_11 = (float *)malloc(sizeof(float *)); + float * d_var_78_11; + cudaMalloc((void **)&d_var_78_11, sizeof(float *)); + + float * h_var_78_12 = (float *)malloc(sizeof(float *)); + float * d_var_78_12; + cudaMalloc((void **)&d_var_78_12, sizeof(float *)); + + float * h_var_78_13 = (float *)malloc(sizeof(float *)); + float * d_var_78_13; + cudaMalloc((void **)&d_var_78_13, sizeof(float *)); + + float * h_var_78_14 = (float *)malloc(sizeof(float *)); + float * d_var_78_14; + cudaMalloc((void **)&d_var_78_14, sizeof(float *)); + + float * h_var_78_15 = (float *)malloc(sizeof(float *)); + float * d_var_78_15; + cudaMalloc((void **)&d_var_78_15, sizeof(float *)); + + float * h_var_78_16 = (float *)malloc(sizeof(float *)); + float * d_var_78_16; + cudaMalloc((void **)&d_var_78_16, sizeof(float *)); + + float * h_var_78_17 = (float *)malloc(sizeof(float *)); + float * d_var_78_17; + cudaMalloc((void **)&d_var_78_17, sizeof(float *)); + + float * h_var_78_18 = (float *)malloc(sizeof(float *)); + float * d_var_78_18; + cudaMalloc((void **)&d_var_78_18, sizeof(float *)); + + float * h_var_78_19 = (float *)malloc(sizeof(float *)); + float * d_var_78_19; + cudaMalloc((void **)&d_var_78_19, sizeof(float *)); + + float * h_var_79_0 = (float *)malloc(sizeof(float *)); + float * d_var_79_0; + cudaMalloc((void **)&d_var_79_0, sizeof(float *)); + + float * h_var_79_1 = (float *)malloc(sizeof(float *)); + float * d_var_79_1; + cudaMalloc((void **)&d_var_79_1, sizeof(float *)); + + float * h_var_79_2 = (float *)malloc(sizeof(float *)); + float * d_var_79_2; + cudaMalloc((void **)&d_var_79_2, sizeof(float *)); + + float * h_var_79_3 = (float *)malloc(sizeof(float *)); + float * d_var_79_3; + cudaMalloc((void **)&d_var_79_3, sizeof(float *)); + + float * h_var_79_4 = (float *)malloc(sizeof(float *)); + float * d_var_79_4; + cudaMalloc((void **)&d_var_79_4, sizeof(float *)); + + float * h_var_79_5 = (float *)malloc(sizeof(float *)); + float * d_var_79_5; + cudaMalloc((void **)&d_var_79_5, sizeof(float *)); + + float * h_var_79_6 = (float *)malloc(sizeof(float *)); + float * d_var_79_6; + cudaMalloc((void **)&d_var_79_6, sizeof(float *)); + + float * h_var_79_7 = (float *)malloc(sizeof(float *)); + float * d_var_79_7; + cudaMalloc((void **)&d_var_79_7, sizeof(float *)); + + float * h_var_79_8 = (float *)malloc(sizeof(float *)); + float * d_var_79_8; + cudaMalloc((void **)&d_var_79_8, sizeof(float *)); + + float * h_var_79_9 = (float *)malloc(sizeof(float *)); + float * d_var_79_9; + cudaMalloc((void **)&d_var_79_9, sizeof(float *)); + + float * h_var_79_10 = (float *)malloc(sizeof(float *)); + float * d_var_79_10; + cudaMalloc((void **)&d_var_79_10, sizeof(float *)); + + float * h_var_79_11 = (float *)malloc(sizeof(float *)); + float * d_var_79_11; + cudaMalloc((void **)&d_var_79_11, sizeof(float *)); + + float * h_var_79_12 = (float *)malloc(sizeof(float *)); + float * d_var_79_12; + cudaMalloc((void **)&d_var_79_12, sizeof(float *)); + + float * h_var_79_13 = (float *)malloc(sizeof(float *)); + float * d_var_79_13; + cudaMalloc((void **)&d_var_79_13, sizeof(float *)); + + float * h_var_79_14 = (float *)malloc(sizeof(float *)); + float * d_var_79_14; + cudaMalloc((void **)&d_var_79_14, sizeof(float *)); + + float * h_var_79_15 = (float *)malloc(sizeof(float *)); + float * d_var_79_15; + cudaMalloc((void **)&d_var_79_15, sizeof(float *)); + + float * h_var_79_16 = (float *)malloc(sizeof(float *)); + float * d_var_79_16; + cudaMalloc((void **)&d_var_79_16, sizeof(float *)); + + float * h_var_79_17 = (float *)malloc(sizeof(float *)); + float * d_var_79_17; + cudaMalloc((void **)&d_var_79_17, sizeof(float *)); + + float * h_var_79_18 = (float *)malloc(sizeof(float *)); + float * d_var_79_18; + cudaMalloc((void **)&d_var_79_18, sizeof(float *)); + + float * h_var_79_19 = (float *)malloc(sizeof(float *)); + float * d_var_79_19; + cudaMalloc((void **)&d_var_79_19, sizeof(float *)); + + float * h_var_80_0 = (float *)malloc(sizeof(float *)); + float * d_var_80_0; + cudaMalloc((void **)&d_var_80_0, sizeof(float *)); + + float * h_var_80_1 = (float *)malloc(sizeof(float *)); + float * d_var_80_1; + cudaMalloc((void **)&d_var_80_1, sizeof(float *)); + + float * h_var_80_2 = (float *)malloc(sizeof(float *)); + float * d_var_80_2; + cudaMalloc((void **)&d_var_80_2, sizeof(float *)); + + float * h_var_80_3 = (float *)malloc(sizeof(float *)); + float * d_var_80_3; + cudaMalloc((void **)&d_var_80_3, sizeof(float *)); + + float * h_var_80_4 = (float *)malloc(sizeof(float *)); + float * d_var_80_4; + cudaMalloc((void **)&d_var_80_4, sizeof(float *)); + + float * h_var_80_5 = (float *)malloc(sizeof(float *)); + float * d_var_80_5; + cudaMalloc((void **)&d_var_80_5, sizeof(float *)); + + float * h_var_80_6 = (float *)malloc(sizeof(float *)); + float * d_var_80_6; + cudaMalloc((void **)&d_var_80_6, sizeof(float *)); + + float * h_var_80_7 = (float *)malloc(sizeof(float *)); + float * d_var_80_7; + cudaMalloc((void **)&d_var_80_7, sizeof(float *)); + + float * h_var_80_8 = (float *)malloc(sizeof(float *)); + float * d_var_80_8; + cudaMalloc((void **)&d_var_80_8, sizeof(float *)); + + float * h_var_80_9 = (float *)malloc(sizeof(float *)); + float * d_var_80_9; + cudaMalloc((void **)&d_var_80_9, sizeof(float *)); + + float * h_var_80_10 = (float *)malloc(sizeof(float *)); + float * d_var_80_10; + cudaMalloc((void **)&d_var_80_10, sizeof(float *)); + + float * h_var_80_11 = (float *)malloc(sizeof(float *)); + float * d_var_80_11; + cudaMalloc((void **)&d_var_80_11, sizeof(float *)); + + float * h_var_80_12 = (float *)malloc(sizeof(float *)); + float * d_var_80_12; + cudaMalloc((void **)&d_var_80_12, sizeof(float *)); + + float * h_var_80_13 = (float *)malloc(sizeof(float *)); + float * d_var_80_13; + cudaMalloc((void **)&d_var_80_13, sizeof(float *)); + + float * h_var_80_14 = (float *)malloc(sizeof(float *)); + float * d_var_80_14; + cudaMalloc((void **)&d_var_80_14, sizeof(float *)); + + float * h_var_80_15 = (float *)malloc(sizeof(float *)); + float * d_var_80_15; + cudaMalloc((void **)&d_var_80_15, sizeof(float *)); + + float * h_var_80_16 = (float *)malloc(sizeof(float *)); + float * d_var_80_16; + cudaMalloc((void **)&d_var_80_16, sizeof(float *)); + + float * h_var_80_17 = (float *)malloc(sizeof(float *)); + float * d_var_80_17; + cudaMalloc((void **)&d_var_80_17, sizeof(float *)); + + float * h_var_80_18 = (float *)malloc(sizeof(float *)); + float * d_var_80_18; + cudaMalloc((void **)&d_var_80_18, sizeof(float *)); + + float * h_var_80_19 = (float *)malloc(sizeof(float *)); + float * d_var_80_19; + cudaMalloc((void **)&d_var_80_19, sizeof(float *)); + + float * h_var_81_0 = (float *)malloc(sizeof(float *)); + float * d_var_81_0; + cudaMalloc((void **)&d_var_81_0, sizeof(float *)); + + float * h_var_81_1 = (float *)malloc(sizeof(float *)); + float * d_var_81_1; + cudaMalloc((void **)&d_var_81_1, sizeof(float *)); + + float * h_var_81_2 = (float *)malloc(sizeof(float *)); + float * d_var_81_2; + cudaMalloc((void **)&d_var_81_2, sizeof(float *)); + + float * h_var_81_3 = (float *)malloc(sizeof(float *)); + float * d_var_81_3; + cudaMalloc((void **)&d_var_81_3, sizeof(float *)); + + float * h_var_81_4 = (float *)malloc(sizeof(float *)); + float * d_var_81_4; + cudaMalloc((void **)&d_var_81_4, sizeof(float *)); + + float * h_var_81_5 = (float *)malloc(sizeof(float *)); + float * d_var_81_5; + cudaMalloc((void **)&d_var_81_5, sizeof(float *)); + + float * h_var_81_6 = (float *)malloc(sizeof(float *)); + float * d_var_81_6; + cudaMalloc((void **)&d_var_81_6, sizeof(float *)); + + float * h_var_81_7 = (float *)malloc(sizeof(float *)); + float * d_var_81_7; + cudaMalloc((void **)&d_var_81_7, sizeof(float *)); + + float * h_var_81_8 = (float *)malloc(sizeof(float *)); + float * d_var_81_8; + cudaMalloc((void **)&d_var_81_8, sizeof(float *)); + + float * h_var_81_9 = (float *)malloc(sizeof(float *)); + float * d_var_81_9; + cudaMalloc((void **)&d_var_81_9, sizeof(float *)); + + float * h_var_81_10 = (float *)malloc(sizeof(float *)); + float * d_var_81_10; + cudaMalloc((void **)&d_var_81_10, sizeof(float *)); + + float * h_var_81_11 = (float *)malloc(sizeof(float *)); + float * d_var_81_11; + cudaMalloc((void **)&d_var_81_11, sizeof(float *)); + + float * h_var_81_12 = (float *)malloc(sizeof(float *)); + float * d_var_81_12; + cudaMalloc((void **)&d_var_81_12, sizeof(float *)); + + float * h_var_81_13 = (float *)malloc(sizeof(float *)); + float * d_var_81_13; + cudaMalloc((void **)&d_var_81_13, sizeof(float *)); + + float * h_var_81_14 = (float *)malloc(sizeof(float *)); + float * d_var_81_14; + cudaMalloc((void **)&d_var_81_14, sizeof(float *)); + + float * h_var_81_15 = (float *)malloc(sizeof(float *)); + float * d_var_81_15; + cudaMalloc((void **)&d_var_81_15, sizeof(float *)); + + float * h_var_81_16 = (float *)malloc(sizeof(float *)); + float * d_var_81_16; + cudaMalloc((void **)&d_var_81_16, sizeof(float *)); + + float * h_var_81_17 = (float *)malloc(sizeof(float *)); + float * d_var_81_17; + cudaMalloc((void **)&d_var_81_17, sizeof(float *)); + + float * h_var_81_18 = (float *)malloc(sizeof(float *)); + float * d_var_81_18; + cudaMalloc((void **)&d_var_81_18, sizeof(float *)); + + float * h_var_81_19 = (float *)malloc(sizeof(float *)); + float * d_var_81_19; + cudaMalloc((void **)&d_var_81_19, sizeof(float *)); + + float * h_var_82_0 = (float *)malloc(sizeof(float *)); + float * d_var_82_0; + cudaMalloc((void **)&d_var_82_0, sizeof(float *)); + + float * h_var_82_1 = (float *)malloc(sizeof(float *)); + float * d_var_82_1; + cudaMalloc((void **)&d_var_82_1, sizeof(float *)); + + float * h_var_82_2 = (float *)malloc(sizeof(float *)); + float * d_var_82_2; + cudaMalloc((void **)&d_var_82_2, sizeof(float *)); + + float * h_var_82_3 = (float *)malloc(sizeof(float *)); + float * d_var_82_3; + cudaMalloc((void **)&d_var_82_3, sizeof(float *)); + + float * h_var_82_4 = (float *)malloc(sizeof(float *)); + float * d_var_82_4; + cudaMalloc((void **)&d_var_82_4, sizeof(float *)); + + float * h_var_82_5 = (float *)malloc(sizeof(float *)); + float * d_var_82_5; + cudaMalloc((void **)&d_var_82_5, sizeof(float *)); + + float * h_var_82_6 = (float *)malloc(sizeof(float *)); + float * d_var_82_6; + cudaMalloc((void **)&d_var_82_6, sizeof(float *)); + + float * h_var_82_7 = (float *)malloc(sizeof(float *)); + float * d_var_82_7; + cudaMalloc((void **)&d_var_82_7, sizeof(float *)); + + float * h_var_82_8 = (float *)malloc(sizeof(float *)); + float * d_var_82_8; + cudaMalloc((void **)&d_var_82_8, sizeof(float *)); + + float * h_var_82_9 = (float *)malloc(sizeof(float *)); + float * d_var_82_9; + cudaMalloc((void **)&d_var_82_9, sizeof(float *)); + + float * h_var_82_10 = (float *)malloc(sizeof(float *)); + float * d_var_82_10; + cudaMalloc((void **)&d_var_82_10, sizeof(float *)); + + float * h_var_82_11 = (float *)malloc(sizeof(float *)); + float * d_var_82_11; + cudaMalloc((void **)&d_var_82_11, sizeof(float *)); + + float * h_var_82_12 = (float *)malloc(sizeof(float *)); + float * d_var_82_12; + cudaMalloc((void **)&d_var_82_12, sizeof(float *)); + + float * h_var_82_13 = (float *)malloc(sizeof(float *)); + float * d_var_82_13; + cudaMalloc((void **)&d_var_82_13, sizeof(float *)); + + float * h_var_82_14 = (float *)malloc(sizeof(float *)); + float * d_var_82_14; + cudaMalloc((void **)&d_var_82_14, sizeof(float *)); + + float * h_var_82_15 = (float *)malloc(sizeof(float *)); + float * d_var_82_15; + cudaMalloc((void **)&d_var_82_15, sizeof(float *)); + + float * h_var_82_16 = (float *)malloc(sizeof(float *)); + float * d_var_82_16; + cudaMalloc((void **)&d_var_82_16, sizeof(float *)); + + float * h_var_82_17 = (float *)malloc(sizeof(float *)); + float * d_var_82_17; + cudaMalloc((void **)&d_var_82_17, sizeof(float *)); + + float * h_var_82_18 = (float *)malloc(sizeof(float *)); + float * d_var_82_18; + cudaMalloc((void **)&d_var_82_18, sizeof(float *)); + + float * h_var_82_19 = (float *)malloc(sizeof(float *)); + float * d_var_82_19; + cudaMalloc((void **)&d_var_82_19, sizeof(float *)); + + float * h_var_83_0 = (float *)malloc(sizeof(float *)); + float * d_var_83_0; + cudaMalloc((void **)&d_var_83_0, sizeof(float *)); + + float * h_var_83_1 = (float *)malloc(sizeof(float *)); + float * d_var_83_1; + cudaMalloc((void **)&d_var_83_1, sizeof(float *)); + + float * h_var_83_2 = (float *)malloc(sizeof(float *)); + float * d_var_83_2; + cudaMalloc((void **)&d_var_83_2, sizeof(float *)); + + float * h_var_83_3 = (float *)malloc(sizeof(float *)); + float * d_var_83_3; + cudaMalloc((void **)&d_var_83_3, sizeof(float *)); + + float * h_var_83_4 = (float *)malloc(sizeof(float *)); + float * d_var_83_4; + cudaMalloc((void **)&d_var_83_4, sizeof(float *)); + + float * h_var_83_5 = (float *)malloc(sizeof(float *)); + float * d_var_83_5; + cudaMalloc((void **)&d_var_83_5, sizeof(float *)); + + float * h_var_83_6 = (float *)malloc(sizeof(float *)); + float * d_var_83_6; + cudaMalloc((void **)&d_var_83_6, sizeof(float *)); + + float * h_var_83_7 = (float *)malloc(sizeof(float *)); + float * d_var_83_7; + cudaMalloc((void **)&d_var_83_7, sizeof(float *)); + + float * h_var_83_8 = (float *)malloc(sizeof(float *)); + float * d_var_83_8; + cudaMalloc((void **)&d_var_83_8, sizeof(float *)); + + float * h_var_83_9 = (float *)malloc(sizeof(float *)); + float * d_var_83_9; + cudaMalloc((void **)&d_var_83_9, sizeof(float *)); + + float * h_var_83_10 = (float *)malloc(sizeof(float *)); + float * d_var_83_10; + cudaMalloc((void **)&d_var_83_10, sizeof(float *)); + + float * h_var_83_11 = (float *)malloc(sizeof(float *)); + float * d_var_83_11; + cudaMalloc((void **)&d_var_83_11, sizeof(float *)); + + float * h_var_83_12 = (float *)malloc(sizeof(float *)); + float * d_var_83_12; + cudaMalloc((void **)&d_var_83_12, sizeof(float *)); + + float * h_var_83_13 = (float *)malloc(sizeof(float *)); + float * d_var_83_13; + cudaMalloc((void **)&d_var_83_13, sizeof(float *)); + + float * h_var_83_14 = (float *)malloc(sizeof(float *)); + float * d_var_83_14; + cudaMalloc((void **)&d_var_83_14, sizeof(float *)); + + float * h_var_83_15 = (float *)malloc(sizeof(float *)); + float * d_var_83_15; + cudaMalloc((void **)&d_var_83_15, sizeof(float *)); + + float * h_var_83_16 = (float *)malloc(sizeof(float *)); + float * d_var_83_16; + cudaMalloc((void **)&d_var_83_16, sizeof(float *)); + + float * h_var_83_17 = (float *)malloc(sizeof(float *)); + float * d_var_83_17; + cudaMalloc((void **)&d_var_83_17, sizeof(float *)); + + float * h_var_83_18 = (float *)malloc(sizeof(float *)); + float * d_var_83_18; + cudaMalloc((void **)&d_var_83_18, sizeof(float *)); + + float * h_var_83_19 = (float *)malloc(sizeof(float *)); + float * d_var_83_19; + cudaMalloc((void **)&d_var_83_19, sizeof(float *)); + + float * h_var_84_0 = (float *)malloc(sizeof(float *)); + float * d_var_84_0; + cudaMalloc((void **)&d_var_84_0, sizeof(float *)); + + float * h_var_84_1 = (float *)malloc(sizeof(float *)); + float * d_var_84_1; + cudaMalloc((void **)&d_var_84_1, sizeof(float *)); + + float * h_var_84_2 = (float *)malloc(sizeof(float *)); + float * d_var_84_2; + cudaMalloc((void **)&d_var_84_2, sizeof(float *)); + + float * h_var_84_3 = (float *)malloc(sizeof(float *)); + float * d_var_84_3; + cudaMalloc((void **)&d_var_84_3, sizeof(float *)); + + float * h_var_84_4 = (float *)malloc(sizeof(float *)); + float * d_var_84_4; + cudaMalloc((void **)&d_var_84_4, sizeof(float *)); + + float * h_var_84_5 = (float *)malloc(sizeof(float *)); + float * d_var_84_5; + cudaMalloc((void **)&d_var_84_5, sizeof(float *)); + + float * h_var_84_6 = (float *)malloc(sizeof(float *)); + float * d_var_84_6; + cudaMalloc((void **)&d_var_84_6, sizeof(float *)); + + float * h_var_84_7 = (float *)malloc(sizeof(float *)); + float * d_var_84_7; + cudaMalloc((void **)&d_var_84_7, sizeof(float *)); + + float * h_var_84_8 = (float *)malloc(sizeof(float *)); + float * d_var_84_8; + cudaMalloc((void **)&d_var_84_8, sizeof(float *)); + + float * h_var_84_9 = (float *)malloc(sizeof(float *)); + float * d_var_84_9; + cudaMalloc((void **)&d_var_84_9, sizeof(float *)); + + float * h_var_84_10 = (float *)malloc(sizeof(float *)); + float * d_var_84_10; + cudaMalloc((void **)&d_var_84_10, sizeof(float *)); + + float * h_var_84_11 = (float *)malloc(sizeof(float *)); + float * d_var_84_11; + cudaMalloc((void **)&d_var_84_11, sizeof(float *)); + + float * h_var_84_12 = (float *)malloc(sizeof(float *)); + float * d_var_84_12; + cudaMalloc((void **)&d_var_84_12, sizeof(float *)); + + float * h_var_84_13 = (float *)malloc(sizeof(float *)); + float * d_var_84_13; + cudaMalloc((void **)&d_var_84_13, sizeof(float *)); + + float * h_var_84_14 = (float *)malloc(sizeof(float *)); + float * d_var_84_14; + cudaMalloc((void **)&d_var_84_14, sizeof(float *)); + + float * h_var_84_15 = (float *)malloc(sizeof(float *)); + float * d_var_84_15; + cudaMalloc((void **)&d_var_84_15, sizeof(float *)); + + float * h_var_84_16 = (float *)malloc(sizeof(float *)); + float * d_var_84_16; + cudaMalloc((void **)&d_var_84_16, sizeof(float *)); + + float * h_var_84_17 = (float *)malloc(sizeof(float *)); + float * d_var_84_17; + cudaMalloc((void **)&d_var_84_17, sizeof(float *)); + + float * h_var_84_18 = (float *)malloc(sizeof(float *)); + float * d_var_84_18; + cudaMalloc((void **)&d_var_84_18, sizeof(float *)); + + float * h_var_84_19 = (float *)malloc(sizeof(float *)); + float * d_var_84_19; + cudaMalloc((void **)&d_var_84_19, sizeof(float *)); + + float * h_var_85_0 = (float *)malloc(sizeof(float *)); + float * d_var_85_0; + cudaMalloc((void **)&d_var_85_0, sizeof(float *)); + + float * h_var_85_1 = (float *)malloc(sizeof(float *)); + float * d_var_85_1; + cudaMalloc((void **)&d_var_85_1, sizeof(float *)); + + float * h_var_85_2 = (float *)malloc(sizeof(float *)); + float * d_var_85_2; + cudaMalloc((void **)&d_var_85_2, sizeof(float *)); + + float * h_var_85_3 = (float *)malloc(sizeof(float *)); + float * d_var_85_3; + cudaMalloc((void **)&d_var_85_3, sizeof(float *)); + + float * h_var_85_4 = (float *)malloc(sizeof(float *)); + float * d_var_85_4; + cudaMalloc((void **)&d_var_85_4, sizeof(float *)); + + float * h_var_85_5 = (float *)malloc(sizeof(float *)); + float * d_var_85_5; + cudaMalloc((void **)&d_var_85_5, sizeof(float *)); + + float * h_var_85_6 = (float *)malloc(sizeof(float *)); + float * d_var_85_6; + cudaMalloc((void **)&d_var_85_6, sizeof(float *)); + + float * h_var_85_7 = (float *)malloc(sizeof(float *)); + float * d_var_85_7; + cudaMalloc((void **)&d_var_85_7, sizeof(float *)); + + float * h_var_85_8 = (float *)malloc(sizeof(float *)); + float * d_var_85_8; + cudaMalloc((void **)&d_var_85_8, sizeof(float *)); + + float * h_var_85_9 = (float *)malloc(sizeof(float *)); + float * d_var_85_9; + cudaMalloc((void **)&d_var_85_9, sizeof(float *)); + + float * h_var_85_10 = (float *)malloc(sizeof(float *)); + float * d_var_85_10; + cudaMalloc((void **)&d_var_85_10, sizeof(float *)); + + float * h_var_85_11 = (float *)malloc(sizeof(float *)); + float * d_var_85_11; + cudaMalloc((void **)&d_var_85_11, sizeof(float *)); + + float * h_var_85_12 = (float *)malloc(sizeof(float *)); + float * d_var_85_12; + cudaMalloc((void **)&d_var_85_12, sizeof(float *)); + + float * h_var_85_13 = (float *)malloc(sizeof(float *)); + float * d_var_85_13; + cudaMalloc((void **)&d_var_85_13, sizeof(float *)); + + float * h_var_85_14 = (float *)malloc(sizeof(float *)); + float * d_var_85_14; + cudaMalloc((void **)&d_var_85_14, sizeof(float *)); + + float * h_var_85_15 = (float *)malloc(sizeof(float *)); + float * d_var_85_15; + cudaMalloc((void **)&d_var_85_15, sizeof(float *)); + + float * h_var_85_16 = (float *)malloc(sizeof(float *)); + float * d_var_85_16; + cudaMalloc((void **)&d_var_85_16, sizeof(float *)); + + float * h_var_85_17 = (float *)malloc(sizeof(float *)); + float * d_var_85_17; + cudaMalloc((void **)&d_var_85_17, sizeof(float *)); + + float * h_var_85_18 = (float *)malloc(sizeof(float *)); + float * d_var_85_18; + cudaMalloc((void **)&d_var_85_18, sizeof(float *)); + + float * h_var_85_19 = (float *)malloc(sizeof(float *)); + float * d_var_85_19; + cudaMalloc((void **)&d_var_85_19, sizeof(float *)); + + float * h_var_86_0 = (float *)malloc(sizeof(float *)); + float * d_var_86_0; + cudaMalloc((void **)&d_var_86_0, sizeof(float *)); + + float * h_var_86_1 = (float *)malloc(sizeof(float *)); + float * d_var_86_1; + cudaMalloc((void **)&d_var_86_1, sizeof(float *)); + + float * h_var_86_2 = (float *)malloc(sizeof(float *)); + float * d_var_86_2; + cudaMalloc((void **)&d_var_86_2, sizeof(float *)); + + float * h_var_86_3 = (float *)malloc(sizeof(float *)); + float * d_var_86_3; + cudaMalloc((void **)&d_var_86_3, sizeof(float *)); + + float * h_var_86_4 = (float *)malloc(sizeof(float *)); + float * d_var_86_4; + cudaMalloc((void **)&d_var_86_4, sizeof(float *)); + + float * h_var_86_5 = (float *)malloc(sizeof(float *)); + float * d_var_86_5; + cudaMalloc((void **)&d_var_86_5, sizeof(float *)); + + float * h_var_86_6 = (float *)malloc(sizeof(float *)); + float * d_var_86_6; + cudaMalloc((void **)&d_var_86_6, sizeof(float *)); + + float * h_var_86_7 = (float *)malloc(sizeof(float *)); + float * d_var_86_7; + cudaMalloc((void **)&d_var_86_7, sizeof(float *)); + + float * h_var_86_8 = (float *)malloc(sizeof(float *)); + float * d_var_86_8; + cudaMalloc((void **)&d_var_86_8, sizeof(float *)); + + float * h_var_86_9 = (float *)malloc(sizeof(float *)); + float * d_var_86_9; + cudaMalloc((void **)&d_var_86_9, sizeof(float *)); + + float * h_var_86_10 = (float *)malloc(sizeof(float *)); + float * d_var_86_10; + cudaMalloc((void **)&d_var_86_10, sizeof(float *)); + + float * h_var_86_11 = (float *)malloc(sizeof(float *)); + float * d_var_86_11; + cudaMalloc((void **)&d_var_86_11, sizeof(float *)); + + float * h_var_86_12 = (float *)malloc(sizeof(float *)); + float * d_var_86_12; + cudaMalloc((void **)&d_var_86_12, sizeof(float *)); + + float * h_var_86_13 = (float *)malloc(sizeof(float *)); + float * d_var_86_13; + cudaMalloc((void **)&d_var_86_13, sizeof(float *)); + + float * h_var_86_14 = (float *)malloc(sizeof(float *)); + float * d_var_86_14; + cudaMalloc((void **)&d_var_86_14, sizeof(float *)); + + float * h_var_86_15 = (float *)malloc(sizeof(float *)); + float * d_var_86_15; + cudaMalloc((void **)&d_var_86_15, sizeof(float *)); + + float * h_var_86_16 = (float *)malloc(sizeof(float *)); + float * d_var_86_16; + cudaMalloc((void **)&d_var_86_16, sizeof(float *)); + + float * h_var_86_17 = (float *)malloc(sizeof(float *)); + float * d_var_86_17; + cudaMalloc((void **)&d_var_86_17, sizeof(float *)); + + float * h_var_86_18 = (float *)malloc(sizeof(float *)); + float * d_var_86_18; + cudaMalloc((void **)&d_var_86_18, sizeof(float *)); + + float * h_var_86_19 = (float *)malloc(sizeof(float *)); + float * d_var_86_19; + cudaMalloc((void **)&d_var_86_19, sizeof(float *)); + + float * h_var_87_0 = (float *)malloc(sizeof(float *)); + float * d_var_87_0; + cudaMalloc((void **)&d_var_87_0, sizeof(float *)); + + float * h_var_87_1 = (float *)malloc(sizeof(float *)); + float * d_var_87_1; + cudaMalloc((void **)&d_var_87_1, sizeof(float *)); + + float * h_var_87_2 = (float *)malloc(sizeof(float *)); + float * d_var_87_2; + cudaMalloc((void **)&d_var_87_2, sizeof(float *)); + + float * h_var_87_3 = (float *)malloc(sizeof(float *)); + float * d_var_87_3; + cudaMalloc((void **)&d_var_87_3, sizeof(float *)); + + float * h_var_87_4 = (float *)malloc(sizeof(float *)); + float * d_var_87_4; + cudaMalloc((void **)&d_var_87_4, sizeof(float *)); + + float * h_var_87_5 = (float *)malloc(sizeof(float *)); + float * d_var_87_5; + cudaMalloc((void **)&d_var_87_5, sizeof(float *)); + + float * h_var_87_6 = (float *)malloc(sizeof(float *)); + float * d_var_87_6; + cudaMalloc((void **)&d_var_87_6, sizeof(float *)); + + float * h_var_87_7 = (float *)malloc(sizeof(float *)); + float * d_var_87_7; + cudaMalloc((void **)&d_var_87_7, sizeof(float *)); + + float * h_var_87_8 = (float *)malloc(sizeof(float *)); + float * d_var_87_8; + cudaMalloc((void **)&d_var_87_8, sizeof(float *)); + + float * h_var_87_9 = (float *)malloc(sizeof(float *)); + float * d_var_87_9; + cudaMalloc((void **)&d_var_87_9, sizeof(float *)); + + float * h_var_87_10 = (float *)malloc(sizeof(float *)); + float * d_var_87_10; + cudaMalloc((void **)&d_var_87_10, sizeof(float *)); + + float * h_var_87_11 = (float *)malloc(sizeof(float *)); + float * d_var_87_11; + cudaMalloc((void **)&d_var_87_11, sizeof(float *)); + + float * h_var_87_12 = (float *)malloc(sizeof(float *)); + float * d_var_87_12; + cudaMalloc((void **)&d_var_87_12, sizeof(float *)); + + float * h_var_87_13 = (float *)malloc(sizeof(float *)); + float * d_var_87_13; + cudaMalloc((void **)&d_var_87_13, sizeof(float *)); + + float * h_var_87_14 = (float *)malloc(sizeof(float *)); + float * d_var_87_14; + cudaMalloc((void **)&d_var_87_14, sizeof(float *)); + + float * h_var_87_15 = (float *)malloc(sizeof(float *)); + float * d_var_87_15; + cudaMalloc((void **)&d_var_87_15, sizeof(float *)); + + float * h_var_87_16 = (float *)malloc(sizeof(float *)); + float * d_var_87_16; + cudaMalloc((void **)&d_var_87_16, sizeof(float *)); + + float * h_var_87_17 = (float *)malloc(sizeof(float *)); + float * d_var_87_17; + cudaMalloc((void **)&d_var_87_17, sizeof(float *)); + + float * h_var_87_18 = (float *)malloc(sizeof(float *)); + float * d_var_87_18; + cudaMalloc((void **)&d_var_87_18, sizeof(float *)); + + float * h_var_87_19 = (float *)malloc(sizeof(float *)); + float * d_var_87_19; + cudaMalloc((void **)&d_var_87_19, sizeof(float *)); + + float * h_var_88_0 = (float *)malloc(sizeof(float *)); + float * d_var_88_0; + cudaMalloc((void **)&d_var_88_0, sizeof(float *)); + + float * h_var_88_1 = (float *)malloc(sizeof(float *)); + float * d_var_88_1; + cudaMalloc((void **)&d_var_88_1, sizeof(float *)); + + float * h_var_88_2 = (float *)malloc(sizeof(float *)); + float * d_var_88_2; + cudaMalloc((void **)&d_var_88_2, sizeof(float *)); + + float * h_var_88_3 = (float *)malloc(sizeof(float *)); + float * d_var_88_3; + cudaMalloc((void **)&d_var_88_3, sizeof(float *)); + + float * h_var_88_4 = (float *)malloc(sizeof(float *)); + float * d_var_88_4; + cudaMalloc((void **)&d_var_88_4, sizeof(float *)); + + float * h_var_88_5 = (float *)malloc(sizeof(float *)); + float * d_var_88_5; + cudaMalloc((void **)&d_var_88_5, sizeof(float *)); + + float * h_var_88_6 = (float *)malloc(sizeof(float *)); + float * d_var_88_6; + cudaMalloc((void **)&d_var_88_6, sizeof(float *)); + + float * h_var_88_7 = (float *)malloc(sizeof(float *)); + float * d_var_88_7; + cudaMalloc((void **)&d_var_88_7, sizeof(float *)); + + float * h_var_88_8 = (float *)malloc(sizeof(float *)); + float * d_var_88_8; + cudaMalloc((void **)&d_var_88_8, sizeof(float *)); + + float * h_var_88_9 = (float *)malloc(sizeof(float *)); + float * d_var_88_9; + cudaMalloc((void **)&d_var_88_9, sizeof(float *)); + + float * h_var_88_10 = (float *)malloc(sizeof(float *)); + float * d_var_88_10; + cudaMalloc((void **)&d_var_88_10, sizeof(float *)); + + float * h_var_88_11 = (float *)malloc(sizeof(float *)); + float * d_var_88_11; + cudaMalloc((void **)&d_var_88_11, sizeof(float *)); + + float * h_var_88_12 = (float *)malloc(sizeof(float *)); + float * d_var_88_12; + cudaMalloc((void **)&d_var_88_12, sizeof(float *)); + + float * h_var_88_13 = (float *)malloc(sizeof(float *)); + float * d_var_88_13; + cudaMalloc((void **)&d_var_88_13, sizeof(float *)); + + float * h_var_88_14 = (float *)malloc(sizeof(float *)); + float * d_var_88_14; + cudaMalloc((void **)&d_var_88_14, sizeof(float *)); + + float * h_var_88_15 = (float *)malloc(sizeof(float *)); + float * d_var_88_15; + cudaMalloc((void **)&d_var_88_15, sizeof(float *)); + + float * h_var_88_16 = (float *)malloc(sizeof(float *)); + float * d_var_88_16; + cudaMalloc((void **)&d_var_88_16, sizeof(float *)); + + float * h_var_88_17 = (float *)malloc(sizeof(float *)); + float * d_var_88_17; + cudaMalloc((void **)&d_var_88_17, sizeof(float *)); + + float * h_var_88_18 = (float *)malloc(sizeof(float *)); + float * d_var_88_18; + cudaMalloc((void **)&d_var_88_18, sizeof(float *)); + + float * h_var_88_19 = (float *)malloc(sizeof(float *)); + float * d_var_88_19; + cudaMalloc((void **)&d_var_88_19, sizeof(float *)); + + float * h_var_89_0 = (float *)malloc(sizeof(float *)); + float * d_var_89_0; + cudaMalloc((void **)&d_var_89_0, sizeof(float *)); + + float * h_var_89_1 = (float *)malloc(sizeof(float *)); + float * d_var_89_1; + cudaMalloc((void **)&d_var_89_1, sizeof(float *)); + + float * h_var_89_2 = (float *)malloc(sizeof(float *)); + float * d_var_89_2; + cudaMalloc((void **)&d_var_89_2, sizeof(float *)); + + float * h_var_89_3 = (float *)malloc(sizeof(float *)); + float * d_var_89_3; + cudaMalloc((void **)&d_var_89_3, sizeof(float *)); + + float * h_var_89_4 = (float *)malloc(sizeof(float *)); + float * d_var_89_4; + cudaMalloc((void **)&d_var_89_4, sizeof(float *)); + + float * h_var_89_5 = (float *)malloc(sizeof(float *)); + float * d_var_89_5; + cudaMalloc((void **)&d_var_89_5, sizeof(float *)); + + float * h_var_89_6 = (float *)malloc(sizeof(float *)); + float * d_var_89_6; + cudaMalloc((void **)&d_var_89_6, sizeof(float *)); + + float * h_var_89_7 = (float *)malloc(sizeof(float *)); + float * d_var_89_7; + cudaMalloc((void **)&d_var_89_7, sizeof(float *)); + + float * h_var_89_8 = (float *)malloc(sizeof(float *)); + float * d_var_89_8; + cudaMalloc((void **)&d_var_89_8, sizeof(float *)); + + float * h_var_89_9 = (float *)malloc(sizeof(float *)); + float * d_var_89_9; + cudaMalloc((void **)&d_var_89_9, sizeof(float *)); + + float * h_var_89_10 = (float *)malloc(sizeof(float *)); + float * d_var_89_10; + cudaMalloc((void **)&d_var_89_10, sizeof(float *)); + + float * h_var_89_11 = (float *)malloc(sizeof(float *)); + float * d_var_89_11; + cudaMalloc((void **)&d_var_89_11, sizeof(float *)); + + float * h_var_89_12 = (float *)malloc(sizeof(float *)); + float * d_var_89_12; + cudaMalloc((void **)&d_var_89_12, sizeof(float *)); + + float * h_var_89_13 = (float *)malloc(sizeof(float *)); + float * d_var_89_13; + cudaMalloc((void **)&d_var_89_13, sizeof(float *)); + + float * h_var_89_14 = (float *)malloc(sizeof(float *)); + float * d_var_89_14; + cudaMalloc((void **)&d_var_89_14, sizeof(float *)); + + float * h_var_89_15 = (float *)malloc(sizeof(float *)); + float * d_var_89_15; + cudaMalloc((void **)&d_var_89_15, sizeof(float *)); + + float * h_var_89_16 = (float *)malloc(sizeof(float *)); + float * d_var_89_16; + cudaMalloc((void **)&d_var_89_16, sizeof(float *)); + + float * h_var_89_17 = (float *)malloc(sizeof(float *)); + float * d_var_89_17; + cudaMalloc((void **)&d_var_89_17, sizeof(float *)); + + float * h_var_89_18 = (float *)malloc(sizeof(float *)); + float * d_var_89_18; + cudaMalloc((void **)&d_var_89_18, sizeof(float *)); + + float * h_var_89_19 = (float *)malloc(sizeof(float *)); + float * d_var_89_19; + cudaMalloc((void **)&d_var_89_19, sizeof(float *)); + + float * h_var_90_0 = (float *)malloc(sizeof(float *)); + float * d_var_90_0; + cudaMalloc((void **)&d_var_90_0, sizeof(float *)); + + float * h_var_90_1 = (float *)malloc(sizeof(float *)); + float * d_var_90_1; + cudaMalloc((void **)&d_var_90_1, sizeof(float *)); + + float * h_var_90_2 = (float *)malloc(sizeof(float *)); + float * d_var_90_2; + cudaMalloc((void **)&d_var_90_2, sizeof(float *)); + + float * h_var_90_3 = (float *)malloc(sizeof(float *)); + float * d_var_90_3; + cudaMalloc((void **)&d_var_90_3, sizeof(float *)); + + float * h_var_90_4 = (float *)malloc(sizeof(float *)); + float * d_var_90_4; + cudaMalloc((void **)&d_var_90_4, sizeof(float *)); + + float * h_var_90_5 = (float *)malloc(sizeof(float *)); + float * d_var_90_5; + cudaMalloc((void **)&d_var_90_5, sizeof(float *)); + + float * h_var_90_6 = (float *)malloc(sizeof(float *)); + float * d_var_90_6; + cudaMalloc((void **)&d_var_90_6, sizeof(float *)); + + float * h_var_90_7 = (float *)malloc(sizeof(float *)); + float * d_var_90_7; + cudaMalloc((void **)&d_var_90_7, sizeof(float *)); + + float * h_var_90_8 = (float *)malloc(sizeof(float *)); + float * d_var_90_8; + cudaMalloc((void **)&d_var_90_8, sizeof(float *)); + + float * h_var_90_9 = (float *)malloc(sizeof(float *)); + float * d_var_90_9; + cudaMalloc((void **)&d_var_90_9, sizeof(float *)); + + float * h_var_90_10 = (float *)malloc(sizeof(float *)); + float * d_var_90_10; + cudaMalloc((void **)&d_var_90_10, sizeof(float *)); + + float * h_var_90_11 = (float *)malloc(sizeof(float *)); + float * d_var_90_11; + cudaMalloc((void **)&d_var_90_11, sizeof(float *)); + + float * h_var_90_12 = (float *)malloc(sizeof(float *)); + float * d_var_90_12; + cudaMalloc((void **)&d_var_90_12, sizeof(float *)); + + float * h_var_90_13 = (float *)malloc(sizeof(float *)); + float * d_var_90_13; + cudaMalloc((void **)&d_var_90_13, sizeof(float *)); + + float * h_var_90_14 = (float *)malloc(sizeof(float *)); + float * d_var_90_14; + cudaMalloc((void **)&d_var_90_14, sizeof(float *)); + + float * h_var_90_15 = (float *)malloc(sizeof(float *)); + float * d_var_90_15; + cudaMalloc((void **)&d_var_90_15, sizeof(float *)); + + float * h_var_90_16 = (float *)malloc(sizeof(float *)); + float * d_var_90_16; + cudaMalloc((void **)&d_var_90_16, sizeof(float *)); + + float * h_var_90_17 = (float *)malloc(sizeof(float *)); + float * d_var_90_17; + cudaMalloc((void **)&d_var_90_17, sizeof(float *)); + + float * h_var_90_18 = (float *)malloc(sizeof(float *)); + float * d_var_90_18; + cudaMalloc((void **)&d_var_90_18, sizeof(float *)); + + float * h_var_90_19 = (float *)malloc(sizeof(float *)); + float * d_var_90_19; + cudaMalloc((void **)&d_var_90_19, sizeof(float *)); + + float * h_var_91_0 = (float *)malloc(sizeof(float *)); + float * d_var_91_0; + cudaMalloc((void **)&d_var_91_0, sizeof(float *)); + + float * h_var_91_1 = (float *)malloc(sizeof(float *)); + float * d_var_91_1; + cudaMalloc((void **)&d_var_91_1, sizeof(float *)); + + float * h_var_91_2 = (float *)malloc(sizeof(float *)); + float * d_var_91_2; + cudaMalloc((void **)&d_var_91_2, sizeof(float *)); + + float * h_var_91_3 = (float *)malloc(sizeof(float *)); + float * d_var_91_3; + cudaMalloc((void **)&d_var_91_3, sizeof(float *)); + + float * h_var_91_4 = (float *)malloc(sizeof(float *)); + float * d_var_91_4; + cudaMalloc((void **)&d_var_91_4, sizeof(float *)); + + float * h_var_91_5 = (float *)malloc(sizeof(float *)); + float * d_var_91_5; + cudaMalloc((void **)&d_var_91_5, sizeof(float *)); + + float * h_var_91_6 = (float *)malloc(sizeof(float *)); + float * d_var_91_6; + cudaMalloc((void **)&d_var_91_6, sizeof(float *)); + + float * h_var_91_7 = (float *)malloc(sizeof(float *)); + float * d_var_91_7; + cudaMalloc((void **)&d_var_91_7, sizeof(float *)); + + float * h_var_91_8 = (float *)malloc(sizeof(float *)); + float * d_var_91_8; + cudaMalloc((void **)&d_var_91_8, sizeof(float *)); + + float * h_var_91_9 = (float *)malloc(sizeof(float *)); + float * d_var_91_9; + cudaMalloc((void **)&d_var_91_9, sizeof(float *)); + + float * h_var_91_10 = (float *)malloc(sizeof(float *)); + float * d_var_91_10; + cudaMalloc((void **)&d_var_91_10, sizeof(float *)); + + float * h_var_91_11 = (float *)malloc(sizeof(float *)); + float * d_var_91_11; + cudaMalloc((void **)&d_var_91_11, sizeof(float *)); + + float * h_var_91_12 = (float *)malloc(sizeof(float *)); + float * d_var_91_12; + cudaMalloc((void **)&d_var_91_12, sizeof(float *)); + + float * h_var_91_13 = (float *)malloc(sizeof(float *)); + float * d_var_91_13; + cudaMalloc((void **)&d_var_91_13, sizeof(float *)); + + float * h_var_91_14 = (float *)malloc(sizeof(float *)); + float * d_var_91_14; + cudaMalloc((void **)&d_var_91_14, sizeof(float *)); + + float * h_var_91_15 = (float *)malloc(sizeof(float *)); + float * d_var_91_15; + cudaMalloc((void **)&d_var_91_15, sizeof(float *)); + + float * h_var_91_16 = (float *)malloc(sizeof(float *)); + float * d_var_91_16; + cudaMalloc((void **)&d_var_91_16, sizeof(float *)); + + float * h_var_91_17 = (float *)malloc(sizeof(float *)); + float * d_var_91_17; + cudaMalloc((void **)&d_var_91_17, sizeof(float *)); + + float * h_var_91_18 = (float *)malloc(sizeof(float *)); + float * d_var_91_18; + cudaMalloc((void **)&d_var_91_18, sizeof(float *)); + + float * h_var_91_19 = (float *)malloc(sizeof(float *)); + float * d_var_91_19; + cudaMalloc((void **)&d_var_91_19, sizeof(float *)); + + float * h_var_92_0 = (float *)malloc(sizeof(float *)); + float * d_var_92_0; + cudaMalloc((void **)&d_var_92_0, sizeof(float *)); + + float * h_var_92_1 = (float *)malloc(sizeof(float *)); + float * d_var_92_1; + cudaMalloc((void **)&d_var_92_1, sizeof(float *)); + + float * h_var_92_2 = (float *)malloc(sizeof(float *)); + float * d_var_92_2; + cudaMalloc((void **)&d_var_92_2, sizeof(float *)); + + float * h_var_92_3 = (float *)malloc(sizeof(float *)); + float * d_var_92_3; + cudaMalloc((void **)&d_var_92_3, sizeof(float *)); + + float * h_var_92_4 = (float *)malloc(sizeof(float *)); + float * d_var_92_4; + cudaMalloc((void **)&d_var_92_4, sizeof(float *)); + + float * h_var_92_5 = (float *)malloc(sizeof(float *)); + float * d_var_92_5; + cudaMalloc((void **)&d_var_92_5, sizeof(float *)); + + float * h_var_92_6 = (float *)malloc(sizeof(float *)); + float * d_var_92_6; + cudaMalloc((void **)&d_var_92_6, sizeof(float *)); + + float * h_var_92_7 = (float *)malloc(sizeof(float *)); + float * d_var_92_7; + cudaMalloc((void **)&d_var_92_7, sizeof(float *)); + + float * h_var_92_8 = (float *)malloc(sizeof(float *)); + float * d_var_92_8; + cudaMalloc((void **)&d_var_92_8, sizeof(float *)); + + float * h_var_92_9 = (float *)malloc(sizeof(float *)); + float * d_var_92_9; + cudaMalloc((void **)&d_var_92_9, sizeof(float *)); + + float * h_var_92_10 = (float *)malloc(sizeof(float *)); + float * d_var_92_10; + cudaMalloc((void **)&d_var_92_10, sizeof(float *)); + + float * h_var_92_11 = (float *)malloc(sizeof(float *)); + float * d_var_92_11; + cudaMalloc((void **)&d_var_92_11, sizeof(float *)); + + float * h_var_92_12 = (float *)malloc(sizeof(float *)); + float * d_var_92_12; + cudaMalloc((void **)&d_var_92_12, sizeof(float *)); + + float * h_var_92_13 = (float *)malloc(sizeof(float *)); + float * d_var_92_13; + cudaMalloc((void **)&d_var_92_13, sizeof(float *)); + + float * h_var_92_14 = (float *)malloc(sizeof(float *)); + float * d_var_92_14; + cudaMalloc((void **)&d_var_92_14, sizeof(float *)); + + float * h_var_92_15 = (float *)malloc(sizeof(float *)); + float * d_var_92_15; + cudaMalloc((void **)&d_var_92_15, sizeof(float *)); + + float * h_var_92_16 = (float *)malloc(sizeof(float *)); + float * d_var_92_16; + cudaMalloc((void **)&d_var_92_16, sizeof(float *)); + + float * h_var_92_17 = (float *)malloc(sizeof(float *)); + float * d_var_92_17; + cudaMalloc((void **)&d_var_92_17, sizeof(float *)); + + float * h_var_92_18 = (float *)malloc(sizeof(float *)); + float * d_var_92_18; + cudaMalloc((void **)&d_var_92_18, sizeof(float *)); + + float * h_var_92_19 = (float *)malloc(sizeof(float *)); + float * d_var_92_19; + cudaMalloc((void **)&d_var_92_19, sizeof(float *)); + + float * h_var_93_0 = (float *)malloc(sizeof(float *)); + float * d_var_93_0; + cudaMalloc((void **)&d_var_93_0, sizeof(float *)); + + float * h_var_93_1 = (float *)malloc(sizeof(float *)); + float * d_var_93_1; + cudaMalloc((void **)&d_var_93_1, sizeof(float *)); + + float * h_var_93_2 = (float *)malloc(sizeof(float *)); + float * d_var_93_2; + cudaMalloc((void **)&d_var_93_2, sizeof(float *)); + + float * h_var_93_3 = (float *)malloc(sizeof(float *)); + float * d_var_93_3; + cudaMalloc((void **)&d_var_93_3, sizeof(float *)); + + float * h_var_93_4 = (float *)malloc(sizeof(float *)); + float * d_var_93_4; + cudaMalloc((void **)&d_var_93_4, sizeof(float *)); + + float * h_var_93_5 = (float *)malloc(sizeof(float *)); + float * d_var_93_5; + cudaMalloc((void **)&d_var_93_5, sizeof(float *)); + + float * h_var_93_6 = (float *)malloc(sizeof(float *)); + float * d_var_93_6; + cudaMalloc((void **)&d_var_93_6, sizeof(float *)); + + float * h_var_93_7 = (float *)malloc(sizeof(float *)); + float * d_var_93_7; + cudaMalloc((void **)&d_var_93_7, sizeof(float *)); + + float * h_var_93_8 = (float *)malloc(sizeof(float *)); + float * d_var_93_8; + cudaMalloc((void **)&d_var_93_8, sizeof(float *)); + + float * h_var_93_9 = (float *)malloc(sizeof(float *)); + float * d_var_93_9; + cudaMalloc((void **)&d_var_93_9, sizeof(float *)); + + float * h_var_93_10 = (float *)malloc(sizeof(float *)); + float * d_var_93_10; + cudaMalloc((void **)&d_var_93_10, sizeof(float *)); + + float * h_var_93_11 = (float *)malloc(sizeof(float *)); + float * d_var_93_11; + cudaMalloc((void **)&d_var_93_11, sizeof(float *)); + + float * h_var_93_12 = (float *)malloc(sizeof(float *)); + float * d_var_93_12; + cudaMalloc((void **)&d_var_93_12, sizeof(float *)); + + float * h_var_93_13 = (float *)malloc(sizeof(float *)); + float * d_var_93_13; + cudaMalloc((void **)&d_var_93_13, sizeof(float *)); + + float * h_var_93_14 = (float *)malloc(sizeof(float *)); + float * d_var_93_14; + cudaMalloc((void **)&d_var_93_14, sizeof(float *)); + + float * h_var_93_15 = (float *)malloc(sizeof(float *)); + float * d_var_93_15; + cudaMalloc((void **)&d_var_93_15, sizeof(float *)); + + float * h_var_93_16 = (float *)malloc(sizeof(float *)); + float * d_var_93_16; + cudaMalloc((void **)&d_var_93_16, sizeof(float *)); + + float * h_var_93_17 = (float *)malloc(sizeof(float *)); + float * d_var_93_17; + cudaMalloc((void **)&d_var_93_17, sizeof(float *)); + + float * h_var_93_18 = (float *)malloc(sizeof(float *)); + float * d_var_93_18; + cudaMalloc((void **)&d_var_93_18, sizeof(float *)); + + float * h_var_93_19 = (float *)malloc(sizeof(float *)); + float * d_var_93_19; + cudaMalloc((void **)&d_var_93_19, sizeof(float *)); + + float * h_var_94_0 = (float *)malloc(sizeof(float *)); + float * d_var_94_0; + cudaMalloc((void **)&d_var_94_0, sizeof(float *)); + + float * h_var_94_1 = (float *)malloc(sizeof(float *)); + float * d_var_94_1; + cudaMalloc((void **)&d_var_94_1, sizeof(float *)); + + float * h_var_94_2 = (float *)malloc(sizeof(float *)); + float * d_var_94_2; + cudaMalloc((void **)&d_var_94_2, sizeof(float *)); + + float * h_var_94_3 = (float *)malloc(sizeof(float *)); + float * d_var_94_3; + cudaMalloc((void **)&d_var_94_3, sizeof(float *)); + + float * h_var_94_4 = (float *)malloc(sizeof(float *)); + float * d_var_94_4; + cudaMalloc((void **)&d_var_94_4, sizeof(float *)); + + float * h_var_94_5 = (float *)malloc(sizeof(float *)); + float * d_var_94_5; + cudaMalloc((void **)&d_var_94_5, sizeof(float *)); + + float * h_var_94_6 = (float *)malloc(sizeof(float *)); + float * d_var_94_6; + cudaMalloc((void **)&d_var_94_6, sizeof(float *)); + + float * h_var_94_7 = (float *)malloc(sizeof(float *)); + float * d_var_94_7; + cudaMalloc((void **)&d_var_94_7, sizeof(float *)); + + float * h_var_94_8 = (float *)malloc(sizeof(float *)); + float * d_var_94_8; + cudaMalloc((void **)&d_var_94_8, sizeof(float *)); + + float * h_var_94_9 = (float *)malloc(sizeof(float *)); + float * d_var_94_9; + cudaMalloc((void **)&d_var_94_9, sizeof(float *)); + + float * h_var_94_10 = (float *)malloc(sizeof(float *)); + float * d_var_94_10; + cudaMalloc((void **)&d_var_94_10, sizeof(float *)); + + float * h_var_94_11 = (float *)malloc(sizeof(float *)); + float * d_var_94_11; + cudaMalloc((void **)&d_var_94_11, sizeof(float *)); + + float * h_var_94_12 = (float *)malloc(sizeof(float *)); + float * d_var_94_12; + cudaMalloc((void **)&d_var_94_12, sizeof(float *)); + + float * h_var_94_13 = (float *)malloc(sizeof(float *)); + float * d_var_94_13; + cudaMalloc((void **)&d_var_94_13, sizeof(float *)); + + float * h_var_94_14 = (float *)malloc(sizeof(float *)); + float * d_var_94_14; + cudaMalloc((void **)&d_var_94_14, sizeof(float *)); + + float * h_var_94_15 = (float *)malloc(sizeof(float *)); + float * d_var_94_15; + cudaMalloc((void **)&d_var_94_15, sizeof(float *)); + + float * h_var_94_16 = (float *)malloc(sizeof(float *)); + float * d_var_94_16; + cudaMalloc((void **)&d_var_94_16, sizeof(float *)); + + float * h_var_94_17 = (float *)malloc(sizeof(float *)); + float * d_var_94_17; + cudaMalloc((void **)&d_var_94_17, sizeof(float *)); + + float * h_var_94_18 = (float *)malloc(sizeof(float *)); + float * d_var_94_18; + cudaMalloc((void **)&d_var_94_18, sizeof(float *)); + + float * h_var_94_19 = (float *)malloc(sizeof(float *)); + float * d_var_94_19; + cudaMalloc((void **)&d_var_94_19, sizeof(float *)); + + float * h_var_95_0 = (float *)malloc(sizeof(float *)); + float * d_var_95_0; + cudaMalloc((void **)&d_var_95_0, sizeof(float *)); + + float * h_var_95_1 = (float *)malloc(sizeof(float *)); + float * d_var_95_1; + cudaMalloc((void **)&d_var_95_1, sizeof(float *)); + + float * h_var_95_2 = (float *)malloc(sizeof(float *)); + float * d_var_95_2; + cudaMalloc((void **)&d_var_95_2, sizeof(float *)); + + float * h_var_95_3 = (float *)malloc(sizeof(float *)); + float * d_var_95_3; + cudaMalloc((void **)&d_var_95_3, sizeof(float *)); + + float * h_var_95_4 = (float *)malloc(sizeof(float *)); + float * d_var_95_4; + cudaMalloc((void **)&d_var_95_4, sizeof(float *)); + + float * h_var_95_5 = (float *)malloc(sizeof(float *)); + float * d_var_95_5; + cudaMalloc((void **)&d_var_95_5, sizeof(float *)); + + float * h_var_95_6 = (float *)malloc(sizeof(float *)); + float * d_var_95_6; + cudaMalloc((void **)&d_var_95_6, sizeof(float *)); + + float * h_var_95_7 = (float *)malloc(sizeof(float *)); + float * d_var_95_7; + cudaMalloc((void **)&d_var_95_7, sizeof(float *)); + + float * h_var_95_8 = (float *)malloc(sizeof(float *)); + float * d_var_95_8; + cudaMalloc((void **)&d_var_95_8, sizeof(float *)); + + float * h_var_95_9 = (float *)malloc(sizeof(float *)); + float * d_var_95_9; + cudaMalloc((void **)&d_var_95_9, sizeof(float *)); + + float * h_var_95_10 = (float *)malloc(sizeof(float *)); + float * d_var_95_10; + cudaMalloc((void **)&d_var_95_10, sizeof(float *)); + + float * h_var_95_11 = (float *)malloc(sizeof(float *)); + float * d_var_95_11; + cudaMalloc((void **)&d_var_95_11, sizeof(float *)); + + float * h_var_95_12 = (float *)malloc(sizeof(float *)); + float * d_var_95_12; + cudaMalloc((void **)&d_var_95_12, sizeof(float *)); + + float * h_var_95_13 = (float *)malloc(sizeof(float *)); + float * d_var_95_13; + cudaMalloc((void **)&d_var_95_13, sizeof(float *)); + + float * h_var_95_14 = (float *)malloc(sizeof(float *)); + float * d_var_95_14; + cudaMalloc((void **)&d_var_95_14, sizeof(float *)); + + float * h_var_95_15 = (float *)malloc(sizeof(float *)); + float * d_var_95_15; + cudaMalloc((void **)&d_var_95_15, sizeof(float *)); + + float * h_var_95_16 = (float *)malloc(sizeof(float *)); + float * d_var_95_16; + cudaMalloc((void **)&d_var_95_16, sizeof(float *)); + + float * h_var_95_17 = (float *)malloc(sizeof(float *)); + float * d_var_95_17; + cudaMalloc((void **)&d_var_95_17, sizeof(float *)); + + float * h_var_95_18 = (float *)malloc(sizeof(float *)); + float * d_var_95_18; + cudaMalloc((void **)&d_var_95_18, sizeof(float *)); + + float * h_var_95_19 = (float *)malloc(sizeof(float *)); + float * d_var_95_19; + cudaMalloc((void **)&d_var_95_19, sizeof(float *)); + + float * h_var_96_0 = (float *)malloc(sizeof(float *)); + float * d_var_96_0; + cudaMalloc((void **)&d_var_96_0, sizeof(float *)); + + float * h_var_96_1 = (float *)malloc(sizeof(float *)); + float * d_var_96_1; + cudaMalloc((void **)&d_var_96_1, sizeof(float *)); + + float * h_var_96_2 = (float *)malloc(sizeof(float *)); + float * d_var_96_2; + cudaMalloc((void **)&d_var_96_2, sizeof(float *)); + + float * h_var_96_3 = (float *)malloc(sizeof(float *)); + float * d_var_96_3; + cudaMalloc((void **)&d_var_96_3, sizeof(float *)); + + float * h_var_96_4 = (float *)malloc(sizeof(float *)); + float * d_var_96_4; + cudaMalloc((void **)&d_var_96_4, sizeof(float *)); + + float * h_var_96_5 = (float *)malloc(sizeof(float *)); + float * d_var_96_5; + cudaMalloc((void **)&d_var_96_5, sizeof(float *)); + + float * h_var_96_6 = (float *)malloc(sizeof(float *)); + float * d_var_96_6; + cudaMalloc((void **)&d_var_96_6, sizeof(float *)); + + float * h_var_96_7 = (float *)malloc(sizeof(float *)); + float * d_var_96_7; + cudaMalloc((void **)&d_var_96_7, sizeof(float *)); + + float * h_var_96_8 = (float *)malloc(sizeof(float *)); + float * d_var_96_8; + cudaMalloc((void **)&d_var_96_8, sizeof(float *)); + + float * h_var_96_9 = (float *)malloc(sizeof(float *)); + float * d_var_96_9; + cudaMalloc((void **)&d_var_96_9, sizeof(float *)); + + float * h_var_96_10 = (float *)malloc(sizeof(float *)); + float * d_var_96_10; + cudaMalloc((void **)&d_var_96_10, sizeof(float *)); + + float * h_var_96_11 = (float *)malloc(sizeof(float *)); + float * d_var_96_11; + cudaMalloc((void **)&d_var_96_11, sizeof(float *)); + + float * h_var_96_12 = (float *)malloc(sizeof(float *)); + float * d_var_96_12; + cudaMalloc((void **)&d_var_96_12, sizeof(float *)); + + float * h_var_96_13 = (float *)malloc(sizeof(float *)); + float * d_var_96_13; + cudaMalloc((void **)&d_var_96_13, sizeof(float *)); + + float * h_var_96_14 = (float *)malloc(sizeof(float *)); + float * d_var_96_14; + cudaMalloc((void **)&d_var_96_14, sizeof(float *)); + + float * h_var_96_15 = (float *)malloc(sizeof(float *)); + float * d_var_96_15; + cudaMalloc((void **)&d_var_96_15, sizeof(float *)); + + float * h_var_96_16 = (float *)malloc(sizeof(float *)); + float * d_var_96_16; + cudaMalloc((void **)&d_var_96_16, sizeof(float *)); + + float * h_var_96_17 = (float *)malloc(sizeof(float *)); + float * d_var_96_17; + cudaMalloc((void **)&d_var_96_17, sizeof(float *)); + + float * h_var_96_18 = (float *)malloc(sizeof(float *)); + float * d_var_96_18; + cudaMalloc((void **)&d_var_96_18, sizeof(float *)); + + float * h_var_96_19 = (float *)malloc(sizeof(float *)); + float * d_var_96_19; + cudaMalloc((void **)&d_var_96_19, sizeof(float *)); + + float * h_var_97_0 = (float *)malloc(sizeof(float *)); + float * d_var_97_0; + cudaMalloc((void **)&d_var_97_0, sizeof(float *)); + + float * h_var_97_1 = (float *)malloc(sizeof(float *)); + float * d_var_97_1; + cudaMalloc((void **)&d_var_97_1, sizeof(float *)); + + float * h_var_97_2 = (float *)malloc(sizeof(float *)); + float * d_var_97_2; + cudaMalloc((void **)&d_var_97_2, sizeof(float *)); + + float * h_var_97_3 = (float *)malloc(sizeof(float *)); + float * d_var_97_3; + cudaMalloc((void **)&d_var_97_3, sizeof(float *)); + + float * h_var_97_4 = (float *)malloc(sizeof(float *)); + float * d_var_97_4; + cudaMalloc((void **)&d_var_97_4, sizeof(float *)); + + float * h_var_97_5 = (float *)malloc(sizeof(float *)); + float * d_var_97_5; + cudaMalloc((void **)&d_var_97_5, sizeof(float *)); + + float * h_var_97_6 = (float *)malloc(sizeof(float *)); + float * d_var_97_6; + cudaMalloc((void **)&d_var_97_6, sizeof(float *)); + + float * h_var_97_7 = (float *)malloc(sizeof(float *)); + float * d_var_97_7; + cudaMalloc((void **)&d_var_97_7, sizeof(float *)); + + float * h_var_97_8 = (float *)malloc(sizeof(float *)); + float * d_var_97_8; + cudaMalloc((void **)&d_var_97_8, sizeof(float *)); + + float * h_var_97_9 = (float *)malloc(sizeof(float *)); + float * d_var_97_9; + cudaMalloc((void **)&d_var_97_9, sizeof(float *)); + + float * h_var_97_10 = (float *)malloc(sizeof(float *)); + float * d_var_97_10; + cudaMalloc((void **)&d_var_97_10, sizeof(float *)); + + float * h_var_97_11 = (float *)malloc(sizeof(float *)); + float * d_var_97_11; + cudaMalloc((void **)&d_var_97_11, sizeof(float *)); + + float * h_var_97_12 = (float *)malloc(sizeof(float *)); + float * d_var_97_12; + cudaMalloc((void **)&d_var_97_12, sizeof(float *)); + + float * h_var_97_13 = (float *)malloc(sizeof(float *)); + float * d_var_97_13; + cudaMalloc((void **)&d_var_97_13, sizeof(float *)); + + float * h_var_97_14 = (float *)malloc(sizeof(float *)); + float * d_var_97_14; + cudaMalloc((void **)&d_var_97_14, sizeof(float *)); + + float * h_var_97_15 = (float *)malloc(sizeof(float *)); + float * d_var_97_15; + cudaMalloc((void **)&d_var_97_15, sizeof(float *)); + + float * h_var_97_16 = (float *)malloc(sizeof(float *)); + float * d_var_97_16; + cudaMalloc((void **)&d_var_97_16, sizeof(float *)); + + float * h_var_97_17 = (float *)malloc(sizeof(float *)); + float * d_var_97_17; + cudaMalloc((void **)&d_var_97_17, sizeof(float *)); + + float * h_var_97_18 = (float *)malloc(sizeof(float *)); + float * d_var_97_18; + cudaMalloc((void **)&d_var_97_18, sizeof(float *)); + + float * h_var_97_19 = (float *)malloc(sizeof(float *)); + float * d_var_97_19; + cudaMalloc((void **)&d_var_97_19, sizeof(float *)); + + float * h_var_98_0 = (float *)malloc(sizeof(float *)); + float * d_var_98_0; + cudaMalloc((void **)&d_var_98_0, sizeof(float *)); + + float * h_var_98_1 = (float *)malloc(sizeof(float *)); + float * d_var_98_1; + cudaMalloc((void **)&d_var_98_1, sizeof(float *)); + + float * h_var_98_2 = (float *)malloc(sizeof(float *)); + float * d_var_98_2; + cudaMalloc((void **)&d_var_98_2, sizeof(float *)); + + float * h_var_98_3 = (float *)malloc(sizeof(float *)); + float * d_var_98_3; + cudaMalloc((void **)&d_var_98_3, sizeof(float *)); + + float * h_var_98_4 = (float *)malloc(sizeof(float *)); + float * d_var_98_4; + cudaMalloc((void **)&d_var_98_4, sizeof(float *)); + + float * h_var_98_5 = (float *)malloc(sizeof(float *)); + float * d_var_98_5; + cudaMalloc((void **)&d_var_98_5, sizeof(float *)); + + float * h_var_98_6 = (float *)malloc(sizeof(float *)); + float * d_var_98_6; + cudaMalloc((void **)&d_var_98_6, sizeof(float *)); + + float * h_var_98_7 = (float *)malloc(sizeof(float *)); + float * d_var_98_7; + cudaMalloc((void **)&d_var_98_7, sizeof(float *)); + + float * h_var_98_8 = (float *)malloc(sizeof(float *)); + float * d_var_98_8; + cudaMalloc((void **)&d_var_98_8, sizeof(float *)); + + float * h_var_98_9 = (float *)malloc(sizeof(float *)); + float * d_var_98_9; + cudaMalloc((void **)&d_var_98_9, sizeof(float *)); + + float * h_var_98_10 = (float *)malloc(sizeof(float *)); + float * d_var_98_10; + cudaMalloc((void **)&d_var_98_10, sizeof(float *)); + + float * h_var_98_11 = (float *)malloc(sizeof(float *)); + float * d_var_98_11; + cudaMalloc((void **)&d_var_98_11, sizeof(float *)); + + float * h_var_98_12 = (float *)malloc(sizeof(float *)); + float * d_var_98_12; + cudaMalloc((void **)&d_var_98_12, sizeof(float *)); + + float * h_var_98_13 = (float *)malloc(sizeof(float *)); + float * d_var_98_13; + cudaMalloc((void **)&d_var_98_13, sizeof(float *)); + + float * h_var_98_14 = (float *)malloc(sizeof(float *)); + float * d_var_98_14; + cudaMalloc((void **)&d_var_98_14, sizeof(float *)); + + float * h_var_98_15 = (float *)malloc(sizeof(float *)); + float * d_var_98_15; + cudaMalloc((void **)&d_var_98_15, sizeof(float *)); + + float * h_var_98_16 = (float *)malloc(sizeof(float *)); + float * d_var_98_16; + cudaMalloc((void **)&d_var_98_16, sizeof(float *)); + + float * h_var_98_17 = (float *)malloc(sizeof(float *)); + float * d_var_98_17; + cudaMalloc((void **)&d_var_98_17, sizeof(float *)); + + float * h_var_98_18 = (float *)malloc(sizeof(float *)); + float * d_var_98_18; + cudaMalloc((void **)&d_var_98_18, sizeof(float *)); + + float * h_var_98_19 = (float *)malloc(sizeof(float *)); + float * d_var_98_19; + cudaMalloc((void **)&d_var_98_19, sizeof(float *)); + + float * h_var_99_0 = (float *)malloc(sizeof(float *)); + float * d_var_99_0; + cudaMalloc((void **)&d_var_99_0, sizeof(float *)); + + float * h_var_99_1 = (float *)malloc(sizeof(float *)); + float * d_var_99_1; + cudaMalloc((void **)&d_var_99_1, sizeof(float *)); + + float * h_var_99_2 = (float *)malloc(sizeof(float *)); + float * d_var_99_2; + cudaMalloc((void **)&d_var_99_2, sizeof(float *)); + + float * h_var_99_3 = (float *)malloc(sizeof(float *)); + float * d_var_99_3; + cudaMalloc((void **)&d_var_99_3, sizeof(float *)); + + float * h_var_99_4 = (float *)malloc(sizeof(float *)); + float * d_var_99_4; + cudaMalloc((void **)&d_var_99_4, sizeof(float *)); + + float * h_var_99_5 = (float *)malloc(sizeof(float *)); + float * d_var_99_5; + cudaMalloc((void **)&d_var_99_5, sizeof(float *)); + + float * h_var_99_6 = (float *)malloc(sizeof(float *)); + float * d_var_99_6; + cudaMalloc((void **)&d_var_99_6, sizeof(float *)); + + float * h_var_99_7 = (float *)malloc(sizeof(float *)); + float * d_var_99_7; + cudaMalloc((void **)&d_var_99_7, sizeof(float *)); + + float * h_var_99_8 = (float *)malloc(sizeof(float *)); + float * d_var_99_8; + cudaMalloc((void **)&d_var_99_8, sizeof(float *)); + + float * h_var_99_9 = (float *)malloc(sizeof(float *)); + float * d_var_99_9; + cudaMalloc((void **)&d_var_99_9, sizeof(float *)); + + float * h_var_99_10 = (float *)malloc(sizeof(float *)); + float * d_var_99_10; + cudaMalloc((void **)&d_var_99_10, sizeof(float *)); + + float * h_var_99_11 = (float *)malloc(sizeof(float *)); + float * d_var_99_11; + cudaMalloc((void **)&d_var_99_11, sizeof(float *)); + + float * h_var_99_12 = (float *)malloc(sizeof(float *)); + float * d_var_99_12; + cudaMalloc((void **)&d_var_99_12, sizeof(float *)); + + float * h_var_99_13 = (float *)malloc(sizeof(float *)); + float * d_var_99_13; + cudaMalloc((void **)&d_var_99_13, sizeof(float *)); + + float * h_var_99_14 = (float *)malloc(sizeof(float *)); + float * d_var_99_14; + cudaMalloc((void **)&d_var_99_14, sizeof(float *)); + + float * h_var_99_15 = (float *)malloc(sizeof(float *)); + float * d_var_99_15; + cudaMalloc((void **)&d_var_99_15, sizeof(float *)); + + float * h_var_99_16 = (float *)malloc(sizeof(float *)); + float * d_var_99_16; + cudaMalloc((void **)&d_var_99_16, sizeof(float *)); + + float * h_var_99_17 = (float *)malloc(sizeof(float *)); + float * d_var_99_17; + cudaMalloc((void **)&d_var_99_17, sizeof(float *)); + + float * h_var_99_18 = (float *)malloc(sizeof(float *)); + float * d_var_99_18; + cudaMalloc((void **)&d_var_99_18, sizeof(float *)); + + float * h_var_99_19 = (float *)malloc(sizeof(float *)); + float * d_var_99_19; + cudaMalloc((void **)&d_var_99_19, sizeof(float *)); + + + // clang-format off + + kernel_0<<<10, 10>>>(d_var_0_0, d_var_0_1, d_var_0_2, d_var_0_3, d_var_0_4, d_var_0_5, d_var_0_6, d_var_0_7, d_var_0_8, d_var_0_9, d_var_0_10, d_var_0_11, d_var_0_12, d_var_0_13, d_var_0_14, d_var_0_15, d_var_0_16, d_var_0_17, d_var_0_18, d_var_0_19); + + kernel_1<<<10, 10>>>(d_var_1_0, d_var_1_1, d_var_1_2, d_var_1_3, d_var_1_4, d_var_1_5, d_var_1_6, d_var_1_7, d_var_1_8, d_var_1_9, d_var_1_10, d_var_1_11, d_var_1_12, d_var_1_13, d_var_1_14, d_var_1_15, d_var_1_16, d_var_1_17, d_var_1_18, d_var_1_19); + + kernel_2<<<10, 10>>>(d_var_2_0, d_var_2_1, d_var_2_2, d_var_2_3, d_var_2_4, d_var_2_5, d_var_2_6, d_var_2_7, d_var_2_8, d_var_2_9, d_var_2_10, d_var_2_11, d_var_2_12, d_var_2_13, d_var_2_14, d_var_2_15, d_var_2_16, d_var_2_17, d_var_2_18, d_var_2_19); + + kernel_3<<<10, 10>>>(d_var_3_0, d_var_3_1, d_var_3_2, d_var_3_3, d_var_3_4, d_var_3_5, d_var_3_6, d_var_3_7, d_var_3_8, d_var_3_9, d_var_3_10, d_var_3_11, d_var_3_12, d_var_3_13, d_var_3_14, d_var_3_15, d_var_3_16, d_var_3_17, d_var_3_18, d_var_3_19); + + kernel_4<<<10, 10>>>(d_var_4_0, d_var_4_1, d_var_4_2, d_var_4_3, d_var_4_4, d_var_4_5, d_var_4_6, d_var_4_7, d_var_4_8, d_var_4_9, d_var_4_10, d_var_4_11, d_var_4_12, d_var_4_13, d_var_4_14, d_var_4_15, d_var_4_16, d_var_4_17, d_var_4_18, d_var_4_19); + + kernel_5<<<10, 10>>>(d_var_5_0, d_var_5_1, d_var_5_2, d_var_5_3, d_var_5_4, d_var_5_5, d_var_5_6, d_var_5_7, d_var_5_8, d_var_5_9, d_var_5_10, d_var_5_11, d_var_5_12, d_var_5_13, d_var_5_14, d_var_5_15, d_var_5_16, d_var_5_17, d_var_5_18, d_var_5_19); + + kernel_6<<<10, 10>>>(d_var_6_0, d_var_6_1, d_var_6_2, d_var_6_3, d_var_6_4, d_var_6_5, d_var_6_6, d_var_6_7, d_var_6_8, d_var_6_9, d_var_6_10, d_var_6_11, d_var_6_12, d_var_6_13, d_var_6_14, d_var_6_15, d_var_6_16, d_var_6_17, d_var_6_18, d_var_6_19); + + kernel_7<<<10, 10>>>(d_var_7_0, d_var_7_1, d_var_7_2, d_var_7_3, d_var_7_4, d_var_7_5, d_var_7_6, d_var_7_7, d_var_7_8, d_var_7_9, d_var_7_10, d_var_7_11, d_var_7_12, d_var_7_13, d_var_7_14, d_var_7_15, d_var_7_16, d_var_7_17, d_var_7_18, d_var_7_19); + + kernel_8<<<10, 10>>>(d_var_8_0, d_var_8_1, d_var_8_2, d_var_8_3, d_var_8_4, d_var_8_5, d_var_8_6, d_var_8_7, d_var_8_8, d_var_8_9, d_var_8_10, d_var_8_11, d_var_8_12, d_var_8_13, d_var_8_14, d_var_8_15, d_var_8_16, d_var_8_17, d_var_8_18, d_var_8_19); + + kernel_9<<<10, 10>>>(d_var_9_0, d_var_9_1, d_var_9_2, d_var_9_3, d_var_9_4, d_var_9_5, d_var_9_6, d_var_9_7, d_var_9_8, d_var_9_9, d_var_9_10, d_var_9_11, d_var_9_12, d_var_9_13, d_var_9_14, d_var_9_15, d_var_9_16, d_var_9_17, d_var_9_18, d_var_9_19); + + kernel_10<<<10, 10>>>(d_var_10_0, d_var_10_1, d_var_10_2, d_var_10_3, d_var_10_4, d_var_10_5, d_var_10_6, d_var_10_7, d_var_10_8, d_var_10_9, d_var_10_10, d_var_10_11, d_var_10_12, d_var_10_13, d_var_10_14, d_var_10_15, d_var_10_16, d_var_10_17, d_var_10_18, d_var_10_19); + + kernel_11<<<10, 10>>>(d_var_11_0, d_var_11_1, d_var_11_2, d_var_11_3, d_var_11_4, d_var_11_5, d_var_11_6, d_var_11_7, d_var_11_8, d_var_11_9, d_var_11_10, d_var_11_11, d_var_11_12, d_var_11_13, d_var_11_14, d_var_11_15, d_var_11_16, d_var_11_17, d_var_11_18, d_var_11_19); + + kernel_12<<<10, 10>>>(d_var_12_0, d_var_12_1, d_var_12_2, d_var_12_3, d_var_12_4, d_var_12_5, d_var_12_6, d_var_12_7, d_var_12_8, d_var_12_9, d_var_12_10, d_var_12_11, d_var_12_12, d_var_12_13, d_var_12_14, d_var_12_15, d_var_12_16, d_var_12_17, d_var_12_18, d_var_12_19); + + kernel_13<<<10, 10>>>(d_var_13_0, d_var_13_1, d_var_13_2, d_var_13_3, d_var_13_4, d_var_13_5, d_var_13_6, d_var_13_7, d_var_13_8, d_var_13_9, d_var_13_10, d_var_13_11, d_var_13_12, d_var_13_13, d_var_13_14, d_var_13_15, d_var_13_16, d_var_13_17, d_var_13_18, d_var_13_19); + + kernel_14<<<10, 10>>>(d_var_14_0, d_var_14_1, d_var_14_2, d_var_14_3, d_var_14_4, d_var_14_5, d_var_14_6, d_var_14_7, d_var_14_8, d_var_14_9, d_var_14_10, d_var_14_11, d_var_14_12, d_var_14_13, d_var_14_14, d_var_14_15, d_var_14_16, d_var_14_17, d_var_14_18, d_var_14_19); + + kernel_15<<<10, 10>>>(d_var_15_0, d_var_15_1, d_var_15_2, d_var_15_3, d_var_15_4, d_var_15_5, d_var_15_6, d_var_15_7, d_var_15_8, d_var_15_9, d_var_15_10, d_var_15_11, d_var_15_12, d_var_15_13, d_var_15_14, d_var_15_15, d_var_15_16, d_var_15_17, d_var_15_18, d_var_15_19); + + kernel_16<<<10, 10>>>(d_var_16_0, d_var_16_1, d_var_16_2, d_var_16_3, d_var_16_4, d_var_16_5, d_var_16_6, d_var_16_7, d_var_16_8, d_var_16_9, d_var_16_10, d_var_16_11, d_var_16_12, d_var_16_13, d_var_16_14, d_var_16_15, d_var_16_16, d_var_16_17, d_var_16_18, d_var_16_19); + + kernel_17<<<10, 10>>>(d_var_17_0, d_var_17_1, d_var_17_2, d_var_17_3, d_var_17_4, d_var_17_5, d_var_17_6, d_var_17_7, d_var_17_8, d_var_17_9, d_var_17_10, d_var_17_11, d_var_17_12, d_var_17_13, d_var_17_14, d_var_17_15, d_var_17_16, d_var_17_17, d_var_17_18, d_var_17_19); + + kernel_18<<<10, 10>>>(d_var_18_0, d_var_18_1, d_var_18_2, d_var_18_3, d_var_18_4, d_var_18_5, d_var_18_6, d_var_18_7, d_var_18_8, d_var_18_9, d_var_18_10, d_var_18_11, d_var_18_12, d_var_18_13, d_var_18_14, d_var_18_15, d_var_18_16, d_var_18_17, d_var_18_18, d_var_18_19); + + kernel_19<<<10, 10>>>(d_var_19_0, d_var_19_1, d_var_19_2, d_var_19_3, d_var_19_4, d_var_19_5, d_var_19_6, d_var_19_7, d_var_19_8, d_var_19_9, d_var_19_10, d_var_19_11, d_var_19_12, d_var_19_13, d_var_19_14, d_var_19_15, d_var_19_16, d_var_19_17, d_var_19_18, d_var_19_19); + + kernel_20<<<10, 10>>>(d_var_20_0, d_var_20_1, d_var_20_2, d_var_20_3, d_var_20_4, d_var_20_5, d_var_20_6, d_var_20_7, d_var_20_8, d_var_20_9, d_var_20_10, d_var_20_11, d_var_20_12, d_var_20_13, d_var_20_14, d_var_20_15, d_var_20_16, d_var_20_17, d_var_20_18, d_var_20_19); + + kernel_21<<<10, 10>>>(d_var_21_0, d_var_21_1, d_var_21_2, d_var_21_3, d_var_21_4, d_var_21_5, d_var_21_6, d_var_21_7, d_var_21_8, d_var_21_9, d_var_21_10, d_var_21_11, d_var_21_12, d_var_21_13, d_var_21_14, d_var_21_15, d_var_21_16, d_var_21_17, d_var_21_18, d_var_21_19); + + kernel_22<<<10, 10>>>(d_var_22_0, d_var_22_1, d_var_22_2, d_var_22_3, d_var_22_4, d_var_22_5, d_var_22_6, d_var_22_7, d_var_22_8, d_var_22_9, d_var_22_10, d_var_22_11, d_var_22_12, d_var_22_13, d_var_22_14, d_var_22_15, d_var_22_16, d_var_22_17, d_var_22_18, d_var_22_19); + + kernel_23<<<10, 10>>>(d_var_23_0, d_var_23_1, d_var_23_2, d_var_23_3, d_var_23_4, d_var_23_5, d_var_23_6, d_var_23_7, d_var_23_8, d_var_23_9, d_var_23_10, d_var_23_11, d_var_23_12, d_var_23_13, d_var_23_14, d_var_23_15, d_var_23_16, d_var_23_17, d_var_23_18, d_var_23_19); + + kernel_24<<<10, 10>>>(d_var_24_0, d_var_24_1, d_var_24_2, d_var_24_3, d_var_24_4, d_var_24_5, d_var_24_6, d_var_24_7, d_var_24_8, d_var_24_9, d_var_24_10, d_var_24_11, d_var_24_12, d_var_24_13, d_var_24_14, d_var_24_15, d_var_24_16, d_var_24_17, d_var_24_18, d_var_24_19); + + kernel_25<<<10, 10>>>(d_var_25_0, d_var_25_1, d_var_25_2, d_var_25_3, d_var_25_4, d_var_25_5, d_var_25_6, d_var_25_7, d_var_25_8, d_var_25_9, d_var_25_10, d_var_25_11, d_var_25_12, d_var_25_13, d_var_25_14, d_var_25_15, d_var_25_16, d_var_25_17, d_var_25_18, d_var_25_19); + + kernel_26<<<10, 10>>>(d_var_26_0, d_var_26_1, d_var_26_2, d_var_26_3, d_var_26_4, d_var_26_5, d_var_26_6, d_var_26_7, d_var_26_8, d_var_26_9, d_var_26_10, d_var_26_11, d_var_26_12, d_var_26_13, d_var_26_14, d_var_26_15, d_var_26_16, d_var_26_17, d_var_26_18, d_var_26_19); + + kernel_27<<<10, 10>>>(d_var_27_0, d_var_27_1, d_var_27_2, d_var_27_3, d_var_27_4, d_var_27_5, d_var_27_6, d_var_27_7, d_var_27_8, d_var_27_9, d_var_27_10, d_var_27_11, d_var_27_12, d_var_27_13, d_var_27_14, d_var_27_15, d_var_27_16, d_var_27_17, d_var_27_18, d_var_27_19); + + kernel_28<<<10, 10>>>(d_var_28_0, d_var_28_1, d_var_28_2, d_var_28_3, d_var_28_4, d_var_28_5, d_var_28_6, d_var_28_7, d_var_28_8, d_var_28_9, d_var_28_10, d_var_28_11, d_var_28_12, d_var_28_13, d_var_28_14, d_var_28_15, d_var_28_16, d_var_28_17, d_var_28_18, d_var_28_19); + + kernel_29<<<10, 10>>>(d_var_29_0, d_var_29_1, d_var_29_2, d_var_29_3, d_var_29_4, d_var_29_5, d_var_29_6, d_var_29_7, d_var_29_8, d_var_29_9, d_var_29_10, d_var_29_11, d_var_29_12, d_var_29_13, d_var_29_14, d_var_29_15, d_var_29_16, d_var_29_17, d_var_29_18, d_var_29_19); + + kernel_30<<<10, 10>>>(d_var_30_0, d_var_30_1, d_var_30_2, d_var_30_3, d_var_30_4, d_var_30_5, d_var_30_6, d_var_30_7, d_var_30_8, d_var_30_9, d_var_30_10, d_var_30_11, d_var_30_12, d_var_30_13, d_var_30_14, d_var_30_15, d_var_30_16, d_var_30_17, d_var_30_18, d_var_30_19); + + kernel_31<<<10, 10>>>(d_var_31_0, d_var_31_1, d_var_31_2, d_var_31_3, d_var_31_4, d_var_31_5, d_var_31_6, d_var_31_7, d_var_31_8, d_var_31_9, d_var_31_10, d_var_31_11, d_var_31_12, d_var_31_13, d_var_31_14, d_var_31_15, d_var_31_16, d_var_31_17, d_var_31_18, d_var_31_19); + + kernel_32<<<10, 10>>>(d_var_32_0, d_var_32_1, d_var_32_2, d_var_32_3, d_var_32_4, d_var_32_5, d_var_32_6, d_var_32_7, d_var_32_8, d_var_32_9, d_var_32_10, d_var_32_11, d_var_32_12, d_var_32_13, d_var_32_14, d_var_32_15, d_var_32_16, d_var_32_17, d_var_32_18, d_var_32_19); + + kernel_33<<<10, 10>>>(d_var_33_0, d_var_33_1, d_var_33_2, d_var_33_3, d_var_33_4, d_var_33_5, d_var_33_6, d_var_33_7, d_var_33_8, d_var_33_9, d_var_33_10, d_var_33_11, d_var_33_12, d_var_33_13, d_var_33_14, d_var_33_15, d_var_33_16, d_var_33_17, d_var_33_18, d_var_33_19); + + kernel_34<<<10, 10>>>(d_var_34_0, d_var_34_1, d_var_34_2, d_var_34_3, d_var_34_4, d_var_34_5, d_var_34_6, d_var_34_7, d_var_34_8, d_var_34_9, d_var_34_10, d_var_34_11, d_var_34_12, d_var_34_13, d_var_34_14, d_var_34_15, d_var_34_16, d_var_34_17, d_var_34_18, d_var_34_19); + + kernel_35<<<10, 10>>>(d_var_35_0, d_var_35_1, d_var_35_2, d_var_35_3, d_var_35_4, d_var_35_5, d_var_35_6, d_var_35_7, d_var_35_8, d_var_35_9, d_var_35_10, d_var_35_11, d_var_35_12, d_var_35_13, d_var_35_14, d_var_35_15, d_var_35_16, d_var_35_17, d_var_35_18, d_var_35_19); + + kernel_36<<<10, 10>>>(d_var_36_0, d_var_36_1, d_var_36_2, d_var_36_3, d_var_36_4, d_var_36_5, d_var_36_6, d_var_36_7, d_var_36_8, d_var_36_9, d_var_36_10, d_var_36_11, d_var_36_12, d_var_36_13, d_var_36_14, d_var_36_15, d_var_36_16, d_var_36_17, d_var_36_18, d_var_36_19); + + kernel_37<<<10, 10>>>(d_var_37_0, d_var_37_1, d_var_37_2, d_var_37_3, d_var_37_4, d_var_37_5, d_var_37_6, d_var_37_7, d_var_37_8, d_var_37_9, d_var_37_10, d_var_37_11, d_var_37_12, d_var_37_13, d_var_37_14, d_var_37_15, d_var_37_16, d_var_37_17, d_var_37_18, d_var_37_19); + + kernel_38<<<10, 10>>>(d_var_38_0, d_var_38_1, d_var_38_2, d_var_38_3, d_var_38_4, d_var_38_5, d_var_38_6, d_var_38_7, d_var_38_8, d_var_38_9, d_var_38_10, d_var_38_11, d_var_38_12, d_var_38_13, d_var_38_14, d_var_38_15, d_var_38_16, d_var_38_17, d_var_38_18, d_var_38_19); + + kernel_39<<<10, 10>>>(d_var_39_0, d_var_39_1, d_var_39_2, d_var_39_3, d_var_39_4, d_var_39_5, d_var_39_6, d_var_39_7, d_var_39_8, d_var_39_9, d_var_39_10, d_var_39_11, d_var_39_12, d_var_39_13, d_var_39_14, d_var_39_15, d_var_39_16, d_var_39_17, d_var_39_18, d_var_39_19); + + kernel_40<<<10, 10>>>(d_var_40_0, d_var_40_1, d_var_40_2, d_var_40_3, d_var_40_4, d_var_40_5, d_var_40_6, d_var_40_7, d_var_40_8, d_var_40_9, d_var_40_10, d_var_40_11, d_var_40_12, d_var_40_13, d_var_40_14, d_var_40_15, d_var_40_16, d_var_40_17, d_var_40_18, d_var_40_19); + + kernel_41<<<10, 10>>>(d_var_41_0, d_var_41_1, d_var_41_2, d_var_41_3, d_var_41_4, d_var_41_5, d_var_41_6, d_var_41_7, d_var_41_8, d_var_41_9, d_var_41_10, d_var_41_11, d_var_41_12, d_var_41_13, d_var_41_14, d_var_41_15, d_var_41_16, d_var_41_17, d_var_41_18, d_var_41_19); + + kernel_42<<<10, 10>>>(d_var_42_0, d_var_42_1, d_var_42_2, d_var_42_3, d_var_42_4, d_var_42_5, d_var_42_6, d_var_42_7, d_var_42_8, d_var_42_9, d_var_42_10, d_var_42_11, d_var_42_12, d_var_42_13, d_var_42_14, d_var_42_15, d_var_42_16, d_var_42_17, d_var_42_18, d_var_42_19); + + kernel_43<<<10, 10>>>(d_var_43_0, d_var_43_1, d_var_43_2, d_var_43_3, d_var_43_4, d_var_43_5, d_var_43_6, d_var_43_7, d_var_43_8, d_var_43_9, d_var_43_10, d_var_43_11, d_var_43_12, d_var_43_13, d_var_43_14, d_var_43_15, d_var_43_16, d_var_43_17, d_var_43_18, d_var_43_19); + + kernel_44<<<10, 10>>>(d_var_44_0, d_var_44_1, d_var_44_2, d_var_44_3, d_var_44_4, d_var_44_5, d_var_44_6, d_var_44_7, d_var_44_8, d_var_44_9, d_var_44_10, d_var_44_11, d_var_44_12, d_var_44_13, d_var_44_14, d_var_44_15, d_var_44_16, d_var_44_17, d_var_44_18, d_var_44_19); + + kernel_45<<<10, 10>>>(d_var_45_0, d_var_45_1, d_var_45_2, d_var_45_3, d_var_45_4, d_var_45_5, d_var_45_6, d_var_45_7, d_var_45_8, d_var_45_9, d_var_45_10, d_var_45_11, d_var_45_12, d_var_45_13, d_var_45_14, d_var_45_15, d_var_45_16, d_var_45_17, d_var_45_18, d_var_45_19); + + kernel_46<<<10, 10>>>(d_var_46_0, d_var_46_1, d_var_46_2, d_var_46_3, d_var_46_4, d_var_46_5, d_var_46_6, d_var_46_7, d_var_46_8, d_var_46_9, d_var_46_10, d_var_46_11, d_var_46_12, d_var_46_13, d_var_46_14, d_var_46_15, d_var_46_16, d_var_46_17, d_var_46_18, d_var_46_19); + + kernel_47<<<10, 10>>>(d_var_47_0, d_var_47_1, d_var_47_2, d_var_47_3, d_var_47_4, d_var_47_5, d_var_47_6, d_var_47_7, d_var_47_8, d_var_47_9, d_var_47_10, d_var_47_11, d_var_47_12, d_var_47_13, d_var_47_14, d_var_47_15, d_var_47_16, d_var_47_17, d_var_47_18, d_var_47_19); + + kernel_48<<<10, 10>>>(d_var_48_0, d_var_48_1, d_var_48_2, d_var_48_3, d_var_48_4, d_var_48_5, d_var_48_6, d_var_48_7, d_var_48_8, d_var_48_9, d_var_48_10, d_var_48_11, d_var_48_12, d_var_48_13, d_var_48_14, d_var_48_15, d_var_48_16, d_var_48_17, d_var_48_18, d_var_48_19); + + kernel_49<<<10, 10>>>(d_var_49_0, d_var_49_1, d_var_49_2, d_var_49_3, d_var_49_4, d_var_49_5, d_var_49_6, d_var_49_7, d_var_49_8, d_var_49_9, d_var_49_10, d_var_49_11, d_var_49_12, d_var_49_13, d_var_49_14, d_var_49_15, d_var_49_16, d_var_49_17, d_var_49_18, d_var_49_19); + + kernel_50<<<10, 10>>>(d_var_50_0, d_var_50_1, d_var_50_2, d_var_50_3, d_var_50_4, d_var_50_5, d_var_50_6, d_var_50_7, d_var_50_8, d_var_50_9, d_var_50_10, d_var_50_11, d_var_50_12, d_var_50_13, d_var_50_14, d_var_50_15, d_var_50_16, d_var_50_17, d_var_50_18, d_var_50_19); + + kernel_51<<<10, 10>>>(d_var_51_0, d_var_51_1, d_var_51_2, d_var_51_3, d_var_51_4, d_var_51_5, d_var_51_6, d_var_51_7, d_var_51_8, d_var_51_9, d_var_51_10, d_var_51_11, d_var_51_12, d_var_51_13, d_var_51_14, d_var_51_15, d_var_51_16, d_var_51_17, d_var_51_18, d_var_51_19); + + kernel_52<<<10, 10>>>(d_var_52_0, d_var_52_1, d_var_52_2, d_var_52_3, d_var_52_4, d_var_52_5, d_var_52_6, d_var_52_7, d_var_52_8, d_var_52_9, d_var_52_10, d_var_52_11, d_var_52_12, d_var_52_13, d_var_52_14, d_var_52_15, d_var_52_16, d_var_52_17, d_var_52_18, d_var_52_19); + + kernel_53<<<10, 10>>>(d_var_53_0, d_var_53_1, d_var_53_2, d_var_53_3, d_var_53_4, d_var_53_5, d_var_53_6, d_var_53_7, d_var_53_8, d_var_53_9, d_var_53_10, d_var_53_11, d_var_53_12, d_var_53_13, d_var_53_14, d_var_53_15, d_var_53_16, d_var_53_17, d_var_53_18, d_var_53_19); + + kernel_54<<<10, 10>>>(d_var_54_0, d_var_54_1, d_var_54_2, d_var_54_3, d_var_54_4, d_var_54_5, d_var_54_6, d_var_54_7, d_var_54_8, d_var_54_9, d_var_54_10, d_var_54_11, d_var_54_12, d_var_54_13, d_var_54_14, d_var_54_15, d_var_54_16, d_var_54_17, d_var_54_18, d_var_54_19); + + kernel_55<<<10, 10>>>(d_var_55_0, d_var_55_1, d_var_55_2, d_var_55_3, d_var_55_4, d_var_55_5, d_var_55_6, d_var_55_7, d_var_55_8, d_var_55_9, d_var_55_10, d_var_55_11, d_var_55_12, d_var_55_13, d_var_55_14, d_var_55_15, d_var_55_16, d_var_55_17, d_var_55_18, d_var_55_19); + + kernel_56<<<10, 10>>>(d_var_56_0, d_var_56_1, d_var_56_2, d_var_56_3, d_var_56_4, d_var_56_5, d_var_56_6, d_var_56_7, d_var_56_8, d_var_56_9, d_var_56_10, d_var_56_11, d_var_56_12, d_var_56_13, d_var_56_14, d_var_56_15, d_var_56_16, d_var_56_17, d_var_56_18, d_var_56_19); + + kernel_57<<<10, 10>>>(d_var_57_0, d_var_57_1, d_var_57_2, d_var_57_3, d_var_57_4, d_var_57_5, d_var_57_6, d_var_57_7, d_var_57_8, d_var_57_9, d_var_57_10, d_var_57_11, d_var_57_12, d_var_57_13, d_var_57_14, d_var_57_15, d_var_57_16, d_var_57_17, d_var_57_18, d_var_57_19); + + kernel_58<<<10, 10>>>(d_var_58_0, d_var_58_1, d_var_58_2, d_var_58_3, d_var_58_4, d_var_58_5, d_var_58_6, d_var_58_7, d_var_58_8, d_var_58_9, d_var_58_10, d_var_58_11, d_var_58_12, d_var_58_13, d_var_58_14, d_var_58_15, d_var_58_16, d_var_58_17, d_var_58_18, d_var_58_19); + + kernel_59<<<10, 10>>>(d_var_59_0, d_var_59_1, d_var_59_2, d_var_59_3, d_var_59_4, d_var_59_5, d_var_59_6, d_var_59_7, d_var_59_8, d_var_59_9, d_var_59_10, d_var_59_11, d_var_59_12, d_var_59_13, d_var_59_14, d_var_59_15, d_var_59_16, d_var_59_17, d_var_59_18, d_var_59_19); + + kernel_60<<<10, 10>>>(d_var_60_0, d_var_60_1, d_var_60_2, d_var_60_3, d_var_60_4, d_var_60_5, d_var_60_6, d_var_60_7, d_var_60_8, d_var_60_9, d_var_60_10, d_var_60_11, d_var_60_12, d_var_60_13, d_var_60_14, d_var_60_15, d_var_60_16, d_var_60_17, d_var_60_18, d_var_60_19); + + kernel_61<<<10, 10>>>(d_var_61_0, d_var_61_1, d_var_61_2, d_var_61_3, d_var_61_4, d_var_61_5, d_var_61_6, d_var_61_7, d_var_61_8, d_var_61_9, d_var_61_10, d_var_61_11, d_var_61_12, d_var_61_13, d_var_61_14, d_var_61_15, d_var_61_16, d_var_61_17, d_var_61_18, d_var_61_19); + + kernel_62<<<10, 10>>>(d_var_62_0, d_var_62_1, d_var_62_2, d_var_62_3, d_var_62_4, d_var_62_5, d_var_62_6, d_var_62_7, d_var_62_8, d_var_62_9, d_var_62_10, d_var_62_11, d_var_62_12, d_var_62_13, d_var_62_14, d_var_62_15, d_var_62_16, d_var_62_17, d_var_62_18, d_var_62_19); + + kernel_63<<<10, 10>>>(d_var_63_0, d_var_63_1, d_var_63_2, d_var_63_3, d_var_63_4, d_var_63_5, d_var_63_6, d_var_63_7, d_var_63_8, d_var_63_9, d_var_63_10, d_var_63_11, d_var_63_12, d_var_63_13, d_var_63_14, d_var_63_15, d_var_63_16, d_var_63_17, d_var_63_18, d_var_63_19); + + kernel_64<<<10, 10>>>(d_var_64_0, d_var_64_1, d_var_64_2, d_var_64_3, d_var_64_4, d_var_64_5, d_var_64_6, d_var_64_7, d_var_64_8, d_var_64_9, d_var_64_10, d_var_64_11, d_var_64_12, d_var_64_13, d_var_64_14, d_var_64_15, d_var_64_16, d_var_64_17, d_var_64_18, d_var_64_19); + + kernel_65<<<10, 10>>>(d_var_65_0, d_var_65_1, d_var_65_2, d_var_65_3, d_var_65_4, d_var_65_5, d_var_65_6, d_var_65_7, d_var_65_8, d_var_65_9, d_var_65_10, d_var_65_11, d_var_65_12, d_var_65_13, d_var_65_14, d_var_65_15, d_var_65_16, d_var_65_17, d_var_65_18, d_var_65_19); + + kernel_66<<<10, 10>>>(d_var_66_0, d_var_66_1, d_var_66_2, d_var_66_3, d_var_66_4, d_var_66_5, d_var_66_6, d_var_66_7, d_var_66_8, d_var_66_9, d_var_66_10, d_var_66_11, d_var_66_12, d_var_66_13, d_var_66_14, d_var_66_15, d_var_66_16, d_var_66_17, d_var_66_18, d_var_66_19); + + kernel_67<<<10, 10>>>(d_var_67_0, d_var_67_1, d_var_67_2, d_var_67_3, d_var_67_4, d_var_67_5, d_var_67_6, d_var_67_7, d_var_67_8, d_var_67_9, d_var_67_10, d_var_67_11, d_var_67_12, d_var_67_13, d_var_67_14, d_var_67_15, d_var_67_16, d_var_67_17, d_var_67_18, d_var_67_19); + + kernel_68<<<10, 10>>>(d_var_68_0, d_var_68_1, d_var_68_2, d_var_68_3, d_var_68_4, d_var_68_5, d_var_68_6, d_var_68_7, d_var_68_8, d_var_68_9, d_var_68_10, d_var_68_11, d_var_68_12, d_var_68_13, d_var_68_14, d_var_68_15, d_var_68_16, d_var_68_17, d_var_68_18, d_var_68_19); + + kernel_69<<<10, 10>>>(d_var_69_0, d_var_69_1, d_var_69_2, d_var_69_3, d_var_69_4, d_var_69_5, d_var_69_6, d_var_69_7, d_var_69_8, d_var_69_9, d_var_69_10, d_var_69_11, d_var_69_12, d_var_69_13, d_var_69_14, d_var_69_15, d_var_69_16, d_var_69_17, d_var_69_18, d_var_69_19); + + kernel_70<<<10, 10>>>(d_var_70_0, d_var_70_1, d_var_70_2, d_var_70_3, d_var_70_4, d_var_70_5, d_var_70_6, d_var_70_7, d_var_70_8, d_var_70_9, d_var_70_10, d_var_70_11, d_var_70_12, d_var_70_13, d_var_70_14, d_var_70_15, d_var_70_16, d_var_70_17, d_var_70_18, d_var_70_19); + + kernel_71<<<10, 10>>>(d_var_71_0, d_var_71_1, d_var_71_2, d_var_71_3, d_var_71_4, d_var_71_5, d_var_71_6, d_var_71_7, d_var_71_8, d_var_71_9, d_var_71_10, d_var_71_11, d_var_71_12, d_var_71_13, d_var_71_14, d_var_71_15, d_var_71_16, d_var_71_17, d_var_71_18, d_var_71_19); + + kernel_72<<<10, 10>>>(d_var_72_0, d_var_72_1, d_var_72_2, d_var_72_3, d_var_72_4, d_var_72_5, d_var_72_6, d_var_72_7, d_var_72_8, d_var_72_9, d_var_72_10, d_var_72_11, d_var_72_12, d_var_72_13, d_var_72_14, d_var_72_15, d_var_72_16, d_var_72_17, d_var_72_18, d_var_72_19); + + kernel_73<<<10, 10>>>(d_var_73_0, d_var_73_1, d_var_73_2, d_var_73_3, d_var_73_4, d_var_73_5, d_var_73_6, d_var_73_7, d_var_73_8, d_var_73_9, d_var_73_10, d_var_73_11, d_var_73_12, d_var_73_13, d_var_73_14, d_var_73_15, d_var_73_16, d_var_73_17, d_var_73_18, d_var_73_19); + + kernel_74<<<10, 10>>>(d_var_74_0, d_var_74_1, d_var_74_2, d_var_74_3, d_var_74_4, d_var_74_5, d_var_74_6, d_var_74_7, d_var_74_8, d_var_74_9, d_var_74_10, d_var_74_11, d_var_74_12, d_var_74_13, d_var_74_14, d_var_74_15, d_var_74_16, d_var_74_17, d_var_74_18, d_var_74_19); + + kernel_75<<<10, 10>>>(d_var_75_0, d_var_75_1, d_var_75_2, d_var_75_3, d_var_75_4, d_var_75_5, d_var_75_6, d_var_75_7, d_var_75_8, d_var_75_9, d_var_75_10, d_var_75_11, d_var_75_12, d_var_75_13, d_var_75_14, d_var_75_15, d_var_75_16, d_var_75_17, d_var_75_18, d_var_75_19); + + kernel_76<<<10, 10>>>(d_var_76_0, d_var_76_1, d_var_76_2, d_var_76_3, d_var_76_4, d_var_76_5, d_var_76_6, d_var_76_7, d_var_76_8, d_var_76_9, d_var_76_10, d_var_76_11, d_var_76_12, d_var_76_13, d_var_76_14, d_var_76_15, d_var_76_16, d_var_76_17, d_var_76_18, d_var_76_19); + + kernel_77<<<10, 10>>>(d_var_77_0, d_var_77_1, d_var_77_2, d_var_77_3, d_var_77_4, d_var_77_5, d_var_77_6, d_var_77_7, d_var_77_8, d_var_77_9, d_var_77_10, d_var_77_11, d_var_77_12, d_var_77_13, d_var_77_14, d_var_77_15, d_var_77_16, d_var_77_17, d_var_77_18, d_var_77_19); + + kernel_78<<<10, 10>>>(d_var_78_0, d_var_78_1, d_var_78_2, d_var_78_3, d_var_78_4, d_var_78_5, d_var_78_6, d_var_78_7, d_var_78_8, d_var_78_9, d_var_78_10, d_var_78_11, d_var_78_12, d_var_78_13, d_var_78_14, d_var_78_15, d_var_78_16, d_var_78_17, d_var_78_18, d_var_78_19); + + kernel_79<<<10, 10>>>(d_var_79_0, d_var_79_1, d_var_79_2, d_var_79_3, d_var_79_4, d_var_79_5, d_var_79_6, d_var_79_7, d_var_79_8, d_var_79_9, d_var_79_10, d_var_79_11, d_var_79_12, d_var_79_13, d_var_79_14, d_var_79_15, d_var_79_16, d_var_79_17, d_var_79_18, d_var_79_19); + + kernel_80<<<10, 10>>>(d_var_80_0, d_var_80_1, d_var_80_2, d_var_80_3, d_var_80_4, d_var_80_5, d_var_80_6, d_var_80_7, d_var_80_8, d_var_80_9, d_var_80_10, d_var_80_11, d_var_80_12, d_var_80_13, d_var_80_14, d_var_80_15, d_var_80_16, d_var_80_17, d_var_80_18, d_var_80_19); + + kernel_81<<<10, 10>>>(d_var_81_0, d_var_81_1, d_var_81_2, d_var_81_3, d_var_81_4, d_var_81_5, d_var_81_6, d_var_81_7, d_var_81_8, d_var_81_9, d_var_81_10, d_var_81_11, d_var_81_12, d_var_81_13, d_var_81_14, d_var_81_15, d_var_81_16, d_var_81_17, d_var_81_18, d_var_81_19); + + kernel_82<<<10, 10>>>(d_var_82_0, d_var_82_1, d_var_82_2, d_var_82_3, d_var_82_4, d_var_82_5, d_var_82_6, d_var_82_7, d_var_82_8, d_var_82_9, d_var_82_10, d_var_82_11, d_var_82_12, d_var_82_13, d_var_82_14, d_var_82_15, d_var_82_16, d_var_82_17, d_var_82_18, d_var_82_19); + + kernel_83<<<10, 10>>>(d_var_83_0, d_var_83_1, d_var_83_2, d_var_83_3, d_var_83_4, d_var_83_5, d_var_83_6, d_var_83_7, d_var_83_8, d_var_83_9, d_var_83_10, d_var_83_11, d_var_83_12, d_var_83_13, d_var_83_14, d_var_83_15, d_var_83_16, d_var_83_17, d_var_83_18, d_var_83_19); + + kernel_84<<<10, 10>>>(d_var_84_0, d_var_84_1, d_var_84_2, d_var_84_3, d_var_84_4, d_var_84_5, d_var_84_6, d_var_84_7, d_var_84_8, d_var_84_9, d_var_84_10, d_var_84_11, d_var_84_12, d_var_84_13, d_var_84_14, d_var_84_15, d_var_84_16, d_var_84_17, d_var_84_18, d_var_84_19); + + kernel_85<<<10, 10>>>(d_var_85_0, d_var_85_1, d_var_85_2, d_var_85_3, d_var_85_4, d_var_85_5, d_var_85_6, d_var_85_7, d_var_85_8, d_var_85_9, d_var_85_10, d_var_85_11, d_var_85_12, d_var_85_13, d_var_85_14, d_var_85_15, d_var_85_16, d_var_85_17, d_var_85_18, d_var_85_19); + + kernel_86<<<10, 10>>>(d_var_86_0, d_var_86_1, d_var_86_2, d_var_86_3, d_var_86_4, d_var_86_5, d_var_86_6, d_var_86_7, d_var_86_8, d_var_86_9, d_var_86_10, d_var_86_11, d_var_86_12, d_var_86_13, d_var_86_14, d_var_86_15, d_var_86_16, d_var_86_17, d_var_86_18, d_var_86_19); + + kernel_87<<<10, 10>>>(d_var_87_0, d_var_87_1, d_var_87_2, d_var_87_3, d_var_87_4, d_var_87_5, d_var_87_6, d_var_87_7, d_var_87_8, d_var_87_9, d_var_87_10, d_var_87_11, d_var_87_12, d_var_87_13, d_var_87_14, d_var_87_15, d_var_87_16, d_var_87_17, d_var_87_18, d_var_87_19); + + kernel_88<<<10, 10>>>(d_var_88_0, d_var_88_1, d_var_88_2, d_var_88_3, d_var_88_4, d_var_88_5, d_var_88_6, d_var_88_7, d_var_88_8, d_var_88_9, d_var_88_10, d_var_88_11, d_var_88_12, d_var_88_13, d_var_88_14, d_var_88_15, d_var_88_16, d_var_88_17, d_var_88_18, d_var_88_19); + + kernel_89<<<10, 10>>>(d_var_89_0, d_var_89_1, d_var_89_2, d_var_89_3, d_var_89_4, d_var_89_5, d_var_89_6, d_var_89_7, d_var_89_8, d_var_89_9, d_var_89_10, d_var_89_11, d_var_89_12, d_var_89_13, d_var_89_14, d_var_89_15, d_var_89_16, d_var_89_17, d_var_89_18, d_var_89_19); + + kernel_90<<<10, 10>>>(d_var_90_0, d_var_90_1, d_var_90_2, d_var_90_3, d_var_90_4, d_var_90_5, d_var_90_6, d_var_90_7, d_var_90_8, d_var_90_9, d_var_90_10, d_var_90_11, d_var_90_12, d_var_90_13, d_var_90_14, d_var_90_15, d_var_90_16, d_var_90_17, d_var_90_18, d_var_90_19); + + kernel_91<<<10, 10>>>(d_var_91_0, d_var_91_1, d_var_91_2, d_var_91_3, d_var_91_4, d_var_91_5, d_var_91_6, d_var_91_7, d_var_91_8, d_var_91_9, d_var_91_10, d_var_91_11, d_var_91_12, d_var_91_13, d_var_91_14, d_var_91_15, d_var_91_16, d_var_91_17, d_var_91_18, d_var_91_19); + + kernel_92<<<10, 10>>>(d_var_92_0, d_var_92_1, d_var_92_2, d_var_92_3, d_var_92_4, d_var_92_5, d_var_92_6, d_var_92_7, d_var_92_8, d_var_92_9, d_var_92_10, d_var_92_11, d_var_92_12, d_var_92_13, d_var_92_14, d_var_92_15, d_var_92_16, d_var_92_17, d_var_92_18, d_var_92_19); + + kernel_93<<<10, 10>>>(d_var_93_0, d_var_93_1, d_var_93_2, d_var_93_3, d_var_93_4, d_var_93_5, d_var_93_6, d_var_93_7, d_var_93_8, d_var_93_9, d_var_93_10, d_var_93_11, d_var_93_12, d_var_93_13, d_var_93_14, d_var_93_15, d_var_93_16, d_var_93_17, d_var_93_18, d_var_93_19); + + kernel_94<<<10, 10>>>(d_var_94_0, d_var_94_1, d_var_94_2, d_var_94_3, d_var_94_4, d_var_94_5, d_var_94_6, d_var_94_7, d_var_94_8, d_var_94_9, d_var_94_10, d_var_94_11, d_var_94_12, d_var_94_13, d_var_94_14, d_var_94_15, d_var_94_16, d_var_94_17, d_var_94_18, d_var_94_19); + + kernel_95<<<10, 10>>>(d_var_95_0, d_var_95_1, d_var_95_2, d_var_95_3, d_var_95_4, d_var_95_5, d_var_95_6, d_var_95_7, d_var_95_8, d_var_95_9, d_var_95_10, d_var_95_11, d_var_95_12, d_var_95_13, d_var_95_14, d_var_95_15, d_var_95_16, d_var_95_17, d_var_95_18, d_var_95_19); + + kernel_96<<<10, 10>>>(d_var_96_0, d_var_96_1, d_var_96_2, d_var_96_3, d_var_96_4, d_var_96_5, d_var_96_6, d_var_96_7, d_var_96_8, d_var_96_9, d_var_96_10, d_var_96_11, d_var_96_12, d_var_96_13, d_var_96_14, d_var_96_15, d_var_96_16, d_var_96_17, d_var_96_18, d_var_96_19); + + kernel_97<<<10, 10>>>(d_var_97_0, d_var_97_1, d_var_97_2, d_var_97_3, d_var_97_4, d_var_97_5, d_var_97_6, d_var_97_7, d_var_97_8, d_var_97_9, d_var_97_10, d_var_97_11, d_var_97_12, d_var_97_13, d_var_97_14, d_var_97_15, d_var_97_16, d_var_97_17, d_var_97_18, d_var_97_19); + + kernel_98<<<10, 10>>>(d_var_98_0, d_var_98_1, d_var_98_2, d_var_98_3, d_var_98_4, d_var_98_5, d_var_98_6, d_var_98_7, d_var_98_8, d_var_98_9, d_var_98_10, d_var_98_11, d_var_98_12, d_var_98_13, d_var_98_14, d_var_98_15, d_var_98_16, d_var_98_17, d_var_98_18, d_var_98_19); + + kernel_99<<<10, 10>>>(d_var_99_0, d_var_99_1, d_var_99_2, d_var_99_3, d_var_99_4, d_var_99_5, d_var_99_6, d_var_99_7, d_var_99_8, d_var_99_9, d_var_99_10, d_var_99_11, d_var_99_12, d_var_99_13, d_var_99_14, d_var_99_15, d_var_99_16, d_var_99_17, d_var_99_18, d_var_99_19); + + // clang-format on + + printf("Done\n"); + return 0; +} diff --git a/pkg/gpu/cuda/testdata/heavy-sample.cu.tmpl b/pkg/gpu/cuda/testdata/heavy-sample.cu.tmpl new file mode 100644 index 0000000000000..9b5a8a89a4911 --- /dev/null +++ b/pkg/gpu/cuda/testdata/heavy-sample.cu.tmpl @@ -0,0 +1,33 @@ +/* AUTO-GENERATED, DO NOT CHANGE */ + +// To regenerate, run `make heavy-sample.cu` in this directory + +#include + +#include + +{{ range .Kernels }} +__global__ void {{ .Name }}({{ .Argdef }}) { + __shared__ float myVar[{{ .SharedMemorySize }}]; + {{ range .Instructions }} + {{- . }} + {{ end }} +} +{{ end }} + +int main(void) { + {{ range .Variables }} + {{ .Type }} h_{{ .Name }} = ({{ .Type }})malloc(sizeof({{ .Type }})); + {{ .Type }} d_{{ .Name }}; + cudaMalloc((void **)&d_{{ .Name }}, sizeof({{ .Type }})); + {{ end }} + + // clang-format off + {{ range .Kernels }} + {{ .Name }}<<<10, 10>>>({{ .Argcall }}); + {{ end }} + // clang-format on + + printf("Done\n"); + return 0; +} diff --git a/pkg/gpu/nvml.go b/pkg/gpu/nvml.go deleted file mode 100644 index 7bc7543cda8ef..0000000000000 --- a/pkg/gpu/nvml.go +++ /dev/null @@ -1,57 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2024-present Datadog, Inc. - -//go:build linux_bpf - -package gpu - -import ( - "errors" - "fmt" - - "github.com/NVIDIA/go-nvml/pkg/nvml" -) - -func wrapNvmlError(ret nvml.Return) error { - if ret == nvml.SUCCESS { - return nil - } - - return errors.New(nvml.ErrorString(ret)) -} - -func getGPUDevices(lib nvml.Interface) ([]nvml.Device, error) { - count, ret := lib.DeviceGetCount() - if err := wrapNvmlError(ret); err != nil { - return nil, fmt.Errorf("cannot get number of GPU devices: %w", err) - } - - var devices []nvml.Device - - for i := 0; i < count; i++ { - device, ret := lib.DeviceGetHandleByIndex(i) - if err := wrapNvmlError(ret); err != nil { - return nil, fmt.Errorf("cannot get handle for GPU device %d: %w", i, err) - } - - devices = append(devices, device) - } - - return devices, nil -} - -// GetMaxThreads returns the maximum number of threads that can be run on the -// GPU. Each GPU core runs a thread, so this is the number of cores. Do not -// confuse the number of cores with the number of streaming multiprocessors -// (SM): the number of cores is equal to the number of SMs multiplied by the -// number of cores per SM. -func getMaxThreadsForDevice(device nvml.Device) (int, error) { - cores, ret := device.GetNumGpuCores() - if err := wrapNvmlError(ret); err != nil { - return 0, fmt.Errorf("cannot get number of GPU cores: %w", err) - } - - return int(cores), nil -} diff --git a/pkg/gpu/probe.go b/pkg/gpu/probe.go index 0a43ae9ae9118..ff9bcfdfebd1d 100644 --- a/pkg/gpu/probe.go +++ b/pkg/gpu/probe.go @@ -22,14 +22,11 @@ import ( ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/ebpf/bytecode" "github.com/DataDog/datadog-agent/pkg/ebpf/uprobes" + "github.com/DataDog/datadog-agent/pkg/gpu/config" "github.com/DataDog/datadog-agent/pkg/process/monitor" - "github.com/DataDog/datadog-agent/pkg/util/kernel" "github.com/DataDog/datadog-agent/pkg/util/log" ) -// TODO: Set a minimum kernel version -var minimumKernelVersion = kernel.VersionCode(5, 8, 0) - const ( cudaEventMap = "cuda_events" cudaAllocCacheMap = "cuda_alloc_cache" @@ -50,24 +47,21 @@ type ProbeDependencies struct { // Probe represents the GPU monitoring probe type Probe struct { mgr *ddebpf.Manager - cfg *Config + cfg *config.Config consumer *cudaEventConsumer attacher *uprobes.UprobeAttacher statsGenerator *statsGenerator deps ProbeDependencies + procMon *monitor.ProcessMonitor } // NewProbe starts the GPU monitoring probe, setting up the eBPF program and the uprobes, the // consumers for the events generated from the uprobes, and the stats generator to aggregate the data from // streams into per-process GPU stats. -func NewProbe(cfg *Config, deps ProbeDependencies) (*Probe, error) { +func NewProbe(cfg *config.Config, deps ProbeDependencies) (*Probe, error) { log.Debugf("starting GPU monitoring probe...") - kv, err := kernel.HostVersion() - if err != nil { - return nil, fmt.Errorf("kernel version: %s", err) - } - if kv < minimumKernelVersion { - return nil, fmt.Errorf("minimum kernel version %s not met, read %s", minimumKernelVersion, kv) + if err := config.CheckGPUSupported(); err != nil { + return nil, err } var probe *Probe @@ -75,7 +69,7 @@ func NewProbe(cfg *Config, deps ProbeDependencies) (*Probe, error) { if cfg.BPFDebug { filename = "gpu-debug.o" } - err = ddebpf.LoadCOREAsset(filename, func(buf bytecode.AssetReader, opts manager.Options) error { + err := ddebpf.LoadCOREAsset(filename, func(buf bytecode.AssetReader, opts manager.Options) error { var err error probe, err = startGPUProbe(buf, opts, deps, cfg) if err != nil { @@ -91,7 +85,7 @@ func NewProbe(cfg *Config, deps ProbeDependencies) (*Probe, error) { return probe, nil } -func startGPUProbe(buf bytecode.AssetReader, opts manager.Options, deps ProbeDependencies, cfg *Config) (*Probe, error) { +func startGPUProbe(buf bytecode.AssetReader, opts manager.Options, deps ProbeDependencies, cfg *config.Config) (*Probe, error) { mgr := ddebpf.NewManagerWithDefault(&manager.Manager{ Maps: []*manager.Map{ {Name: cudaAllocCacheMap}, @@ -146,7 +140,7 @@ func startGPUProbe(buf bytecode.AssetReader, opts manager.Options, deps ProbeDep return nil, fmt.Errorf("error initializing process monitor: %w", err) } - attacher, err := uprobes.NewUprobeAttacher(gpuAttacherName, attachCfg, mgr, nil, &uprobes.NativeBinaryInspector{}) + attacher, err := uprobes.NewUprobeAttacher(gpuAttacherName, attachCfg, mgr, nil, &uprobes.NativeBinaryInspector{}, procMon) if err != nil { return nil, fmt.Errorf("error creating uprobes attacher: %w", err) } @@ -160,6 +154,7 @@ func startGPUProbe(buf bytecode.AssetReader, opts manager.Options, deps ProbeDep cfg: cfg, attacher: attacher, deps: deps, + procMon: procMon, } sysCtx, err := getSystemContext(deps.NvmlLib) @@ -192,6 +187,10 @@ func startGPUProbe(buf bytecode.AssetReader, opts manager.Options, deps ProbeDep // Close stops the probe func (p *Probe) Close() { + if p.procMon != nil { + p.procMon.Stop() + } + if p.attacher != nil { p.attacher.Stop() } diff --git a/pkg/gpu/probe_stub.go b/pkg/gpu/probe_stub.go index f4cbbae2cf57a..b781cc344c8f3 100644 --- a/pkg/gpu/probe_stub.go +++ b/pkg/gpu/probe_stub.go @@ -13,6 +13,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/telemetry" "github.com/DataDog/datadog-agent/pkg/collector/corechecks/gpu/model" "github.com/DataDog/datadog-agent/pkg/ebpf" + "github.com/DataDog/datadog-agent/pkg/gpu/config" ) // ProbeDependencies holds the dependencies for the probe @@ -25,7 +26,7 @@ type ProbeDependencies struct { type Probe struct{} // NewProbe is not implemented on non-linux systems -func NewProbe(_ *Config, _ ProbeDependencies) (*Probe, error) { +func NewProbe(_ *config.Config, _ ProbeDependencies) (*Probe, error) { return nil, ebpf.ErrNotImplemented } diff --git a/pkg/gpu/probe_test.go b/pkg/gpu/probe_test.go index 9357203ba8c6a..b485c0a27b4bb 100644 --- a/pkg/gpu/probe_test.go +++ b/pkg/gpu/probe_test.go @@ -13,21 +13,19 @@ import ( "github.com/stretchr/testify/require" + "github.com/DataDog/datadog-agent/pkg/gpu/config" "github.com/DataDog/datadog-agent/pkg/gpu/testutil" "github.com/DataDog/datadog-agent/pkg/network/usm/utils" "github.com/DataDog/datadog-agent/pkg/process/monitor" - "github.com/DataDog/datadog-agent/pkg/util/kernel" ) func TestProbeCanLoad(t *testing.T) { - kver, err := kernel.HostVersion() - require.NoError(t, err) - if kver < minimumKernelVersion { - t.Skipf("minimum kernel version %s not met, read %s", minimumKernelVersion, kver) + if err := config.CheckGPUSupported(); err != nil { + t.Skipf("minimum kernel version not met, %v", err) } nvmlMock := testutil.GetBasicNvmlMock() - probe, err := NewProbe(NewConfig(), ProbeDependencies{NvmlLib: nvmlMock}) + probe, err := NewProbe(config.NewConfig(), ProbeDependencies{NvmlLib: nvmlMock}) require.NoError(t, err) require.NotNil(t, probe) t.Cleanup(probe.Close) @@ -38,10 +36,8 @@ func TestProbeCanLoad(t *testing.T) { } func TestProbeCanReceiveEvents(t *testing.T) { - kver, err := kernel.HostVersion() - require.NoError(t, err) - if kver < minimumKernelVersion { - t.Skipf("minimum kernel version %s not met, read %s", minimumKernelVersion, kver) + if err := config.CheckGPUSupported(); err != nil { + t.Skipf("minimum kernel version not met, %v", err) } procMon := monitor.GetProcessMonitor() @@ -49,7 +45,7 @@ func TestProbeCanReceiveEvents(t *testing.T) { require.NoError(t, procMon.Initialize(false)) t.Cleanup(procMon.Stop) - cfg := NewConfig() + cfg := config.NewConfig() cfg.InitialProcessSync = false cfg.BPFDebug = true @@ -94,10 +90,8 @@ func TestProbeCanReceiveEvents(t *testing.T) { } func TestProbeCanGenerateStats(t *testing.T) { - kver, err := kernel.HostVersion() - require.NoError(t, err) - if kver < minimumKernelVersion { - t.Skipf("minimum kernel version %s not met, read %s", minimumKernelVersion, kver) + if err := config.CheckGPUSupported(); err != nil { + t.Skipf("minimum kernel version not met, %v", err) } procMon := monitor.GetProcessMonitor() @@ -105,7 +99,7 @@ func TestProbeCanGenerateStats(t *testing.T) { require.NoError(t, procMon.Initialize(false)) t.Cleanup(procMon.Stop) - cfg := NewConfig() + cfg := config.NewConfig() cfg.InitialProcessSync = false cfg.BPFDebug = true diff --git a/pkg/gpu/testutil/builder.go b/pkg/gpu/testutil/builder.go index b287e6c6e9d7f..520a0bc211e90 100644 --- a/pkg/gpu/testutil/builder.go +++ b/pkg/gpu/testutil/builder.go @@ -4,6 +4,9 @@ // Copyright 2024-present Datadog, Inc. // Package testutil contains helpers to build sample C binaries for testing. + +//go:build linux_bpf && test + package testutil import ( diff --git a/pkg/gpu/testutil/mocks.go b/pkg/gpu/testutil/mocks.go index e414973d509c0..76f8da858b4a2 100644 --- a/pkg/gpu/testutil/mocks.go +++ b/pkg/gpu/testutil/mocks.go @@ -5,6 +5,7 @@ //go:build linux +// Package testutil holds different utilities and stubs for testing package testutil import ( diff --git a/pkg/gpu/testutil/samplebins.go b/pkg/gpu/testutil/samplebins.go index 21d245f419969..fa98bfefcb05e 100644 --- a/pkg/gpu/testutil/samplebins.go +++ b/pkg/gpu/testutil/samplebins.go @@ -3,6 +3,8 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2024-present Datadog, Inc. +//go:build linux_bpf && test + package testutil import ( diff --git a/pkg/gpu/tseries.go b/pkg/gpu/tseries.go index 6be767a205f18..2a732220370a5 100644 --- a/pkg/gpu/tseries.go +++ b/pkg/gpu/tseries.go @@ -3,6 +3,8 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2024-present Datadog, Inc. +//go:build linux_bpf + package gpu import ( diff --git a/pkg/gpu/tseries_test.go b/pkg/gpu/tseries_test.go index f7e7c0ee45d8e..2d95100d5c77b 100644 --- a/pkg/gpu/tseries_test.go +++ b/pkg/gpu/tseries_test.go @@ -3,6 +3,8 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2024-present Datadog, Inc. +//go:build linux_bpf + package gpu import ( diff --git a/pkg/logs/internal/tag/provider_test.go b/pkg/logs/internal/tag/provider_test.go index 3b7b361ec550d..9eb0b249ff68d 100644 --- a/pkg/logs/internal/tag/provider_test.go +++ b/pkg/logs/internal/tag/provider_test.go @@ -24,7 +24,7 @@ func TestProviderExpectedTags(t *testing.T) { m := configmock.New(t) clock := clock.NewMock() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + oldStartTime := pkgconfigsetup.StartTime then := clock.Now() pkgconfigsetup.StartTime = then diff --git a/pkg/logs/internal/util/adlistener/ad_test.go b/pkg/logs/internal/util/adlistener/ad_test.go index a0a23b62ea7b2..1ddbc2bf09fd4 100644 --- a/pkg/logs/internal/util/adlistener/ad_test.go +++ b/pkg/logs/internal/util/adlistener/ad_test.go @@ -15,6 +15,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/autodiscovery/autodiscoveryimpl" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/integration" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/scheduler" + "github.com/DataDog/datadog-agent/comp/core/secrets/secretsimpl" "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" @@ -27,6 +28,7 @@ func TestListenersGetScheduleCalls(t *testing.T) { adsched := scheduler.NewController() ac := fxutil.Test[autodiscovery.Mock](t, fx.Supply(autodiscoveryimpl.MockParams{Scheduler: adsched}), + secretsimpl.MockModule(), autodiscoveryimpl.MockModule(), workloadmetafxmock.MockModule(workloadmeta.NewParams()), core.MockBundle(), diff --git a/pkg/logs/launchers/container/launcher_test.go b/pkg/logs/launchers/container/launcher_test.go index fb31bdc69bd25..a4dc9760b65f7 100644 --- a/pkg/logs/launchers/container/launcher_test.go +++ b/pkg/logs/launchers/container/launcher_test.go @@ -38,7 +38,7 @@ func (tf *testFactory) MakeTailer(source *sources.LogSource) (tailerfactory.Tail func TestStartStop(t *testing.T) { fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + l := NewLauncher(nil, optional.NewNoneOption[workloadmeta.Component](), fakeTagger) sp := launchers.NewMockSourceProvider() @@ -58,7 +58,7 @@ func TestStartStop(t *testing.T) { func TestAddsRemovesSource(t *testing.T) { fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + l := NewLauncher(nil, optional.NewNoneOption[workloadmeta.Component](), fakeTagger) l.tailerFactory = &testFactory{ makeTailer: func(source *sources.LogSource) (tailerfactory.Tailer, error) { @@ -89,7 +89,7 @@ func TestAddsRemovesSource(t *testing.T) { func TestCannotMakeTailer(t *testing.T) { fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + l := NewLauncher(nil, optional.NewNoneOption[workloadmeta.Component](), fakeTagger) l.tailerFactory = &testFactory{ makeTailer: func(_ *sources.LogSource) (tailerfactory.Tailer, error) { @@ -112,7 +112,7 @@ func TestCannotMakeTailer(t *testing.T) { func TestCannotStartTailer(t *testing.T) { fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() + l := NewLauncher(nil, optional.NewNoneOption[workloadmeta.Component](), fakeTagger) l.tailerFactory = &testFactory{ makeTailer: func(source *sources.LogSource) (tailerfactory.Tailer, error) { diff --git a/pkg/logs/launchers/file/launcher.go b/pkg/logs/launchers/file/launcher.go index e0c44ca20e6e1..de04ecdbf6ec7 100644 --- a/pkg/logs/launchers/file/launcher.go +++ b/pkg/logs/launchers/file/launcher.go @@ -285,6 +285,8 @@ func (s *Launcher) launchTailers(source *sources.LogSource) { continue } if tailer, isTailed := s.tailers.Get(file.GetScanKey()); isTailed { + // new source inherits the old source's status + source.Status = tailer.Source().Status // the file is already tailed, update the existing tailer's source so that the tailer // uses this new source going forward tailer.ReplaceSource(source) diff --git a/pkg/logs/launchers/file/launcher_test.go b/pkg/logs/launchers/file/launcher_test.go index a0e53f93f7d3b..ca89d36dbbefc 100644 --- a/pkg/logs/launchers/file/launcher_test.go +++ b/pkg/logs/launchers/file/launcher_test.go @@ -89,7 +89,6 @@ func (suite *LauncherTestSuite) TearDownTest() { suite.testFile.Close() suite.testRotatedFile.Close() suite.s.cleanup() - suite.tagger.ResetTagger() } func (suite *LauncherTestSuite) TestLauncherStartsTailers() { @@ -225,7 +224,6 @@ func TestLauncherScanStartNewTailer(t *testing.T) { var path string var msg *message.Message fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() IDs := []string{"", "123456789"} @@ -272,7 +270,6 @@ func TestLauncherWithConcurrentContainerTailer(t *testing.T) { testDir := t.TempDir() path := fmt.Sprintf("%s/container.log", testDir) fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() // create launcher openFilesLimit := 3 @@ -322,7 +319,6 @@ func TestLauncherWithConcurrentContainerTailer(t *testing.T) { func TestLauncherTailFromTheBeginning(t *testing.T) { testDir := t.TempDir() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() // create launcher openFilesLimit := 3 @@ -374,7 +370,6 @@ func TestLauncherTailFromTheBeginning(t *testing.T) { func TestLauncherSetTail(t *testing.T) { testDir := t.TempDir() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() path1 := fmt.Sprintf("%s/test.log", testDir) path2 := fmt.Sprintf("%s/test2.log", testDir) @@ -402,7 +397,6 @@ func TestLauncherSetTail(t *testing.T) { func TestLauncherConfigIdentifier(t *testing.T) { testDir := t.TempDir() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() path := fmt.Sprintf("%s/test.log", testDir) os.Create(path) @@ -428,7 +422,6 @@ func TestLauncherScanWithTooManyFiles(t *testing.T) { testDir := t.TempDir() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() // creates files path = fmt.Sprintf("%s/1.log", testDir) @@ -472,7 +465,6 @@ func TestLauncherScanWithTooManyFiles(t *testing.T) { func TestLauncherUpdatesSourceForExistingTailer(t *testing.T) { testDir := t.TempDir() fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() path := fmt.Sprintf("%s/*.log", testDir) os.Create(path) @@ -523,7 +515,6 @@ func TestLauncherScanRecentFilesWithRemoval(t *testing.T) { assert.Nil(t, err) } fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() createLauncher := func() *Launcher { sleepDuration := 20 * time.Millisecond @@ -579,7 +570,6 @@ func TestLauncherScanRecentFilesWithNewFiles(t *testing.T) { baseTime := time.Date(2010, time.August, 10, 25, 0, 0, 0, time.UTC) openFilesLimit := 2 fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() path := func(name string) string { return fmt.Sprintf("%s/%s", testDir, name) @@ -645,7 +635,6 @@ func TestLauncherFileRotation(t *testing.T) { testDir := t.TempDir() openFilesLimit := 2 fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() path := func(name string) string { return fmt.Sprintf("%s/%s", testDir, name) @@ -712,7 +701,6 @@ func TestLauncherFileDetectionSingleScan(t *testing.T) { testDir := t.TempDir() openFilesLimit := 2 fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() path := func(name string) string { return fmt.Sprintf("%s/%s", testDir, name) diff --git a/pkg/logs/launchers/journald/launcher.go b/pkg/logs/launchers/journald/launcher.go index a96896692c366..b094516a73c96 100644 --- a/pkg/logs/launchers/journald/launcher.go +++ b/pkg/logs/launchers/journald/launcher.go @@ -11,6 +11,9 @@ package journald import ( "os" + "github.com/coreos/go-systemd/sdjournal" + + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/logs/agent/config" flareController "github.com/DataDog/datadog-agent/comp/logs/agent/flare" "github.com/DataDog/datadog-agent/pkg/logs/auditor" @@ -21,7 +24,6 @@ import ( tailer "github.com/DataDog/datadog-agent/pkg/logs/tailers/journald" "github.com/DataDog/datadog-agent/pkg/util/log" "github.com/DataDog/datadog-agent/pkg/util/startstop" - "github.com/coreos/go-systemd/sdjournal" ) // SDJournalFactory is a JournalFactory implementation that produces sdjournal instances @@ -46,20 +48,22 @@ type Launcher struct { stop chan struct{} journalFactory tailer.JournalFactory fc *flareController.FlareController + tagger tagger.Component } // NewLauncher returns a new Launcher. -func NewLauncher(fc *flareController.FlareController) *Launcher { - return NewLauncherWithFactory(&SDJournalFactory{}, fc) +func NewLauncher(fc *flareController.FlareController, tagger tagger.Component) *Launcher { + return NewLauncherWithFactory(&SDJournalFactory{}, fc, tagger) } // NewLauncherWithFactory returns a new Launcher. -func NewLauncherWithFactory(journalFactory tailer.JournalFactory, fc *flareController.FlareController) *Launcher { +func NewLauncherWithFactory(journalFactory tailer.JournalFactory, fc *flareController.FlareController, tagger tagger.Component) *Launcher { return &Launcher{ tailers: make(map[string]*tailer.Tailer), stop: make(chan struct{}), journalFactory: journalFactory, fc: fc, + tagger: tagger, } } @@ -139,7 +143,7 @@ func (l *Launcher) setupTailer(source *sources.LogSource) (*tailer.Tailer, error return nil, err } - tailer := tailer.NewTailer(source, l.pipelineProvider.NextPipelineChan(), journal, source.Config.ShouldProcessRawMessage()) + tailer := tailer.NewTailer(source, l.pipelineProvider.NextPipelineChan(), journal, source.Config.ShouldProcessRawMessage(), l.tagger) cursor := l.registry.GetOffset(tailer.Identifier()) err = tailer.Start(cursor) diff --git a/pkg/logs/launchers/journald/launcher_nosystemd.go b/pkg/logs/launchers/journald/launcher_nosystemd.go index 47ce99e39e453..81490ce621132 100644 --- a/pkg/logs/launchers/journald/launcher_nosystemd.go +++ b/pkg/logs/launchers/journald/launcher_nosystemd.go @@ -9,6 +9,7 @@ package journald import ( + "github.com/DataDog/datadog-agent/comp/core/tagger" flareController "github.com/DataDog/datadog-agent/comp/logs/agent/flare" "github.com/DataDog/datadog-agent/pkg/logs/auditor" "github.com/DataDog/datadog-agent/pkg/logs/launchers" @@ -20,7 +21,7 @@ import ( type Launcher struct{} // NewLauncher returns a new Launcher -func NewLauncher(_ *flareController.FlareController) *Launcher { +func NewLauncher(*flareController.FlareController, tagger.Component) *Launcher { return &Launcher{} } diff --git a/pkg/logs/launchers/journald/launcher_test.go b/pkg/logs/launchers/journald/launcher_test.go index f814025f1e11c..2772be91865f9 100644 --- a/pkg/logs/launchers/journald/launcher_test.go +++ b/pkg/logs/launchers/journald/launcher_test.go @@ -14,6 +14,7 @@ import ( "github.com/coreos/go-systemd/sdjournal" "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/comp/logs/agent/config" "github.com/DataDog/datadog-agent/comp/logs/agent/flare" "github.com/DataDog/datadog-agent/pkg/logs/auditor" @@ -59,14 +60,18 @@ func (s *MockJournalFactory) NewJournalFromPath(path string) (tailer.Journal, er return &MockJournal{}, nil } -func newTestLauncher() *Launcher { - launcher := NewLauncherWithFactory(&MockJournalFactory{}, flare.NewFlareController()) +func newTestLauncher(t *testing.T) *Launcher { + t.Helper() + + fakeTagger := taggerimpl.SetupFakeTagger(t) + + launcher := NewLauncherWithFactory(&MockJournalFactory{}, flare.NewFlareController(), fakeTagger) launcher.Start(launchers.NewMockSourceProvider(), pipeline.NewMockProvider(), auditor.New("", "registry.json", time.Hour, health.RegisterLiveness("fake")), tailers.NewTailerTracker()) return launcher } func TestSingeJournaldConfig(t *testing.T) { - launcher := newTestLauncher() + launcher := newTestLauncher(t) sourceThatShouldWin := sources.NewLogSource("testSource", &config.LogsConfig{}) sourceThatShouldLose := sources.NewLogSource("testSource2", &config.LogsConfig{}) @@ -82,7 +87,7 @@ func TestSingeJournaldConfig(t *testing.T) { } func TestMultipleTailersDifferentPath(t *testing.T) { - launcher := newTestLauncher() + launcher := newTestLauncher(t) launcher.sources <- sources.NewLogSource("testSource", &config.LogsConfig{}) launcher.sources <- sources.NewLogSource("testSource2", &config.LogsConfig{Path: "/foo/bar"}) @@ -93,7 +98,7 @@ func TestMultipleTailersDifferentPath(t *testing.T) { } func TestMultipleTailersOnSamePath(t *testing.T) { - launcher := newTestLauncher() + launcher := newTestLauncher(t) sourceThatShouldWin := sources.NewLogSource("testSource", &config.LogsConfig{Path: "/foo/bar"}) sourceThatShouldLose := sources.NewLogSource("testSource2", &config.LogsConfig{Path: "/foo/bar"}) @@ -109,7 +114,7 @@ func TestMultipleTailersOnSamePath(t *testing.T) { } func TestMultipleTailersSamePathWithId(t *testing.T) { - launcher := newTestLauncher() + launcher := newTestLauncher(t) launcher.sources <- sources.NewLogSource("testSource", &config.LogsConfig{Path: "/foo/bar", ConfigId: "foo"}) launcher.sources <- sources.NewLogSource("testSource2", &config.LogsConfig{Path: "/foo/bar", ConfigId: "bar"}) @@ -120,7 +125,7 @@ func TestMultipleTailersSamePathWithId(t *testing.T) { } func TestMultipleTailersWithId(t *testing.T) { - launcher := newTestLauncher() + launcher := newTestLauncher(t) launcher.sources <- sources.NewLogSource("testSource", &config.LogsConfig{ConfigId: "foo"}) launcher.sources <- sources.NewLogSource("testSource2", &config.LogsConfig{ConfigId: "bar"}) @@ -131,7 +136,7 @@ func TestMultipleTailersWithId(t *testing.T) { } func TestStopLauncher(t *testing.T) { - launcher := newTestLauncher() + launcher := newTestLauncher(t) launcher.sources <- sources.NewLogSource("testSource", &config.LogsConfig{}) launcher.sources <- sources.NewLogSource("testSource2", &config.LogsConfig{Path: "/foo/bar"}) diff --git a/pkg/logs/schedulers/cca/scheduler_test.go b/pkg/logs/schedulers/cca/scheduler_test.go index c32165ef276ed..0d4c884239048 100644 --- a/pkg/logs/schedulers/cca/scheduler_test.go +++ b/pkg/logs/schedulers/cca/scheduler_test.go @@ -15,6 +15,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core" "github.com/DataDog/datadog-agent/comp/core/autodiscovery" "github.com/DataDog/datadog-agent/comp/core/autodiscovery/autodiscoveryimpl" + "github.com/DataDog/datadog-agent/comp/core/secrets/secretsimpl" "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" @@ -28,6 +29,7 @@ import ( func setup(t *testing.T) (scheduler *Scheduler, ac autodiscovery.Component, spy *schedulers.MockSourceManager) { ac = fxutil.Test[autodiscovery.Mock](t, fx.Supply(autodiscoveryimpl.MockParams{}), + secretsimpl.MockModule(), autodiscoveryimpl.MockModule(), workloadmetafxmock.MockModule(workloadmeta.NewParams()), core.MockBundle(), diff --git a/pkg/logs/tailers/journald/docker.go b/pkg/logs/tailers/journald/docker.go index bcc835d341373..9beef0986b666 100644 --- a/pkg/logs/tailers/journald/docker.go +++ b/pkg/logs/tailers/journald/docker.go @@ -11,7 +11,6 @@ package journald import ( "github.com/coreos/go-systemd/sdjournal" - "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/core/tagger/types" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -34,7 +33,7 @@ func (t *Tailer) getContainerID(entry *sdjournal.JournalEntry) string { // getContainerTags returns all the tags of a given container. func (t *Tailer) getContainerTags(containerID string) []string { - tags, err := tagger.Tag(types.NewEntityID(types.ContainerID, containerID), types.HighCardinality) + tags, err := t.tagger.Tag(types.NewEntityID(types.ContainerID, containerID), types.HighCardinality) if err != nil { log.Warn(err) } diff --git a/pkg/logs/tailers/journald/docker_test.go b/pkg/logs/tailers/journald/docker_test.go index 396eb5997f94e..296fe5a88c859 100644 --- a/pkg/logs/tailers/journald/docker_test.go +++ b/pkg/logs/tailers/journald/docker_test.go @@ -13,13 +13,15 @@ import ( "github.com/coreos/go-systemd/sdjournal" "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/comp/logs/agent/config" "github.com/DataDog/datadog-agent/pkg/logs/sources" ) func TestIsContainerEntry(t *testing.T) { source := sources.NewLogSource("", &config.LogsConfig{}) - tailer := NewTailer(source, nil, nil, false) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, nil, false, fakeTagger) var entry *sdjournal.JournalEntry @@ -36,7 +38,8 @@ func TestIsContainerEntry(t *testing.T) { func TestGetContainerID(t *testing.T) { source := sources.NewLogSource("", &config.LogsConfig{}) - tailer := NewTailer(source, nil, nil, false) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, nil, false, fakeTagger) entry := &sdjournal.JournalEntry{ Fields: map[string]string{ diff --git a/pkg/logs/tailers/journald/tailer.go b/pkg/logs/tailers/journald/tailer.go index 281cfa07dc3ea..b2009a0c8f24f 100644 --- a/pkg/logs/tailers/journald/tailer.go +++ b/pkg/logs/tailers/journald/tailer.go @@ -16,6 +16,7 @@ import ( "github.com/coreos/go-systemd/sdjournal" + "github.com/DataDog/datadog-agent/comp/core/tagger" "github.com/DataDog/datadog-agent/comp/logs/agent/config" "github.com/DataDog/datadog-agent/pkg/logs/internal/decoder" "github.com/DataDog/datadog-agent/pkg/logs/internal/framer" @@ -55,10 +56,11 @@ type Tailer struct { // tagProvider provides additional tags to be attached to each log message. It // is called once for each log message. tagProvider tag.Provider + tagger tagger.Component } // NewTailer returns a new tailer. -func NewTailer(source *sources.LogSource, outputChan chan *message.Message, journal Journal, processRawMessage bool) *Tailer { +func NewTailer(source *sources.LogSource, outputChan chan *message.Message, journal Journal, processRawMessage bool, tagger tagger.Component) *Tailer { if len(source.Config.ProcessingRules) > 0 && processRawMessage { log.Warn("The logs processing rules currently apply to the raw journald JSON-structured log. These rules can now be applied to the message content only, and we plan to make this the default behavior in the future.") log.Warn("In order to immediately switch to this new behavior, set 'process_raw_message' to 'false' in your logs integration config and adapt your processing rules accordingly.") @@ -75,6 +77,7 @@ func NewTailer(source *sources.LogSource, outputChan chan *message.Message, jour done: make(chan struct{}, 1), processRawMessage: processRawMessage, tagProvider: tag.NewLocalProvider([]string{}), + tagger: tagger, } } diff --git a/pkg/logs/tailers/journald/tailer_test.go b/pkg/logs/tailers/journald/tailer_test.go index fe48264c2a427..ac44f5f265cb0 100644 --- a/pkg/logs/tailers/journald/tailer_test.go +++ b/pkg/logs/tailers/journald/tailer_test.go @@ -16,6 +16,7 @@ import ( "github.com/coreos/go-systemd/sdjournal" "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/comp/core/tagger/taggerimpl" "github.com/DataDog/datadog-agent/comp/logs/agent/config" configmock "github.com/DataDog/datadog-agent/pkg/config/mock" "github.com/DataDog/datadog-agent/pkg/logs/message" @@ -116,15 +117,16 @@ func (m *MockJournal) GetCursor() (string, error) { func TestIdentifier(t *testing.T) { var tailer *Tailer var source *sources.LogSource + fakeTagger := taggerimpl.SetupFakeTagger(t) // expect default identifier source = sources.NewLogSource("", &config.LogsConfig{}) - tailer = NewTailer(source, nil, nil, true) + tailer = NewTailer(source, nil, nil, true, fakeTagger) assert.Equal(t, "journald:default", tailer.Identifier()) // expect identifier to be overridden source = sources.NewLogSource("", &config.LogsConfig{Path: "any_path"}) - tailer = NewTailer(source, nil, nil, true) + tailer = NewTailer(source, nil, nil, true, fakeTagger) assert.Equal(t, "journald:any_path", tailer.Identifier()) } @@ -134,10 +136,11 @@ func TestShouldDropEntry(t *testing.T) { var source *sources.LogSource var tailer *Tailer var err error + fakeTagger := taggerimpl.SetupFakeTagger(t) // expect only the specified service units or matching entries to be dropped source = sources.NewLogSource("", &config.LogsConfig{ExcludeSystemUnits: []string{"foo", "bar"}, ExcludeUserUnits: []string{"baz", "qux"}, ExcludeMatches: []string{"quux=quuz"}}) - tailer = NewTailer(source, nil, nil, true) + tailer = NewTailer(source, nil, nil, true, fakeTagger) err = tailer.setup() assert.Nil(t, err) @@ -209,7 +212,7 @@ func TestShouldDropEntry(t *testing.T) { // expect all System-level service units to be dropped source = sources.NewLogSource("", &config.LogsConfig{ExcludeSystemUnits: []string{"*"}}) - tailer = NewTailer(source, nil, nil, true) + tailer = NewTailer(source, nil, nil, true, fakeTagger) err = tailer.setup() assert.Nil(t, err) @@ -245,7 +248,7 @@ func TestShouldDropEntry(t *testing.T) { // expect all User-level service units to be dropped source = sources.NewLogSource("", &config.LogsConfig{ExcludeUserUnits: []string{"*"}}) - tailer = NewTailer(source, nil, nil, true) + tailer = NewTailer(source, nil, nil, true, fakeTagger) err = tailer.setup() assert.Nil(t, err) @@ -283,7 +286,8 @@ func TestShouldDropEntry(t *testing.T) { func TestApplicationName(t *testing.T) { source := sources.NewLogSource("", &config.LogsConfig{}) - tailer := NewTailer(source, nil, nil, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, nil, true, fakeTagger) assert.Equal(t, "foo", tailer.getApplicationName( &sdjournal.JournalEntry{ @@ -327,7 +331,8 @@ func TestApplicationName(t *testing.T) { func TestContent(t *testing.T) { source := sources.NewLogSource("", &config.LogsConfig{}) - tailer := NewTailer(source, nil, nil, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, nil, true, fakeTagger) _, marshaled := tailer.getContent( &sdjournal.JournalEntry{ @@ -358,7 +363,8 @@ func TestContent(t *testing.T) { func TestSeverity(t *testing.T) { source := sources.NewLogSource("", &config.LogsConfig{}) - tailer := NewTailer(source, nil, nil, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, nil, true, fakeTagger) priorityValues := []string{"0", "1", "2", "3", "4", "5", "6", "7", "foo"} statuses := []string{message.StatusEmergency, message.StatusAlert, message.StatusCritical, message.StatusError, message.StatusWarning, message.StatusNotice, message.StatusInfo, message.StatusDebug, message.StatusInfo} @@ -375,7 +381,8 @@ func TestSeverity(t *testing.T) { func TestApplicationNameShouldBeDockerForContainerEntries(t *testing.T) { source := sources.NewLogSource("", &config.LogsConfig{}) - tailer := NewTailer(source, nil, nil, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, nil, true, fakeTagger) assert.Equal(t, "docker", tailer.getApplicationName( &sdjournal.JournalEntry{ @@ -393,7 +400,8 @@ func TestApplicationNameShouldBeShortImageForContainerEntries(t *testing.T) { containerID := "bar" source := sources.NewLogSource("", &config.LogsConfig{ContainerMode: true}) - tailer := NewTailer(source, nil, nil, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, nil, true, fakeTagger) assert.Equal(t, "testImage", tailer.getApplicationName( &sdjournal.JournalEntry{ @@ -415,7 +423,8 @@ func TestApplicationNameShouldBeDockerWhenTagNotFound(t *testing.T) { containerID := "bar2" source := sources.NewLogSource("", &config.LogsConfig{ContainerMode: true}) - tailer := NewTailer(source, nil, nil, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, nil, true, fakeTagger) assert.Equal(t, "docker", tailer.getApplicationName( &sdjournal.JournalEntry{ @@ -440,7 +449,8 @@ func TestWrongTypeFromCache(t *testing.T) { cache.Cache.Set(getImageCacheKey(containerID), 10, 30*time.Second) source := sources.NewLogSource("", &config.LogsConfig{ContainerMode: true}) - tailer := NewTailer(source, nil, nil, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, nil, true, fakeTagger) assert.Equal(t, "testImage", tailer.getApplicationName( &sdjournal.JournalEntry{ @@ -483,7 +493,8 @@ func TestTailingMode(t *testing.T) { t.Run(tt.name, func(t *testing.T) { mockJournal := &MockJournal{m: m} source := sources.NewLogSource("", tt.config) - tailer := NewTailer(source, nil, mockJournal, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, nil, mockJournal, true, fakeTagger) tailer.Start(tt.cursor) mockJournal.m.Lock() @@ -507,7 +518,8 @@ func TestTailerCanTailJournal(t *testing.T) { mockJournal := &MockJournal{m: &sync.Mutex{}} source := sources.NewLogSource("", &config.LogsConfig{}) - tailer := NewTailer(source, make(chan *message.Message, 1), mockJournal, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, make(chan *message.Message, 1), mockJournal, true, fakeTagger) mockJournal.entries = append(mockJournal.entries, &sdjournal.JournalEntry{Fields: map[string]string{"MESSAGE": "foobar"}}) @@ -527,7 +539,8 @@ func TestTailerWithStructuredMessage(t *testing.T) { mockJournal := &MockJournal{m: &sync.Mutex{}} source := sources.NewLogSource("", &config.LogsConfig{}) - tailer := NewTailer(source, make(chan *message.Message, 1), mockJournal, false) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailer := NewTailer(source, make(chan *message.Message, 1), mockJournal, false, fakeTagger) mockJournal.entries = append(mockJournal.entries, &sdjournal.JournalEntry{Fields: map[string]string{ sdjournal.SD_JOURNAL_FIELD_MESSAGE: "foobar", "_SESSION_UID": "a97aaca9-ea7a-4ea5-9ebe-048686f2c78a", @@ -551,7 +564,8 @@ func TestTailerCompareUnstructuredAndStructured(t *testing.T) { mockJournalV1 := &MockJournal{m: &sync.Mutex{}} sourceV1 := sources.NewLogSource("", &config.LogsConfig{}) - tailerV1 := NewTailer(sourceV1, make(chan *message.Message, 1), mockJournalV1, true) + fakeTagger := taggerimpl.SetupFakeTagger(t) + tailerV1 := NewTailer(sourceV1, make(chan *message.Message, 1), mockJournalV1, true, fakeTagger) mockJournalV1.entries = append(mockJournalV1.entries, &sdjournal.JournalEntry{Fields: map[string]string{ sdjournal.SD_JOURNAL_FIELD_MESSAGE: "journald log message content", "_SESSION_UID": "a97aaca9-ea7a-4ea5-9ebe-048686f2c78a", @@ -564,7 +578,7 @@ func TestTailerCompareUnstructuredAndStructured(t *testing.T) { mockJournalV2 := &MockJournal{m: &sync.Mutex{}} sourceV2 := sources.NewLogSource("", &config.LogsConfig{}) - tailerV2 := NewTailer(sourceV2, make(chan *message.Message, 1), mockJournalV2, false) + tailerV2 := NewTailer(sourceV2, make(chan *message.Message, 1), mockJournalV2, false, fakeTagger) mockJournalV2.entries = append(mockJournalV2.entries, &sdjournal.JournalEntry{Fields: map[string]string{ sdjournal.SD_JOURNAL_FIELD_MESSAGE: "journald log message content", "_SESSION_UID": "a97aaca9-ea7a-4ea5-9ebe-048686f2c78a", @@ -590,6 +604,7 @@ func TestExpectedTagDuration(t *testing.T) { mockConfig := configmock.New(t) tags := []string{"tag1:value1"} + fakeTagger := taggerimpl.SetupFakeTagger(t) mockConfig.SetWithoutSource("tags", tags) defer mockConfig.SetWithoutSource("tags", nil) @@ -599,7 +614,7 @@ func TestExpectedTagDuration(t *testing.T) { mockJournal := &MockJournal{m: &sync.Mutex{}} source := sources.NewLogSource("", &config.LogsConfig{}) - tailer := NewTailer(source, make(chan *message.Message, 1), mockJournal, true) + tailer := NewTailer(source, make(chan *message.Message, 1), mockJournal, true, fakeTagger) mockJournal.entries = append(mockJournal.entries, &sdjournal.JournalEntry{Fields: map[string]string{"MESSAGE": "foobar"}}) diff --git a/pkg/network/ebpf/c/tracer.c b/pkg/network/ebpf/c/tracer.c index 7555758f40524..909243dba174e 100644 --- a/pkg/network/ebpf/c/tracer.c +++ b/pkg/network/ebpf/c/tracer.c @@ -238,6 +238,7 @@ int BPF_BYPASSABLE_KPROBE(kprobe__tcp_done, struct sock *sk) { __u64 timestamp = bpf_ktime_get_ns(); if (bpf_map_update_with_telemetry(conn_close_flushed, &t, ×tamp, BPF_NOEXIST, -EEXIST) == 0) { cleanup_conn(ctx, &t, sk); + increment_telemetry_count(tcp_done_connection_flush); flush_tcp_failure(ctx, &t, err); } else { bpf_map_delete_elem(&conn_close_flushed, &t); @@ -287,6 +288,7 @@ int BPF_BYPASSABLE_KPROBE(kprobe__tcp_close, struct sock *sk) { __u64 timestamp = bpf_ktime_get_ns(); if (bpf_map_update_with_telemetry(conn_close_flushed, &t, ×tamp, BPF_NOEXIST, -EEXIST) == 0) { cleanup_conn(ctx, &t, sk); + increment_telemetry_count(tcp_close_connection_flush); int err = 0; bpf_probe_read_kernel_with_telemetry(&err, sizeof(err), (&sk->sk_err)); if (err == TCP_CONN_FAILED_RESET || err == TCP_CONN_FAILED_TIMEOUT || err == TCP_CONN_FAILED_REFUSED) { diff --git a/pkg/network/ebpf/c/tracer/maps.h b/pkg/network/ebpf/c/tracer/maps.h index f02066fe4b4dc..6ac62657e90f9 100644 --- a/pkg/network/ebpf/c/tracer/maps.h +++ b/pkg/network/ebpf/c/tracer/maps.h @@ -27,7 +27,7 @@ BPF_HASH_MAP(tcp_retransmits, conn_tuple_t, __u32, 0) BPF_HASH_MAP(tcp_ongoing_connect_pid, skp_conn_tuple_t, pid_ts_t, 0) /* Will hold a flag to indicate that closed connections have already been flushed */ -BPF_HASH_MAP(conn_close_flushed, conn_tuple_t, __u64, 8192) +BPF_HASH_MAP(conn_close_flushed, conn_tuple_t, __u64, 16384) /* Will hold the tcp/udp close events * The keys are the cpu number and the values a perf file descriptor for a perf event diff --git a/pkg/network/ebpf/c/tracer/telemetry.h b/pkg/network/ebpf/c/tracer/telemetry.h index a6067f1fae501..b723f1c4b8b71 100644 --- a/pkg/network/ebpf/c/tracer/telemetry.h +++ b/pkg/network/ebpf/c/tracer/telemetry.h @@ -29,6 +29,8 @@ enum telemetry_counter { tcp_done_failed_tuple, tcp_finish_connect_failed_tuple, tcp_close_target_failures, + tcp_done_connection_flush, + tcp_close_connection_flush }; static __always_inline void increment_telemetry_count(enum telemetry_counter counter_name) { @@ -82,6 +84,12 @@ static __always_inline void increment_telemetry_count(enum telemetry_counter cou case tcp_close_target_failures: __sync_fetch_and_add(&val->tcp_close_target_failures, 1); break; + case tcp_done_connection_flush: + __sync_fetch_and_add(&val->tcp_done_connection_flush, 1); + break; + case tcp_close_connection_flush: + __sync_fetch_and_add(&val->tcp_close_connection_flush, 1); + break; } } diff --git a/pkg/network/ebpf/c/tracer/tracer.h b/pkg/network/ebpf/c/tracer/tracer.h index cb2a96ff7a66c..f99301993b539 100644 --- a/pkg/network/ebpf/c/tracer/tracer.h +++ b/pkg/network/ebpf/c/tracer/tracer.h @@ -119,6 +119,8 @@ typedef struct { __u64 tcp_done_failed_tuple; __u64 tcp_finish_connect_failed_tuple; __u64 tcp_close_target_failures; + __u64 tcp_done_connection_flush; + __u64 tcp_close_connection_flush; } telemetry_t; typedef struct { diff --git a/pkg/network/ebpf/kprobe_types_linux.go b/pkg/network/ebpf/kprobe_types_linux.go index 58cee5d1115aa..13d63751f2adc 100644 --- a/pkg/network/ebpf/kprobe_types_linux.go +++ b/pkg/network/ebpf/kprobe_types_linux.go @@ -78,6 +78,8 @@ type Telemetry struct { Tcp_done_failed_tuple uint64 Tcp_finish_connect_failed_tuple uint64 Tcp_close_target_failures uint64 + Tcp_done_connection_flush uint64 + Tcp_close_connection_flush uint64 } type PortBinding struct { Netns uint32 diff --git a/pkg/network/encoding/encoding_test.go b/pkg/network/encoding/encoding_test.go index 88343a419cb30..04b033d8d5269 100644 --- a/pkg/network/encoding/encoding_test.go +++ b/pkg/network/encoding/encoding_test.go @@ -191,9 +191,16 @@ func TestSerialization(t *testing.T) { in := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.1.1.1"), Dest: util.AddressFromString("10.2.2.2"), + Pid: 6000, + NetNS: 7, + SPort: 1000, + DPort: 9000, + Type: network.TCP, + Family: network.AFINET6, + }, Monotonic: network.StatCounters{ SentBytes: 1, RecvBytes: 100, @@ -207,10 +214,7 @@ func TestSerialization(t *testing.T) { Retransmits: 201, }, LastUpdateEpoch: 50, - Pid: 6000, - NetNS: 7, - SPort: 1000, - DPort: 9000, + IPTranslation: &network.IPTranslation{ ReplSrcIP: util.AddressFromString("20.1.1.1"), ReplDstIP: util.AddressFromString("20.1.1.1"), @@ -218,8 +222,6 @@ func TestSerialization(t *testing.T) { ReplDstPort: 80, }, - Type: network.TCP, - Family: network.AFINET6, Direction: network.LOCAL, Via: &network.Via{ Subnet: network.Subnet{ @@ -228,13 +230,14 @@ func TestSerialization(t *testing.T) { }, ProtocolStack: protocols.Stack{Application: protocols.HTTP}, }, - { - Source: util.AddressFromString("10.1.1.1"), - Dest: util.AddressFromString("8.8.8.8"), - SPort: 1000, - DPort: 53, - Type: network.UDP, - Family: network.AFINET6, + {ConnectionTuple: network.ConnectionTuple{ + Source: util.AddressFromString("10.1.1.1"), + Dest: util.AddressFromString("8.8.8.8"), + SPort: 1000, + DPort: 53, + Type: network.UDP, + Family: network.AFINET6, + }, Direction: network.LOCAL, StaticTags: tagOpenSSL | tagTLS, ProtocolStack: protocols.Stack{Application: protocols.HTTP2}, @@ -491,18 +494,18 @@ func TestHTTPSerializationWithLocalhostTraffic(t *testing.T) { in := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, Dest: localhost, SPort: clientPort, DPort: serverPort, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, Dest: localhost, SPort: serverPort, DPort: clientPort, - }, + }}, }, }, HTTP: map[http.Key]*http.RequestStats{ @@ -651,18 +654,18 @@ func TestHTTP2SerializationWithLocalhostTraffic(t *testing.T) { in := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, Dest: localhost, SPort: clientPort, DPort: serverPort, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, Dest: localhost, SPort: serverPort, DPort: clientPort, - }, + }}, }, }, HTTP2: map[http.Key]*http.RequestStats{ @@ -758,12 +761,12 @@ func TestPooledObjectGarbageRegression(t *testing.T) { in := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.0.15.1"), SPort: uint16(60000), Dest: util.AddressFromString("172.217.10.45"), DPort: uint16(8080), - }, + }}, }, }, } @@ -824,12 +827,12 @@ func TestPooledHTTP2ObjectGarbageRegression(t *testing.T) { in := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.0.15.1"), SPort: uint16(60000), Dest: util.AddressFromString("172.217.10.45"), DPort: uint16(8080), - }, + }}, }, }, } @@ -913,20 +916,20 @@ func TestKafkaSerializationWithLocalhostTraffic(t *testing.T) { ) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: clientPort, Dest: localhost, DPort: serverPort, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: serverPort, Dest: localhost, DPort: clientPort, Pid: 2, - }, + }}, } const topicName = "TopicName" diff --git a/pkg/network/encoding/marshal/dns_test.go b/pkg/network/encoding/marshal/dns_test.go index 18ee7b250947a..e1ffed438d9dc 100644 --- a/pkg/network/encoding/marshal/dns_test.go +++ b/pkg/network/encoding/marshal/dns_test.go @@ -26,13 +26,14 @@ func TestFormatConnectionDNS(t *testing.T) { payload := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { - Source: util.AddressFromString("10.1.1.1"), - Dest: util.AddressFromString("8.8.8.8"), - SPort: 1000, - DPort: 53, - Type: network.UDP, - Family: network.AFINET6, + {ConnectionTuple: network.ConnectionTuple{ + Source: util.AddressFromString("10.1.1.1"), + Dest: util.AddressFromString("8.8.8.8"), + SPort: 1000, + DPort: 53, + Type: network.UDP, + Family: network.AFINET6, + }, Direction: network.LOCAL, DNSStats: map[dns.Hostname]map[dns.QueryType]dns.Stats{ dns.ToHostname("foo.com"): { diff --git a/pkg/network/encoding/marshal/format.go b/pkg/network/encoding/marshal/format.go index f02308ba849b4..4628a0203e390 100644 --- a/pkg/network/encoding/marshal/format.go +++ b/pkg/network/encoding/marshal/format.go @@ -97,8 +97,8 @@ func FormatConnection(builder *model.ConnectionBuilder, conn network.ConnectionS builder.SetRtt(conn.RTT) builder.SetRttVar(conn.RTTVar) builder.SetIntraHost(conn.IntraHost) - builder.SetLastTcpEstablished(conn.Last.TCPEstablished) - builder.SetLastTcpClosed(conn.Last.TCPClosed) + builder.SetLastTcpEstablished(uint32(conn.Last.TCPEstablished)) + builder.SetLastTcpClosed(uint32(conn.Last.TCPClosed)) builder.SetProtocol(func(w *model.ProtocolStackBuilder) { ps := FormatProtocolStack(conn.ProtocolStack, conn.StaticTags) for _, p := range ps.Stack { diff --git a/pkg/network/encoding/marshal/usm_http2_test.go b/pkg/network/encoding/marshal/usm_http2_test.go index 0a658e0066b3c..d6ecbf7471345 100644 --- a/pkg/network/encoding/marshal/usm_http2_test.go +++ b/pkg/network/encoding/marshal/usm_http2_test.go @@ -78,12 +78,12 @@ func (s *HTTP2Suite) TestFormatHTTP2Stats() { in := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, Dest: localhost, SPort: clientPort, DPort: serverPort, - }, + }}, }, }, HTTP2: map[http.Key]*http.RequestStats{ @@ -155,12 +155,12 @@ func (s *HTTP2Suite) TestFormatHTTP2StatsByPath() { payload := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.1.1.1"), Dest: util.AddressFromString("10.2.2.2"), SPort: 60000, DPort: 80, - }, + }}, }, }, HTTP2: map[http.Key]*http.RequestStats{ @@ -202,20 +202,20 @@ func (s *HTTP2Suite) TestHTTP2IDCollisionRegression() { http2Stats := http.NewRequestStats() assert := assert.New(t) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), SPort: 60000, Dest: util.AddressFromString("2.2.2.2"), DPort: 80, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), SPort: 60000, Dest: util.AddressFromString("2.2.2.2"), DPort: 80, Pid: 2, - }, + }}, } httpKey := http.NewKey( @@ -264,20 +264,20 @@ func (s *HTTP2Suite) TestHTTP2LocalhostScenario() { cliport := uint16(6000) serverport := uint16(80) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), SPort: cliport, Dest: util.AddressFromString("127.0.0.1"), DPort: serverport, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), SPort: serverport, Dest: util.AddressFromString("127.0.0.1"), DPort: cliport, Pid: 2, - }, + }}, } http2Stats := http.NewRequestStats() diff --git a/pkg/network/encoding/marshal/usm_http_test.go b/pkg/network/encoding/marshal/usm_http_test.go index b96a22c7fbf32..6e4966de7a5c1 100644 --- a/pkg/network/encoding/marshal/usm_http_test.go +++ b/pkg/network/encoding/marshal/usm_http_test.go @@ -57,12 +57,12 @@ func TestFormatHTTPStats(t *testing.T) { in := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, Dest: localhost, SPort: clientPort, DPort: serverPort, - }, + }}, }, }, HTTP: map[http.Key]*http.RequestStats{ @@ -135,12 +135,12 @@ func TestFormatHTTPStatsByPath(t *testing.T) { payload := &network.Connections{ BufferedData: network.BufferedData{ Conns: []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.1.1.1"), Dest: util.AddressFromString("10.2.2.2"), SPort: 60000, DPort: 80, - }, + }}, }, }, HTTP: map[http.Key]*http.RequestStats{ @@ -180,20 +180,20 @@ func TestIDCollisionRegression(t *testing.T) { httpStats := http.NewRequestStats() assert := assert.New(t) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), SPort: 60000, Dest: util.AddressFromString("2.2.2.2"), DPort: 80, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), SPort: 60000, Dest: util.AddressFromString("2.2.2.2"), DPort: 80, Pid: 2, - }, + }}, } httpKey := http.NewKey( @@ -238,20 +238,20 @@ func TestIDCollisionRegression(t *testing.T) { func TestLocalhostScenario(t *testing.T) { assert := assert.New(t) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), SPort: 60000, Dest: util.AddressFromString("127.0.0.1"), DPort: 80, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), SPort: 80, Dest: util.AddressFromString("127.0.0.1"), DPort: 60000, Pid: 2, - }, + }}, } httpStats := http.NewRequestStats() diff --git a/pkg/network/encoding/marshal/usm_kafka_test.go b/pkg/network/encoding/marshal/usm_kafka_test.go index 350581bec41db..be178759dd94e 100644 --- a/pkg/network/encoding/marshal/usm_kafka_test.go +++ b/pkg/network/encoding/marshal/usm_kafka_test.go @@ -38,12 +38,12 @@ const ( var ( localhost = util.AddressFromString("127.0.0.1") - defaultConnection = network.ConnectionStats{ + defaultConnection = network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: localhost, Dest: localhost, SPort: clientPort, DPort: serverPort, - } + }} ) type KafkaSuite struct { @@ -132,20 +132,20 @@ func (s *KafkaSuite) TestKafkaIDCollisionRegression() { t := s.T() assert := assert.New(t) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: clientPort, Dest: localhost, DPort: serverPort, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: clientPort, Dest: localhost, DPort: serverPort, Pid: 2, - }, + }}, } kafkaKey := kafka.NewKey( @@ -193,20 +193,20 @@ func (s *KafkaSuite) TestKafkaLocalhostScenario() { t := s.T() assert := assert.New(t) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: clientPort, Dest: localhost, DPort: serverPort, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: serverPort, Dest: localhost, DPort: clientPort, Pid: 2, - }, + }}, } kafkaKey := kafka.NewKey( diff --git a/pkg/network/encoding/marshal/usm_lookup_test.go b/pkg/network/encoding/marshal/usm_lookup_test.go index 7b50766ec745b..708881558e82b 100644 --- a/pkg/network/encoding/marshal/usm_lookup_test.go +++ b/pkg/network/encoding/marshal/usm_lookup_test.go @@ -34,20 +34,20 @@ func TestUSMLookup(t *testing.T) { data[key] = val // Assert that c1 and c2 (which are symmetrical) "link" to the same aggregation - c1 := network.ConnectionStats{ + c1 := network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("2.2.2.2"), SPort: 60000, DPort: 80, - } + }} assert.Equal(t, val, USMLookup(c1, data)) - c2 := network.ConnectionStats{ + c2 := network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("2.2.2.2"), Dest: util.AddressFromString("1.1.1.1"), SPort: 80, DPort: 60000, - } + }} assert.Equal(t, val, USMLookup(c2, data)) }) @@ -64,11 +64,12 @@ func TestUSMLookup(t *testing.T) { data[key] = val // Assert that c1 and c2 (which are symmetrical) "link" to the same aggregation - c1 := network.ConnectionStats{ + c1 := network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("2.2.2.2"), SPort: 60000, DPort: 80, + }, IPTranslation: &network.IPTranslation{ ReplSrcIP: util.AddressFromString("3.3.3.3"), ReplDstIP: util.AddressFromString("4.4.4.4"), @@ -78,11 +79,12 @@ func TestUSMLookup(t *testing.T) { } assert.Equal(t, val, USMLookup(c1, data)) - c2 := network.ConnectionStats{ + c2 := network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("2.2.2.2"), Dest: util.AddressFromString("1.1.1.1"), SPort: 80, DPort: 60000, + }, IPTranslation: &network.IPTranslation{ ReplSrcIP: util.AddressFromString("4.4.4.4"), ReplDstIP: util.AddressFromString("3.3.3.3"), diff --git a/pkg/network/encoding/marshal/usm_lookup_windows_test.go b/pkg/network/encoding/marshal/usm_lookup_windows_test.go index 7a7ca47863646..7efe156f104d4 100644 --- a/pkg/network/encoding/marshal/usm_lookup_windows_test.go +++ b/pkg/network/encoding/marshal/usm_lookup_windows_test.go @@ -31,19 +31,19 @@ func TestUSMLookup(t *testing.T) { // In windows the USMLookup operation is done only once and using the // original tuple order, so in the case below only c1 should match the data - c1 := network.ConnectionStats{ + c1 := network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("2.2.2.2"), SPort: 60000, DPort: 80, - } + }} - c2 := network.ConnectionStats{ + c2 := network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("2.2.2.2"), Dest: util.AddressFromString("1.1.1.1"), SPort: 80, DPort: 60000, - } + }} assert.Equal(t, val, USMLookup(c1, data)) assert.Equal(t, (*USMConnectionData[struct{}, any])(nil), USMLookup(c2, data)) diff --git a/pkg/network/encoding/marshal/usm_postgres_test.go b/pkg/network/encoding/marshal/usm_postgres_test.go index 031da39501e12..ff08054d85cde 100644 --- a/pkg/network/encoding/marshal/usm_postgres_test.go +++ b/pkg/network/encoding/marshal/usm_postgres_test.go @@ -27,12 +27,12 @@ const ( ) var ( - postgresDefaultConnection = network.ConnectionStats{ + postgresDefaultConnection = network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: localhost, Dest: localhost, SPort: postgresClientPort, DPort: postgresServerPort, - } + }} ) type PostgresSuite struct { @@ -251,20 +251,20 @@ func (s *PostgresSuite) TestPostgresIDCollisionRegression() { t := s.T() assert := assert.New(t) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: postgresClientPort, Dest: localhost, DPort: postgresServerPort, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: postgresClientPort, Dest: localhost, DPort: postgresServerPort, Pid: 2, - }, + }}, } postgresKey := postgres.NewKey( @@ -311,20 +311,20 @@ func (s *PostgresSuite) TestPostgresLocalhostScenario() { t := s.T() assert := assert.New(t) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: postgresClientPort, Dest: localhost, DPort: postgresServerPort, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: postgresServerPort, Dest: localhost, DPort: postgresClientPort, Pid: 2, - }, + }}, } postgresKey := postgres.NewKey( diff --git a/pkg/network/encoding/marshal/usm_redis_test.go b/pkg/network/encoding/marshal/usm_redis_test.go index c8a41c3e6b07a..191f3cd200984 100644 --- a/pkg/network/encoding/marshal/usm_redis_test.go +++ b/pkg/network/encoding/marshal/usm_redis_test.go @@ -26,12 +26,12 @@ const ( ) var ( - redisDefaultConnection = network.ConnectionStats{ + redisDefaultConnection = network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: localhost, Dest: localhost, SPort: redisClientPort, DPort: redisServerPort, - } + }} ) type RedisSuite struct { @@ -87,20 +87,20 @@ func (s *RedisSuite) TestRedisIDCollisionRegression() { t := s.T() assert := assert.New(t) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: redisClientPort, Dest: localhost, DPort: redisServerPort, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: redisClientPort, Dest: localhost, DPort: redisServerPort, Pid: 2, - }, + }}, } redisKey := redis.NewKey( @@ -138,20 +138,20 @@ func (s *RedisSuite) TestRedisLocalhostScenario() { t := s.T() assert := assert.New(t) connections := []network.ConnectionStats{ - { + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: redisClientPort, Dest: localhost, DPort: redisServerPort, Pid: 1, - }, - { + }}, + {ConnectionTuple: network.ConnectionTuple{ Source: localhost, SPort: redisServerPort, Dest: localhost, DPort: redisClientPort, Pid: 2, - }, + }}, } redisKey := redis.NewKey( diff --git a/pkg/network/encoding/marshal/usm_test.go b/pkg/network/encoding/marshal/usm_test.go index ba4b921fd748f..d3556143539d9 100644 --- a/pkg/network/encoding/marshal/usm_test.go +++ b/pkg/network/encoding/marshal/usm_test.go @@ -80,12 +80,12 @@ func TestGroupByConnection(t *testing.T) { // Connection 1 // Assert that (key1, val1) and (key2, val2) were grouped together - connection1 := network.ConnectionStats{ + connection1 := network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("2.2.2.2"), SPort: 60000, DPort: 80, - } + }} connectionData1 := byConnection.Find(connection1) assert.NotNil(t, connectionData1) assert.Len(t, connectionData1.Data, 2) @@ -94,12 +94,12 @@ func TestGroupByConnection(t *testing.T) { // Connection 2 // Assert that (key3, val3) and (key4, val4) were grouped together - connection2 := network.ConnectionStats{ + connection2 := network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("3.3.3.3"), Dest: util.AddressFromString("4.4.4.4"), SPort: 60000, DPort: 80, - } + }} connectionData2 := byConnection.Find(connection2) assert.NotNil(t, connectionData2) assert.Len(t, connectionData1.Data, 2) diff --git a/pkg/network/event_common.go b/pkg/network/event_common.go index 990c9f40797b7..e8dcbfd2e77c3 100644 --- a/pkg/network/event_common.go +++ b/pkg/network/event_common.go @@ -218,8 +218,8 @@ type StatCounters struct { // * Value 1 represents a connection that was established after system-probe started; // * Values greater than 1 should be rare, but can occur when multiple connections // are established with the same tuple between two agent checks; - TCPEstablished uint32 - TCPClosed uint32 + TCPEstablished uint16 + TCPClosed uint16 } // IsZero returns whether all the stat counter values are zeroes @@ -232,53 +232,64 @@ func (s StatCounters) IsZero() bool { // reduce collisions; see PR #17197 for more info. type StatCookie = uint64 -// ConnectionStats stores statistics for a single connection. Field order in the struct should be 8-byte aligned -type ConnectionStats struct { +// ConnectionTuple represents the unique network key for a connection +type ConnectionTuple struct { Source util.Address Dest util.Address + Pid uint32 + NetNS uint32 + SPort uint16 + DPort uint16 + Type ConnectionType + Family ConnectionFamily +} +func (c ConnectionTuple) String() string { + return fmt.Sprintf( + "[%s%s] [PID: %d] [ns: %d] [%s:%d ⇄ %s:%d] ", + c.Type, + c.Family, + c.Pid, + c.NetNS, + c.Source, + c.SPort, + c.Dest, + c.DPort, + ) +} + +// ConnectionStats stores statistics for a single connection. Field order in the struct should be 8-byte aligned +type ConnectionStats struct { + // move pointer fields first to reduce number of bytes GC has to scan IPTranslation *IPTranslation Via *Via + Tags []*intern.Value + ContainerID struct { + Source, Dest *intern.Value + } + DNSStats map[dns.Hostname]map[dns.QueryType]dns.Stats + // TCPFailures stores the number of failures for a POSIX error code + TCPFailures map[uint32]uint32 - Monotonic StatCounters - - Last StatCounters - - Cookie StatCookie + ConnectionTuple - // Last time the stats for this connection were updated + Monotonic StatCounters + Last StatCounters + Cookie StatCookie + // LastUpdateEpoch is the last time the stats for this connection were updated LastUpdateEpoch uint64 Duration time.Duration + RTT uint32 // Stored in µs + RTTVar uint32 + StaticTags uint64 + ProtocolStack protocols.Stack - RTT uint32 // Stored in µs - RTTVar uint32 - - Pid uint32 - NetNS uint32 - - SPort uint16 - DPort uint16 - Type ConnectionType - Family ConnectionFamily + // keep these fields last because they are 1 byte each and otherwise inflate the struct size due to alignment Direction ConnectionDirection SPortIsEphemeral EphemeralPortType - StaticTags uint64 - Tags []*intern.Value - - IntraHost bool - IsAssured bool - IsClosed bool - - ContainerID struct { - Source, Dest *intern.Value - } - - ProtocolStack protocols.Stack - - DNSStats map[dns.Hostname]map[dns.QueryType]dns.Stats - - // TCPFailures stores the number of failures for a POSIX error code - TCPFailures map[uint32]uint32 + IntraHost bool + IsAssured bool + IsClosed bool } // Via has info about the routing decision for a flow diff --git a/pkg/network/event_linux_test.go b/pkg/network/event_linux_test.go index a0dbe418c4769..148ed7e844993 100644 --- a/pkg/network/event_linux_test.go +++ b/pkg/network/event_linux_test.go @@ -29,12 +29,12 @@ func TestKeyTuplesFromConn(t *testing.T) { destinationAddress := util.AddressFromString("5.6.7.8") destinationPort := uint16(5678) - connectionStats := ConnectionStats{ + connectionStats := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: sourceAddress, SPort: sourcePort, Dest: destinationAddress, DPort: destinationPort, - } + }} keyTuples := ConnectionKeysFromConnectionStats(connectionStats) assert.Len(t, keyTuples, 2, "Expected different number of key tuples") @@ -65,11 +65,12 @@ func TestKeyTuplesFromConnNAT(t *testing.T) { natDestinationAddress := util.AddressFromString("50.60.70.80") natDestinationPort := uint16(8765) - connectionStats := ConnectionStats{ + connectionStats := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: sourceAddress, Dest: destinationAddress, SPort: sourcePort, DPort: destinationPort, + }, IPTranslation: &IPTranslation{ ReplSrcIP: natSourceAddress, ReplDstIP: natDestinationAddress, diff --git a/pkg/network/event_test.go b/pkg/network/event_test.go index beea1f2554496..60ac66900964b 100644 --- a/pkg/network/event_test.go +++ b/pkg/network/event_test.go @@ -18,13 +18,15 @@ import ( var ( testConn = ConnectionStats{ - Pid: 123, - Type: 1, - Family: AFINET, - Source: util.AddressFromString("192.168.0.1"), - Dest: util.AddressFromString("192.168.0.103"), - SPort: 123, - DPort: 35000, + ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: 1, + Family: AFINET, + Source: util.AddressFromString("192.168.0.1"), + Dest: util.AddressFromString("192.168.0.103"), + SPort: 123, + DPort: 35000, + }, Monotonic: StatCounters{ SentBytes: 123123, RecvBytes: 312312, @@ -37,24 +39,28 @@ func TestBeautifyKey(t *testing.T) { for _, c := range []ConnectionStats{ testConn, { - Pid: 345, - Type: 0, - Family: AFINET6, - Source: util.AddressFromNetIP(net.ParseIP("::7f00:35:0:1")), - Dest: util.AddressFromNetIP(net.ParseIP("2001:db8::2:1")), - SPort: 4444, - DPort: 8888, + ConnectionTuple: ConnectionTuple{ + Pid: 345, + Type: 0, + Family: AFINET6, + Source: util.AddressFromNetIP(net.ParseIP("::7f00:35:0:1")), + Dest: util.AddressFromNetIP(net.ParseIP("2001:db8::2:1")), + SPort: 4444, + DPort: 8888, + }, Cookie: 1, }, { - Pid: 32065, - Type: 0, - Family: AFINET, + ConnectionTuple: ConnectionTuple{ + Pid: 32065, + Type: 0, + Family: AFINET, + Source: util.AddressFromString("172.21.148.124"), + Dest: util.AddressFromString("130.211.21.187"), + SPort: 52012, + DPort: 443, + }, Direction: 2, - Source: util.AddressFromString("172.21.148.124"), - Dest: util.AddressFromString("130.211.21.187"), - SPort: 52012, - DPort: 443, Cookie: 2, }, } { @@ -74,44 +80,44 @@ func TestConnStatsByteKey(t *testing.T) { b ConnectionStats }{ { // Port is different - a: ConnectionStats{Source: addrA, Dest: addrB, Pid: 1}, - b: ConnectionStats{Source: addrA, Dest: addrB}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB, Pid: 1}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB}}, }, { // Family is different - a: ConnectionStats{Source: addrA, Dest: addrB, Family: 1}, - b: ConnectionStats{Source: addrA, Dest: addrB}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB, Family: 1}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB}}, }, { // Type is different - a: ConnectionStats{Source: addrA, Dest: addrB, Type: 1}, - b: ConnectionStats{Source: addrA, Dest: addrB}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB, Type: 1}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB}}, }, { // Source is different - a: ConnectionStats{Source: util.AddressFromString("123.255.123.0"), Dest: addrB}, - b: ConnectionStats{Source: addrA, Dest: addrB}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("123.255.123.0"), Dest: addrB}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB}}, }, { // Dest is different - a: ConnectionStats{Source: addrA, Dest: util.AddressFromString("129.0.1.2")}, - b: ConnectionStats{Source: addrA, Dest: addrB}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: util.AddressFromString("129.0.1.2")}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB}}, }, { // Source port is different - a: ConnectionStats{Source: addrA, Dest: addrB, SPort: 1}, - b: ConnectionStats{Source: addrA, Dest: addrB}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB, SPort: 1}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB}}, }, { // Dest port is different - a: ConnectionStats{Source: addrA, Dest: addrB, DPort: 1}, - b: ConnectionStats{Source: addrA, Dest: addrB}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB, DPort: 1}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addrA, Dest: addrB}}, }, { // Fields set, but sources are different - a: ConnectionStats{Pid: 1, Family: 0, Type: 1, Source: addrA, Dest: addrB}, - b: ConnectionStats{Pid: 1, Family: 0, Type: 1, Source: addrB, Dest: addrB}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Pid: 1, Family: 0, Type: 1, Source: addrA, Dest: addrB}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Pid: 1, Family: 0, Type: 1, Source: addrB, Dest: addrB}}, }, { // Both sources and dest are different - a: ConnectionStats{Pid: 1, Dest: addrB, Family: 0, Type: 1, Source: addrA}, - b: ConnectionStats{Pid: 1, Dest: addrA, Family: 0, Type: 1, Source: addrB}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Pid: 1, Dest: addrB, Family: 0, Type: 1, Source: addrA}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Pid: 1, Dest: addrA, Family: 0, Type: 1, Source: addrB}}, }, { // Family and Type are different - a: ConnectionStats{Pid: 1, Source: addrA, Dest: addrB, Family: 1}, - b: ConnectionStats{Pid: 1, Source: addrA, Dest: addrB, Type: 1}, + a: ConnectionStats{ConnectionTuple: ConnectionTuple{Pid: 1, Source: addrA, Dest: addrB, Family: 1}}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{Pid: 1, Source: addrA, Dest: addrB, Type: 1}}, }, } { var keyA, keyB string @@ -129,35 +135,36 @@ func TestByteKeyNAT(t *testing.T) { shouldMatch bool }{ { - a: ConnectionStats{ + a: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), Dest: util.AddressFromString("127.0.0.2"), - }, - b: ConnectionStats{ + }}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), Dest: util.AddressFromString("127.0.0.2"), - }, + }}, shouldMatch: true, }, { - a: ConnectionStats{ + a: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), Dest: util.AddressFromString("127.0.0.2"), - }, - b: ConnectionStats{ + }}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.3"), Dest: util.AddressFromString("127.0.0.4"), - }, + }}, shouldMatch: false, }, { - a: ConnectionStats{ + a: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), Dest: util.AddressFromString("127.0.0.2"), - }, - b: ConnectionStats{ + }}, + b: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), Dest: util.AddressFromString("127.0.0.2"), + }, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("1.1.1.1"), ReplDstIP: util.AddressFromString("2.2.2.2"), @@ -166,17 +173,19 @@ func TestByteKeyNAT(t *testing.T) { shouldMatch: false, }, { - a: ConnectionStats{ + a: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), Dest: util.AddressFromString("127.0.0.2"), + }, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("1.1.1.1"), ReplDstIP: util.AddressFromString("2.2.2.2"), }, }, - b: ConnectionStats{ + b: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), Dest: util.AddressFromString("127.0.0.2"), + }, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("3.3.3.3"), ReplDstIP: util.AddressFromString("4.4.4.4"), @@ -185,17 +194,19 @@ func TestByteKeyNAT(t *testing.T) { shouldMatch: false, }, { - a: ConnectionStats{ + a: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), Dest: util.AddressFromString("127.0.0.2"), + }, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("1.1.1.1"), ReplDstIP: util.AddressFromString("2.2.2.2"), }, }, - b: ConnectionStats{ + b: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.3"), Dest: util.AddressFromString("127.0.0.4"), + }, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("1.1.1.1"), ReplDstIP: util.AddressFromString("2.2.2.2"), @@ -246,7 +257,7 @@ func BenchmarkByteKey(b *testing.B) { buf := make([]byte, ConnectionByteKeyMaxLen) addrA := util.AddressFromString("127.0.0.1") addrB := util.AddressFromString("127.0.0.2") - c := ConnectionStats{Pid: 1, Dest: addrB, Family: 0, Type: 1, Source: addrA} + c := ConnectionStats{ConnectionTuple: ConnectionTuple{Pid: 1, Dest: addrB, Family: 0, Type: 1, Source: addrA}} b.ReportAllocs() b.ResetTimer() diff --git a/pkg/network/event_windows_test.go b/pkg/network/event_windows_test.go index 7fc5e841a7167..235bc10a82c63 100644 --- a/pkg/network/event_windows_test.go +++ b/pkg/network/event_windows_test.go @@ -51,12 +51,12 @@ func TestKeyTuplesFromConn(t *testing.T) { destinationAddress := util.AddressFromString("5.6.7.8") destinationPort := uint16(5678) - connectionStats := ConnectionStats{ + connectionStats := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: sourceAddress, SPort: sourcePort, Dest: destinationAddress, DPort: destinationPort, - } + }} keyTuples := ConnectionKeysFromConnectionStats(connectionStats) assert.Len(t, keyTuples, 1, "Expected different number of key tuples") diff --git a/pkg/network/events/monitor.go b/pkg/network/events/monitor.go index 698bed3651681..08c495db08454 100644 --- a/pkg/network/events/monitor.go +++ b/pkg/network/events/monitor.go @@ -183,7 +183,7 @@ func (h eventConsumerWrapper) ID() string { var _eventConsumerWrapper = &eventConsumerWrapper{} // Consumer returns an event consumer to handle events from the runtime security module -func Consumer() sprobe.EventConsumerInterface { +func Consumer() sprobe.EventConsumerHandler { return _eventConsumerWrapper } diff --git a/pkg/network/events/network_consumer.go b/pkg/network/events/network_consumer.go index e71cbc6e6758e..f825a61e6df4c 100644 --- a/pkg/network/events/network_consumer.go +++ b/pkg/network/events/network_consumer.go @@ -32,7 +32,7 @@ func (n *NetworkConsumer) ID() string { // NewNetworkConsumer returns a new NetworkConsumer instance func NewNetworkConsumer(evm *eventmonitor.EventMonitor) (*NetworkConsumer, error) { h := Consumer() - if err := evm.AddEventConsumer(h); err != nil { + if err := evm.AddEventConsumerHandler(h); err != nil { return nil, err } return &NetworkConsumer{}, nil diff --git a/pkg/network/netlink/conntrack.go b/pkg/network/netlink/conntrack.go index da4d74e2e3da6..4bc0f0f062b30 100644 --- a/pkg/network/netlink/conntrack.go +++ b/pkg/network/netlink/conntrack.go @@ -36,6 +36,10 @@ type Conntrack interface { // `netNS` is the network namespace for the conntrack operations. // A value of `0` will use the current thread's network namespace func NewConntrack(netNS netns.NsHandle) (Conntrack, error) { + if !isNetlinkConntrackSupported() { + return nil, ErrNotPermitted + } + conn, err := NewSocket(netNS) if err != nil { return nil, err diff --git a/pkg/network/netlink/conntracker.go b/pkg/network/netlink/conntracker.go index 885e4f5900b82..901e763bf2e4b 100644 --- a/pkg/network/netlink/conntracker.go +++ b/pkg/network/netlink/conntracker.go @@ -49,10 +49,10 @@ type Conntracker interface { Describe(descs chan<- *prometheus.Desc) // Collect returns the current state of all metrics of the collector Collect(metrics chan<- prometheus.Metric) - GetTranslationForConn(*network.ConnectionStats) *network.IPTranslation + GetTranslationForConn(*network.ConnectionTuple) *network.IPTranslation // GetType returns a string describing whether the conntracker is "ebpf" or "netlink" GetType() string - DeleteTranslation(*network.ConnectionStats) + DeleteTranslation(*network.ConnectionTuple) DumpCachedTable(context.Context) (map[uint32][]DebugConntrackEntry, error) Close() } @@ -112,6 +112,24 @@ var conntrackerTelemetry = struct { prometheus.NewDesc(telemetryModuleName+"__orphan_size", "Gauge measuring the number of orphaned items in the conntrack cache", nil, nil), } +// isNetlinkConntrackSupported checks if we have the right capabilities +// for netlink conntrack; NET_ADMIN is required +func isNetlinkConntrackSupported() bool { + // check if we have the right capabilities for the netlink NewConntracker + // NET_ADMIN is required + caps, err := capability.NewPid2(0) + if err == nil { + err = caps.Load() + } + + if err != nil { + log.Warnf("could not check if netlink conntracker is supported: %s", err) + return false + } + + return caps.Get(capability.EFFECTIVE, capability.CAP_NET_ADMIN) +} + // NewConntracker creates a new conntracker with a short term buffer capped at the given size func NewConntracker(config *config.Config, telemetrycomp telemetryComp.Component) (Conntracker, error) { var ( @@ -119,16 +137,8 @@ func NewConntracker(config *config.Config, telemetrycomp telemetryComp.Component conntracker Conntracker ) - // check if we have the right capabilities for the netlink NewConntracker - // NET_ADMIN is required - if caps, err := capability.NewPid2(0); err == nil { - if err = caps.Load(); err != nil { - return nil, fmt.Errorf("could not load process capabilities: %w", err) - } - - if !caps.Get(capability.EFFECTIVE, capability.CAP_NET_ADMIN) { - return nil, ErrNotPermitted - } + if !isNetlinkConntrackSupported() { + return nil, ErrNotPermitted } done := make(chan struct{}) @@ -182,7 +192,7 @@ func (ctr *realConntracker) GetType() string { return "netlink" } -func (ctr *realConntracker) GetTranslationForConn(c *network.ConnectionStats) *network.IPTranslation { +func (ctr *realConntracker) GetTranslationForConn(c *network.ConnectionTuple) *network.IPTranslation { then := time.Now() defer func() { conntrackerTelemetry.getsDuration.Observe(float64(time.Since(then).Nanoseconds())) @@ -218,7 +228,7 @@ func (ctr *realConntracker) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric(conntrackerTelemetry.orphanSize, prometheus.CounterValue, float64(ctr.cache.orphans.Len())) } -func (ctr *realConntracker) DeleteTranslation(c *network.ConnectionStats) { +func (ctr *realConntracker) DeleteTranslation(c *network.ConnectionTuple) { then := time.Now() ctr.Lock() diff --git a/pkg/network/netlink/conntracker_integration_test.go b/pkg/network/netlink/conntracker_integration_test.go index 2e92ad5fa21dc..6aa15bb7556fd 100644 --- a/pkg/network/netlink/conntracker_integration_test.go +++ b/pkg/network/netlink/conntracker_integration_test.go @@ -59,7 +59,7 @@ func TestConnTrackerCrossNamespaceAllNsDisabled(t *testing.T) { time.Sleep(time.Second) trans := ct.GetTranslationForConn( - &network.ConnectionStats{ + &network.ConnectionTuple{ Source: util.AddressFromNetIP(laddr.IP), SPort: uint16(laddr.Port), Dest: util.AddressFromString("2.2.2.4"), diff --git a/pkg/network/netlink/conntracker_test.go b/pkg/network/netlink/conntracker_test.go index c5b8d28d60a31..51d9d3dfbbb61 100644 --- a/pkg/network/netlink/conntracker_test.go +++ b/pkg/network/netlink/conntracker_test.go @@ -74,7 +74,7 @@ func TestRegisterNonNat(t *testing.T) { rt.register(c) translation := rt.GetTranslationForConn( - &network.ConnectionStats{ + &network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.0"), SPort: 8080, Dest: util.AddressFromString("50.30.40.10"), @@ -91,7 +91,7 @@ func TestRegisterNat(t *testing.T) { rt.register(c) translation := rt.GetTranslationForConn( - &network.ConnectionStats{ + &network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.0"), SPort: 12345, Dest: util.AddressFromString("50.30.40.10"), @@ -108,7 +108,7 @@ func TestRegisterNat(t *testing.T) { }, translation) udpTranslation := rt.GetTranslationForConn( - &network.ConnectionStats{ + &network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.0"), SPort: 12345, Dest: util.AddressFromString("50.30.40.10"), @@ -126,7 +126,7 @@ func TestRegisterNatUDP(t *testing.T) { rt.register(c) translation := rt.GetTranslationForConn( - &network.ConnectionStats{ + &network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.0"), SPort: 12345, Dest: util.AddressFromString("50.30.40.10"), @@ -143,7 +143,7 @@ func TestRegisterNatUDP(t *testing.T) { }, translation) translation = rt.GetTranslationForConn( - &network.ConnectionStats{ + &network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.0"), SPort: 12345, Dest: util.AddressFromString("50.30.40.10"), @@ -158,7 +158,7 @@ func TestTooManyEntries(t *testing.T) { rt := newConntracker(2) rt.register(makeTranslatedConn(netip.MustParseAddr("10.0.0.0"), netip.MustParseAddr("20.0.0.0"), netip.MustParseAddr("50.30.40.10"), 6, 12345, 80, 80)) - tr := rt.GetTranslationForConn(&network.ConnectionStats{ + tr := rt.GetTranslationForConn(&network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.0"), SPort: 12345, Dest: util.AddressFromString("50.30.40.10"), @@ -171,7 +171,7 @@ func TestTooManyEntries(t *testing.T) { rt.register(makeTranslatedConn(netip.MustParseAddr("10.0.0.1"), netip.MustParseAddr("20.0.0.1"), netip.MustParseAddr("50.30.40.20"), 6, 12345, 80, 80)) // old entry should be gone - tr = rt.GetTranslationForConn(&network.ConnectionStats{ + tr = rt.GetTranslationForConn(&network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.0"), SPort: 12345, Dest: util.AddressFromString("50.30.40.10"), @@ -181,7 +181,7 @@ func TestTooManyEntries(t *testing.T) { require.Nil(t, tr) // check new entry - tr = rt.GetTranslationForConn(&network.ConnectionStats{ + tr = rt.GetTranslationForConn(&network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.1"), SPort: 12345, Dest: util.AddressFromString("50.30.40.20"), diff --git a/pkg/network/netlink/noop.go b/pkg/network/netlink/noop.go index 67ce4912168a4..0eaf8001a948e 100644 --- a/pkg/network/netlink/noop.go +++ b/pkg/network/netlink/noop.go @@ -25,11 +25,11 @@ func NewNoOpConntracker() Conntracker { // GetType returns a string describing whether the conntracker is "ebpf" or "netlink" func (*noOpConntracker) GetType() string { return "" } -func (*noOpConntracker) GetTranslationForConn(_c *network.ConnectionStats) *network.IPTranslation { +func (*noOpConntracker) GetTranslationForConn(_c *network.ConnectionTuple) *network.IPTranslation { return nil } -func (*noOpConntracker) DeleteTranslation(_c *network.ConnectionStats) { +func (*noOpConntracker) DeleteTranslation(_c *network.ConnectionTuple) { } diff --git a/pkg/network/network_filter_test.go b/pkg/network/network_filter_test.go index ed8f412ffb673..c1e2711e67e15 100644 --- a/pkg/network/network_filter_test.go +++ b/pkg/network/network_filter_test.go @@ -50,39 +50,39 @@ func TestParseConnectionFilters(t *testing.T) { destList := ParseConnectionFilters(testDestinationFilters) // source - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("172.0.0.1"), SPort: uint16(10), Type: TCP})) - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("*"), SPort: uint16(9000), Type: TCP})) // only port 9000 - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.1.24"), SPort: uint16(9000), Type: TCP})) - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("::7f00:35:0:0"), SPort: uint16(443), Type: TCP})) // ipv6 - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("::"), SPort: uint16(443), Type: TCP})) // 0 == ::7f00:35:0:0 - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.0.10"), SPort: uint16(6666), Type: TCP})) // port wildcard - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.0.10"), SPort: uint16(33), Type: TCP})) - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.0.25"), SPort: uint16(30), Type: TCP})) // bad config - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("123.ABCD"), SPort: uint16(30), Type: TCP})) // bad IP config - - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("172.0.0.2"), SPort: uint16(100), Type: TCP})) - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("::7f00:35:0:1"), SPort: uint16(100), Type: TCP})) // invalid port - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.0.11"), SPort: uint16(6666), Type: TCP})) // port wildcard - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.0.26"), SPort: uint16(30), Type: TCP})) // invalid port range - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.0.1"), SPort: uint16(100), Type: TCP})) // tcp wildcard - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.0.2"), SPort: uint16(53363), Type: UDP})) - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.0.2"), SPort: uint16(53361), Type: TCP})) - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: util.AddressFromString("10.0.0.2"), SPort: uint16(53361), Type: UDP})) + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("172.0.0.1"), SPort: uint16(10), Type: TCP}})) + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("*"), SPort: uint16(9000), Type: TCP}})) // only port 9000 + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.1.24"), SPort: uint16(9000), Type: TCP}})) + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("::7f00:35:0:0"), SPort: uint16(443), Type: TCP}})) // ipv6 + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("::"), SPort: uint16(443), Type: TCP}})) // 0 == ::7f00:35:0:0 + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.0.10"), SPort: uint16(6666), Type: TCP}})) // port wildcard + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.0.10"), SPort: uint16(33), Type: TCP}})) + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.0.25"), SPort: uint16(30), Type: TCP}})) // bad config + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("123.ABCD"), SPort: uint16(30), Type: TCP}})) // bad IP config + + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("172.0.0.2"), SPort: uint16(100), Type: TCP}})) + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("::7f00:35:0:1"), SPort: uint16(100), Type: TCP}})) // invalid port + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.0.11"), SPort: uint16(6666), Type: TCP}})) // port wildcard + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.0.26"), SPort: uint16(30), Type: TCP}})) // invalid port range + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.0.1"), SPort: uint16(100), Type: TCP}})) // tcp wildcard + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.0.2"), SPort: uint16(53363), Type: UDP}})) + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.0.2"), SPort: uint16(53361), Type: TCP}})) + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: util.AddressFromString("10.0.0.2"), SPort: uint16(53361), Type: UDP}})) // destination - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("10.0.0.5"), DPort: uint16(8080), Type: TCP})) - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("10.0.0.5"), DPort: uint16(80), Type: TCP})) - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString(""), DPort: uint16(1234), Type: TCP})) - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("2001:db8::2:1"), DPort: uint16(5001), Type: TCP})) // ipv6 - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("2001:db8::5:1"), DPort: uint16(80), Type: TCP})) // ipv6 CIDR - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("1.1.1.1"), DPort: uint16(11211), Type: TCP})) - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("*"), DPort: uint16(30), Type: TCP})) - - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("2001:db8::2:2"), DPort: uint16(3333), Type: UDP})) // invalid config - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("10.0.0.3/24"), DPort: uint16(80), Type: TCP})) // invalid config - assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("10.0.0.4"), DPort: uint16(1234), Type: TCP})) // port wildcard - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("2001:db8::2:2"), DPort: uint16(8082), Type: TCP})) // invalid config - assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: util.AddressFromString("10.0.0.5"), DPort: uint16(0), Type: TCP})) // invalid port + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("10.0.0.5"), DPort: uint16(8080), Type: TCP}})) + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("10.0.0.5"), DPort: uint16(80), Type: TCP}})) + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString(""), DPort: uint16(1234), Type: TCP}})) + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("2001:db8::2:1"), DPort: uint16(5001), Type: TCP}})) // ipv6 + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("2001:db8::5:1"), DPort: uint16(80), Type: TCP}})) // ipv6 CIDR + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("1.1.1.1"), DPort: uint16(11211), Type: TCP}})) + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("*"), DPort: uint16(30), Type: TCP}})) + + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("2001:db8::2:2"), DPort: uint16(3333), Type: UDP}})) // invalid config + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("10.0.0.3/24"), DPort: uint16(80), Type: TCP}})) // invalid config + assert.True(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("10.0.0.4"), DPort: uint16(1234), Type: TCP}})) // port wildcard + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("2001:db8::2:2"), DPort: uint16(8082), Type: TCP}})) // invalid config + assert.False(t, IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: util.AddressFromString("10.0.0.5"), DPort: uint16(0), Type: TCP}})) // invalid port } var sink bool @@ -96,8 +96,8 @@ func BenchmarkIsBlacklistedConnectionIPv4(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, addr := range addrs { - sink = IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: addr, SPort: uint16(rand.Intn(9999)), Type: TCP}) - sink = IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: addr, DPort: uint16(rand.Intn(9999)), Type: TCP}) + sink = IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addr, SPort: uint16(rand.Intn(9999)), Type: TCP}}) + sink = IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: addr, DPort: uint16(rand.Intn(9999)), Type: TCP}}) } } @@ -112,8 +112,8 @@ func BenchmarkIsBlacklistedConnectionIPv6(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, addr := range addrs { - sink = IsExcludedConnection(sourceList, destList, &ConnectionStats{Source: addr, SPort: uint16(rand.Intn(9999)), Type: TCP}) - sink = IsExcludedConnection(sourceList, destList, &ConnectionStats{Dest: addr, DPort: uint16(rand.Intn(9999)), Type: TCP}) + sink = IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Source: addr, SPort: uint16(rand.Intn(9999)), Type: TCP}}) + sink = IsExcludedConnection(sourceList, destList, &ConnectionStats{ConnectionTuple: ConnectionTuple{Dest: addr, DPort: uint16(rand.Intn(9999)), Type: TCP}}) } } } diff --git a/pkg/network/protocols/types.go b/pkg/network/protocols/types.go index cc1fffbebde04..f74f4c0f1a138 100644 --- a/pkg/network/protocols/types.go +++ b/pkg/network/protocols/types.go @@ -6,7 +6,7 @@ package protocols // ProtocolType is an enum of supported protocols -type ProtocolType uint16 +type ProtocolType uint8 const ( // Unknown is the default value, protocol was not detected diff --git a/pkg/network/resolver_test.go b/pkg/network/resolver_test.go index 342e87e0afc52..c0977141ee34b 100644 --- a/pkg/network/resolver_test.go +++ b/pkg/network/resolver_test.go @@ -18,13 +18,15 @@ import ( func TestResolveLocalConnections(t *testing.T) { conns := []ConnectionStats{ - { - Pid: 8579, - Source: util.AddressFromString("172.29.132.189"), - SPort: 37432, - Dest: util.AddressFromString("172.29.168.124"), - DPort: 8080, - NetNS: 4026533024, + {ConnectionTuple: ConnectionTuple{ + Pid: 8579, + Source: util.AddressFromString("172.29.132.189"), + SPort: 37432, + Dest: util.AddressFromString("172.29.168.124"), + DPort: 8080, + NetNS: 4026533024, + Type: TCP, + }, Direction: OUTGOING, ContainerID: struct { Source *intern.Value @@ -32,16 +34,17 @@ func TestResolveLocalConnections(t *testing.T) { }{ Source: intern.GetByString("6254f6bc5dc03a50440268c2c0771c476fb9a7230c510afef6114c4498b2a4f8"), }, - Type: TCP, IntraHost: true, }, - { - Pid: 8576, - Source: util.AddressFromString("172.29.132.189"), - SPort: 46822, - Dest: util.AddressFromString("172.29.168.124"), - DPort: 8080, - NetNS: 4026533024, + {ConnectionTuple: ConnectionTuple{ + Pid: 8576, + Source: util.AddressFromString("172.29.132.189"), + SPort: 46822, + Dest: util.AddressFromString("172.29.168.124"), + DPort: 8080, + NetNS: 4026533024, + Type: TCP, + }, Direction: OUTGOING, ContainerID: struct { Source *intern.Value @@ -49,16 +52,17 @@ func TestResolveLocalConnections(t *testing.T) { }{ Source: intern.GetByString("6254f6bc5dc03a50440268c2c0771c476fb9a7230c510afef6114c4498b2a4f8"), }, - Type: TCP, IntraHost: true, }, - { - Pid: 1342852, - Source: util.AddressFromString("172.29.168.124"), - SPort: 8080, - Dest: util.AddressFromString("172.29.132.189"), - DPort: 46822, - NetNS: 4026533176, + {ConnectionTuple: ConnectionTuple{ + Pid: 1342852, + Source: util.AddressFromString("172.29.168.124"), + SPort: 8080, + Dest: util.AddressFromString("172.29.132.189"), + DPort: 46822, + NetNS: 4026533176, + Type: TCP, + }, Direction: INCOMING, ContainerID: struct { Source *intern.Value @@ -66,16 +70,17 @@ func TestResolveLocalConnections(t *testing.T) { }{ Source: intern.GetByString("7e999c2c2349713e27cecf87ef8e0cf496aec08b06b6a8b8c988dd42a3839a98"), }, - Type: TCP, IntraHost: true, }, - { - Pid: 1344818, - Source: util.AddressFromString("172.29.168.124"), - SPort: 8080, - Dest: util.AddressFromString("172.29.132.189"), - DPort: 37432, - NetNS: 4026533176, + {ConnectionTuple: ConnectionTuple{ + Pid: 1344818, + Source: util.AddressFromString("172.29.168.124"), + SPort: 8080, + Dest: util.AddressFromString("172.29.132.189"), + DPort: 37432, + NetNS: 4026533176, + Type: TCP, + }, Direction: INCOMING, ContainerID: struct { Source *intern.Value @@ -83,7 +88,6 @@ func TestResolveLocalConnections(t *testing.T) { }{ Source: intern.GetByString("7e999c2c2349713e27cecf87ef8e0cf496aec08b06b6a8b8c988dd42a3839a98"), }, - Type: TCP, IntraHost: true, }, } @@ -111,19 +115,20 @@ func TestResolveLoopbackConnections(t *testing.T) { }{ { name: "raddr resolution with nat", - conn: ConnectionStats{ + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 1, Source: util.AddressFromString("127.0.0.1"), SPort: 1234, Dest: util.AddressFromString("10.1.1.2"), DPort: 1234, + NetNS: 1, + }, IPTranslation: &IPTranslation{ ReplDstIP: util.AddressFromString("127.0.0.1"), ReplDstPort: 1234, ReplSrcIP: util.AddressFromString("10.1.1.2"), ReplSrcPort: 1234, }, - NetNS: 1, Direction: INCOMING, IntraHost: true, ContainerID: struct { @@ -137,13 +142,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "raddr resolution with nat to localhost", - conn: ConnectionStats{ + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 2, NetNS: 1, Source: util.AddressFromString("10.1.1.2"), SPort: 1234, Dest: util.AddressFromString("10.1.1.1"), DPort: 1234, + }, IPTranslation: &IPTranslation{ ReplDstIP: util.AddressFromString("10.1.1.2"), ReplDstPort: 1234, @@ -163,13 +169,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "raddr failed localhost resolution", - conn: ConnectionStats{ - Pid: 3, - NetNS: 3, - Source: util.AddressFromString("127.0.0.1"), - SPort: 1235, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 1234, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 3, + NetNS: 3, + Source: util.AddressFromString("127.0.0.1"), + SPort: 1235, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 1234, + }, IntraHost: true, Direction: INCOMING, ContainerID: struct { @@ -183,13 +190,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "raddr resolution within same netns (3)", - conn: ConnectionStats{ - Pid: 5, - NetNS: 3, - Source: util.AddressFromString("127.0.0.1"), - SPort: 1240, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 1235, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 5, + NetNS: 3, + Source: util.AddressFromString("127.0.0.1"), + SPort: 1240, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 1235, + }, IntraHost: true, Direction: OUTGOING, ContainerID: struct { @@ -203,13 +211,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "raddr resolution within same netns (1)", - conn: ConnectionStats{ - Pid: 3, - NetNS: 3, - Source: util.AddressFromString("127.0.0.1"), - SPort: 1235, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 1240, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 3, + NetNS: 3, + Source: util.AddressFromString("127.0.0.1"), + SPort: 1235, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 1240, + }, IntraHost: true, Direction: INCOMING, ContainerID: struct { @@ -223,13 +232,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "raddr resolution within same netns (2)", - conn: ConnectionStats{ - Pid: 5, - NetNS: 3, - Source: util.AddressFromString("127.0.0.1"), - SPort: 1240, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 1235, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 5, + NetNS: 3, + Source: util.AddressFromString("127.0.0.1"), + SPort: 1240, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 1235, + }, IntraHost: true, Direction: OUTGOING, ContainerID: struct { @@ -243,13 +253,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "raddr failed resolution, known address in different netns", - conn: ConnectionStats{ - Pid: 5, - NetNS: 4, - Source: util.AddressFromString("127.0.0.1"), - SPort: 1240, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 1235, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 5, + NetNS: 4, + Source: util.AddressFromString("127.0.0.1"), + SPort: 1240, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 1235, + }, IntraHost: true, Direction: OUTGOING, ContainerID: struct { @@ -263,13 +274,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "failed laddr and raddr resolution", - conn: ConnectionStats{ - Pid: 10, - NetNS: 10, - Source: util.AddressFromString("127.0.0.1"), - SPort: 1234, - Dest: util.AddressFromString("10.1.1.1"), - DPort: 1235, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 10, + NetNS: 10, + Source: util.AddressFromString("127.0.0.1"), + SPort: 1234, + Dest: util.AddressFromString("10.1.1.1"), + DPort: 1235, + }, Direction: OUTGOING, IntraHost: false, }, @@ -277,13 +289,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "failed resolution: unknown pid for laddr, raddr address in different netns from known address", - conn: ConnectionStats{ - Pid: 11, - NetNS: 10, - Source: util.AddressFromString("127.0.0.1"), - SPort: 1250, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 1240, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 11, + NetNS: 10, + Source: util.AddressFromString("127.0.0.1"), + SPort: 1250, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 1240, + }, Direction: OUTGOING, IntraHost: true, }, @@ -291,13 +304,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "localhost resolution within same netns 1/2", - conn: ConnectionStats{ - Pid: 6, - NetNS: 7, - Source: util.AddressFromString("127.0.0.1"), - SPort: 1260, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 1250, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 6, + NetNS: 7, + Source: util.AddressFromString("127.0.0.1"), + SPort: 1260, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 1250, + }, Direction: OUTGOING, IntraHost: true, ContainerID: struct { @@ -311,13 +325,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "localhost resolution within same netns 2/2", - conn: ConnectionStats{ - Pid: 7, - NetNS: 7, - Source: util.AddressFromString("127.0.0.1"), - SPort: 1250, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 1260, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 7, + NetNS: 7, + Source: util.AddressFromString("127.0.0.1"), + SPort: 1250, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 1260, + }, Direction: INCOMING, IntraHost: true, ContainerID: struct { @@ -331,13 +346,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "zero src netns failed resolution", - conn: ConnectionStats{ - Pid: 22, - NetNS: 0, - Source: util.AddressFromString("127.0.0.1"), - SPort: 8282, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 1250, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 22, + NetNS: 0, + Source: util.AddressFromString("127.0.0.1"), + SPort: 8282, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 1250, + }, Direction: OUTGOING, ContainerID: struct { Source *intern.Value @@ -350,13 +366,14 @@ func TestResolveLoopbackConnections(t *testing.T) { }, { name: "zero src and dst netns failed resolution", - conn: ConnectionStats{ - Pid: 21, - NetNS: 0, - Source: util.AddressFromString("127.0.0.1"), - SPort: 8181, - Dest: util.AddressFromString("127.0.0.1"), - DPort: 8282, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 21, + NetNS: 0, + Source: util.AddressFromString("127.0.0.1"), + SPort: 8181, + Dest: util.AddressFromString("127.0.0.1"), + DPort: 8282, + }, Direction: OUTGOING, ContainerID: struct { Source *intern.Value diff --git a/pkg/network/state.go b/pkg/network/state.go index 7bd2684022837..155e75e78ca07 100644 --- a/pkg/network/state.go +++ b/pkg/network/state.go @@ -6,7 +6,6 @@ package network import ( - "bytes" "fmt" "strconv" "sync" @@ -285,28 +284,22 @@ type networkState struct { enableConnectionRollup bool processEventConsumerEnabled bool - mergeStatsBuffers [2][]byte - localResolver LocalResolver } // NewState creates a new network state func NewState(_ telemetryComponent.Component, clientExpiry time.Duration, maxClosedConns uint32, maxClientStats, maxDNSStats, maxHTTPStats, maxKafkaStats, maxPostgresStats, maxRedisStats int, enableConnectionRollup bool, processEventConsumerEnabled bool) State { ns := &networkState{ - clients: map[string]*client{}, - clientExpiry: clientExpiry, - maxClosedConns: maxClosedConns, - maxClientStats: maxClientStats, - maxDNSStats: maxDNSStats, - maxHTTPStats: maxHTTPStats, - maxKafkaStats: maxKafkaStats, - maxPostgresStats: maxPostgresStats, - maxRedisStats: maxRedisStats, - enableConnectionRollup: enableConnectionRollup, - mergeStatsBuffers: [2][]byte{ - make([]byte, ConnectionByteKeyMaxLen), - make([]byte, ConnectionByteKeyMaxLen), - }, + clients: map[string]*client{}, + clientExpiry: clientExpiry, + maxClosedConns: maxClosedConns, + maxClientStats: maxClientStats, + maxDNSStats: maxDNSStats, + maxHTTPStats: maxHTTPStats, + maxKafkaStats: maxKafkaStats, + maxPostgresStats: maxPostgresStats, + maxRedisStats: maxRedisStats, + enableConnectionRollup: enableConnectionRollup, localResolver: NewLocalResolver(processEventConsumerEnabled), processEventConsumerEnabled: processEventConsumerEnabled, } @@ -1222,8 +1215,7 @@ type aggregateConnection struct { } type aggregationKey struct { - // connKey is the key returned by ConnectionStats.ByteKey() - connKey string + connKey ConnectionTuple direction ConnectionDirection containers struct { source, dest *intern.Value @@ -1232,7 +1224,6 @@ type aggregationKey struct { type connectionAggregator struct { conns map[aggregationKey][]*aggregateConnection - buf []byte dnsStats dns.StatsByKeyByNameByType enablePortRollups bool processEventConsumerEnabled bool @@ -1241,7 +1232,6 @@ type connectionAggregator struct { func newConnectionAggregator(size int, enablePortRollups, processEventConsumerEnabled bool, dnsStats dns.StatsByKeyByNameByType) *connectionAggregator { return &connectionAggregator{ conns: make(map[aggregationKey][]*aggregateConnection, size), - buf: make([]byte, ConnectionByteKeyMaxLen), dnsStats: dnsStats, enablePortRollups: enablePortRollups, processEventConsumerEnabled: processEventConsumerEnabled, @@ -1249,7 +1239,7 @@ func newConnectionAggregator(size int, enablePortRollups, processEventConsumerEn } func (a *connectionAggregator) key(c *ConnectionStats) (key aggregationKey, sportRolledUp, dportRolledUp bool) { - key.connKey = string(c.ByteKey(a.buf)) + key.connKey = c.ConnectionTuple key.direction = c.Direction if a.processEventConsumerEnabled { key.containers.source = c.ContainerID.Source @@ -1297,7 +1287,7 @@ func (a *connectionAggregator) key(c *ConnectionStats) (key aggregationKey, spor }() } - key.connKey = string(c.ByteKey(a.buf)) + key.connKey = c.ConnectionTuple return key, sportRolledUp, dportRolledUp } @@ -1477,7 +1467,7 @@ func (ns *networkState) mergeConnectionStats(a, b *ConnectionStats) (collision b return false } - if !bytes.Equal(a.ByteKey(ns.mergeStatsBuffers[0]), b.ByteKey(ns.mergeStatsBuffers[1])) { + if a.ConnectionTuple != b.ConnectionTuple { log.Debugf("cookie collision for connections %+v and %+v", a, b) // cookie collision return true diff --git a/pkg/network/state_intrahost_test.go b/pkg/network/state_intrahost_test.go index 1e2400ba87226..a908c533e822e 100644 --- a/pkg/network/state_intrahost_test.go +++ b/pkg/network/state_intrahost_test.go @@ -37,13 +37,13 @@ func TestSNATIntraHost(t *testing.T) { } func CreateConnectionStat(source string, dest string, SPort uint16, DPort uint16, connType ConnectionType) ConnectionStats { - return ConnectionStats{ + return ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString(source), Dest: util.AddressFromString(dest), SPort: SPort, DPort: DPort, Type: connType, - } + }} } func AddIPTranslationToConnection(conn *ConnectionStats, ReplSrcIP string, ReplDstIP string, ReplSrcPort uint16, ReplDstPort uint16) { diff --git a/pkg/network/state_linux_test.go b/pkg/network/state_linux_test.go index 1c08d4efca865..2a1f3a9b4df80 100644 --- a/pkg/network/state_linux_test.go +++ b/pkg/network/state_linux_test.go @@ -18,12 +18,13 @@ import ( ) func TestStatsOverflow(t *testing.T) { - conn := ConnectionStats{ - Pid: 123, - Type: TCP, - Family: AFINET, - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("127.0.0.1"), + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: TCP, + Family: AFINET, + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("127.0.0.1"), + }, Monotonic: StatCounters{SentPackets: math.MaxUint32 - 1, RecvPackets: math.MaxUint32 - 2}, IntraHost: true, } diff --git a/pkg/network/state_test.go b/pkg/network/state_test.go index a1134d192ce34..2e6c77c8f12f7 100644 --- a/pkg/network/state_test.go +++ b/pkg/network/state_test.go @@ -109,7 +109,7 @@ func BenchmarkConnectionsGet(b *testing.B) { } func TestRemoveConnections(t *testing.T) { - conn := ConnectionStats{ + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: UDP, Family: AFINET, @@ -117,6 +117,7 @@ func TestRemoveConnections(t *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: 31890, DPort: 80, + }, Monotonic: StatCounters{ SentBytes: 12345, RecvBytes: 6789, @@ -148,7 +149,7 @@ func TestRemoveConnections(t *testing.T) { } func TestRetrieveClosedConnection(t *testing.T) { - conn := ConnectionStats{ + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: TCP, Family: AFINET, @@ -156,6 +157,7 @@ func TestRetrieveClosedConnection(t *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: 31890, DPort: 80, + }, Monotonic: StatCounters{ SentBytes: 12345, RecvBytes: 6789, @@ -202,7 +204,7 @@ func TestRetrieveClosedConnection(t *testing.T) { } func TestDropActiveConnections(t *testing.T) { - conn := ConnectionStats{ + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: TCP, Family: AFINET, @@ -210,6 +212,7 @@ func TestDropActiveConnections(t *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: 31890, DPort: 80, + }, Monotonic: StatCounters{ SentBytes: 12345, RecvBytes: 6789, @@ -245,7 +248,7 @@ func TestDropActiveConnections(t *testing.T) { } func TestDropEmptyConnections(t *testing.T) { - conn := ConnectionStats{ + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: TCP, Family: AFINET, @@ -253,6 +256,7 @@ func TestDropEmptyConnections(t *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: 31890, DPort: 80, + }, Monotonic: StatCounters{ SentBytes: 12345, RecvBytes: 6789, @@ -565,7 +569,7 @@ func TestTelemetryDiffing(t *testing.T) { func TestNoPriorRegistrationActiveConnections(t *testing.T) { clientID := "1" state := newDefaultState() - conn := ConnectionStats{ + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: TCP, Family: AFINET, @@ -573,6 +577,7 @@ func TestNoPriorRegistrationActiveConnections(t *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: 9000, DPort: 1234, + }, Monotonic: StatCounters{ SentBytes: 1, }, @@ -622,14 +627,15 @@ func TestLastStats(t *testing.T) { Retransmits: 2, } - conn := ConnectionStats{ - Pid: 123, - Type: TCP, - Family: AFINET, - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("127.0.0.1"), - SPort: 31890, - DPort: 80, + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: TCP, + Family: AFINET, + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("127.0.0.1"), + SPort: 31890, + DPort: 80, + }, Monotonic: m, } @@ -710,14 +716,15 @@ func TestLastStatsForClosedConnection(t *testing.T) { Retransmits: 1, } - conn := ConnectionStats{ - Pid: 123, - Type: TCP, - Family: AFINET, - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("127.0.0.1"), - SPort: 31890, - DPort: 80, + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: TCP, + Family: AFINET, + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("127.0.0.1"), + SPort: 31890, + DPort: 80, + }, Monotonic: m, } @@ -763,7 +770,7 @@ func TestRaceConditions(_ *testing.T) { genConns := func(n uint32) []ConnectionStats { conns := make([]ConnectionStats, 0, n) for i := uint32(0); i < n; i++ { - conns = append(conns, ConnectionStats{ + conns = append(conns, ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 1 + i, Type: TCP, Family: AFINET, @@ -771,6 +778,7 @@ func TestRaceConditions(_ *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: uint16(rand.Int()), DPort: uint16(rand.Int()), + }, Monotonic: StatCounters{ SentBytes: uint64(rand.Int()), RecvBytes: uint64(rand.Int()), @@ -813,12 +821,13 @@ func TestSameKeyEdgeCases(t *testing.T) { // Each horizontal bar represents a connection lifespan (from start to end with the number of sent bytes written on top of the line) client := "c" - conn := ConnectionStats{ - Pid: 123, - Type: TCP, - Family: AFINET, - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("127.0.0.1"), + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: TCP, + Family: AFINET, + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("127.0.0.1"), + }, Monotonic: StatCounters{SentBytes: 3}, Cookie: 1, } @@ -923,14 +932,15 @@ func TestSameKeyEdgeCases(t *testing.T) { conns := state.GetDelta(client, latestEpochTime(), nil, nil, nil).Conns assert.Len(t, conns, 0) - conn := ConnectionStats{ - Pid: 123, - Type: TCP, - Family: AFINET, - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("127.0.0.1"), - SPort: 9000, - DPort: 1234, + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: TCP, + Family: AFINET, + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("127.0.0.1"), + SPort: 9000, + DPort: 1234, + }, Monotonic: StatCounters{SentBytes: 1}, Cookie: 1, } @@ -1444,12 +1454,13 @@ func TestSameKeyEdgeCases(t *testing.T) { } func TestStatsResetOnUnderflow(t *testing.T) { - conn := ConnectionStats{ - Pid: 123, - Type: TCP, - Family: AFINET, - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("127.0.0.1"), + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: TCP, + Family: AFINET, + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("127.0.0.1"), + }, Monotonic: StatCounters{SentBytes: 3}, IntraHost: true, } @@ -1477,12 +1488,13 @@ func TestStatsResetOnUnderflow(t *testing.T) { } func TestDoubleCloseOnTwoClients(t *testing.T) { - conn := ConnectionStats{ - Pid: 123, - Type: TCP, - Family: AFINET, - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("127.0.0.1"), + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: TCP, + Family: AFINET, + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("127.0.0.1"), + }, Monotonic: StatCounters{SentBytes: 3}, Last: StatCounters{SentBytes: 3}, IntraHost: true, @@ -1515,12 +1527,13 @@ func TestDoubleCloseOnTwoClients(t *testing.T) { func TestUnorderedCloseEvent(t *testing.T) { stateTelemetry.statsUnderflows.Delete() - conn := ConnectionStats{ - Pid: 123, - Type: TCP, - Family: AFINET, - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("127.0.0.1"), + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: TCP, + Family: AFINET, + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("127.0.0.1"), + }, Monotonic: StatCounters{SentBytes: 3}, } @@ -1567,12 +1580,13 @@ func TestUnorderedCloseEvent(t *testing.T) { } func TestAggregateClosedConnectionsTimestamp(t *testing.T) { - conn := ConnectionStats{ - Pid: 123, - Type: TCP, - Family: AFINET, - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("127.0.0.1"), + conn := ConnectionStats{ConnectionTuple: ConnectionTuple{ + Pid: 123, + Type: TCP, + Family: AFINET, + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("127.0.0.1"), + }, Monotonic: StatCounters{SentBytes: 3}, } @@ -1597,7 +1611,7 @@ func TestAggregateClosedConnectionsTimestamp(t *testing.T) { } func TestDNSStatsWithMultipleClients(t *testing.T) { - c := ConnectionStats{ + c := ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: TCP, Family: AFINET, @@ -1605,7 +1619,7 @@ func TestDNSStatsWithMultipleClients(t *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: 1000, DPort: 53, - } + }} dKey := dns.Key{ClientIP: c.Source, ClientPort: c.SPort, ServerIP: c.Dest, Protocol: getIPProtocol(c.Type)} @@ -1673,12 +1687,12 @@ func TestDNSStatsWithMultipleClients(t *testing.T) { } func TestHTTPStats(t *testing.T) { - c := ConnectionStats{ + c := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("0.0.0.0"), SPort: 1000, DPort: 80, - } + }} key := http.NewKey(c.Source, c.Dest, c.SPort, c.DPort, []byte("/testpath"), true, http.MethodGet) @@ -1701,12 +1715,12 @@ func TestHTTPStats(t *testing.T) { } func TestHTTP2Stats(t *testing.T) { - c := ConnectionStats{ + c := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("0.0.0.0"), SPort: 1000, DPort: 80, - } + }} getStats := func(path string) map[protocols.ProtocolType]interface{} { key := http.NewKey(c.Source, c.Dest, c.SPort, c.DPort, []byte(path), true, http.MethodGet) @@ -1733,12 +1747,12 @@ func TestHTTP2Stats(t *testing.T) { } func TestHTTPStatsWithMultipleClients(t *testing.T) { - c := ConnectionStats{ + c := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("0.0.0.0"), SPort: 1000, DPort: 80, - } + }} getStats := func(path string) map[protocols.ProtocolType]interface{} { httpStats := make(map[http.Key]*http.RequestStats) @@ -1796,12 +1810,12 @@ func TestHTTPStatsWithMultipleClients(t *testing.T) { } func TestHTTP2StatsWithMultipleClients(t *testing.T) { - c := ConnectionStats{ + c := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("0.0.0.0"), SPort: 1000, DPort: 80, - } + }} getStats := func(path string) map[protocols.ProtocolType]interface{} { http2Stats := make(map[http.Key]*http.RequestStats) @@ -1866,31 +1880,32 @@ func TestDetermineConnectionIntraHost(t *testing.T) { }{ { name: "equal source/dest", - conn: ConnectionStats{ + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("1.1.1.1"), SPort: 123, DPort: 456, - }, + }}, intraHost: true, }, { name: "source/dest loopback", - conn: ConnectionStats{ + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("127.0.0.1"), Dest: util.AddressFromString("127.0.0.1"), SPort: 123, DPort: 456, - }, + }}, intraHost: true, }, { name: "dest nat'ed to loopback", - conn: ConnectionStats{ + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("2.2.2.2"), SPort: 123, DPort: 456, + }, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("127.0.0.1"), ReplDstIP: util.AddressFromString("1.1.1.1"), @@ -1902,13 +1917,14 @@ func TestDetermineConnectionIntraHost(t *testing.T) { }, { name: "local connection with nat on both sides (outgoing)", - conn: ConnectionStats{ - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("169.254.169.254"), - SPort: 12345, - DPort: 80, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("169.254.169.254"), + SPort: 12345, + DPort: 80, + NetNS: 1212, + }, Direction: OUTGOING, - NetNS: 1212, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("127.0.0.1"), ReplDstIP: util.AddressFromString("1.1.1.1"), @@ -1920,13 +1936,14 @@ func TestDetermineConnectionIntraHost(t *testing.T) { }, { name: "local connection with nat on both sides (incoming)", - conn: ConnectionStats{ - Source: util.AddressFromString("127.0.0.1"), - Dest: util.AddressFromString("1.1.1.1"), - SPort: 8181, - DPort: 12345, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("127.0.0.1"), + Dest: util.AddressFromString("1.1.1.1"), + SPort: 8181, + DPort: 12345, + NetNS: 1233, + }, Direction: INCOMING, - NetNS: 1233, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("1.1.1.1"), ReplDstIP: util.AddressFromString("169.254.169.254"), @@ -1938,13 +1955,14 @@ func TestDetermineConnectionIntraHost(t *testing.T) { }, { name: "remote connection with source translation (redirect)", - conn: ConnectionStats{ - Source: util.AddressFromString("4.4.4.4"), - Dest: util.AddressFromString("2.2.2.2"), - SPort: 12345, - DPort: 80, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("4.4.4.4"), + Dest: util.AddressFromString("2.2.2.2"), + SPort: 12345, + DPort: 80, + NetNS: 2, + }, Direction: INCOMING, - NetNS: 2, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("2.2.2.2"), ReplDstIP: util.AddressFromString("127.0.0.1"), @@ -1956,61 +1974,66 @@ func TestDetermineConnectionIntraHost(t *testing.T) { }, { name: "local connection, same network ns", - conn: ConnectionStats{ - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("2.2.2.2"), - SPort: 12345, - DPort: 80, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("2.2.2.2"), + SPort: 12345, + DPort: 80, + NetNS: 1, + }, Direction: OUTGOING, - NetNS: 1, }, intraHost: true, }, { name: "local connection, same network ns", - conn: ConnectionStats{ - Source: util.AddressFromString("2.2.2.2"), - Dest: util.AddressFromString("1.1.1.1"), - SPort: 80, - DPort: 12345, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("2.2.2.2"), + Dest: util.AddressFromString("1.1.1.1"), + SPort: 80, + DPort: 12345, + NetNS: 1, + }, Direction: INCOMING, - NetNS: 1, }, intraHost: true, }, { name: "local connection, different network ns", - conn: ConnectionStats{ - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("2.2.2.2"), - SPort: 12345, - DPort: 80, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("2.2.2.2"), + SPort: 12345, + DPort: 80, + NetNS: 1, + }, Direction: OUTGOING, - NetNS: 1, }, intraHost: true, }, { name: "local connection, different network ns", - conn: ConnectionStats{ - Source: util.AddressFromString("2.2.2.2"), - Dest: util.AddressFromString("1.1.1.1"), - SPort: 80, - DPort: 12345, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("2.2.2.2"), + Dest: util.AddressFromString("1.1.1.1"), + SPort: 80, + DPort: 12345, + NetNS: 2, + }, Direction: INCOMING, - NetNS: 2, }, intraHost: true, }, { name: "remote connection", - conn: ConnectionStats{ - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("3.3.3.3"), - SPort: 12345, - DPort: 80, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("3.3.3.3"), + SPort: 12345, + DPort: 80, + NetNS: 1, + }, Direction: OUTGOING, - NetNS: 1, }, intraHost: false, }, @@ -2047,75 +2070,81 @@ func TestIntraHostFixDirection(t *testing.T) { }{ { name: "outgoing both non-ephemeral", - conn: ConnectionStats{ + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("1.1.1.1"), + SPort: 123, + DPort: 456, + }, IntraHost: true, - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("1.1.1.1"), - SPort: 123, - DPort: 456, Direction: OUTGOING, }, direction: OUTGOING, }, { name: "outgoing non ephemeral to ephemeral", - conn: ConnectionStats{ + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("1.1.1.1"), + SPort: 123, + DPort: 49612, + }, IntraHost: true, - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("1.1.1.1"), - SPort: 123, - DPort: 49612, Direction: OUTGOING, }, direction: INCOMING, }, { name: "outgoing ephemeral to non ephemeral", - conn: ConnectionStats{ + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("1.1.1.1"), + SPort: 49612, + DPort: 123, + }, IntraHost: true, - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("1.1.1.1"), - SPort: 49612, - DPort: 123, Direction: OUTGOING, }, direction: OUTGOING, }, { name: "incoming udp non ephemeral to ephemeral", - conn: ConnectionStats{ - Type: UDP, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Type: UDP, + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("1.1.1.1"), + SPort: 49612, + DPort: 123, + }, IntraHost: true, - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("1.1.1.1"), - SPort: 49612, - DPort: 123, Direction: INCOMING, }, direction: OUTGOING, }, { name: "incoming udp ephemeral to non ephemeral", - conn: ConnectionStats{ - Type: UDP, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Type: UDP, + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("1.1.1.1"), + SPort: 123, + DPort: 49612, + }, IntraHost: true, - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("1.1.1.1"), - SPort: 123, - DPort: 49612, Direction: INCOMING, }, direction: INCOMING, }, { name: "incoming tcp non ephemeral to ephemeral", - conn: ConnectionStats{ - Type: TCP, + conn: ConnectionStats{ConnectionTuple: ConnectionTuple{ + Type: TCP, + Source: util.AddressFromString("1.1.1.1"), + Dest: util.AddressFromString("1.1.1.1"), + SPort: 49612, + DPort: 123, + }, IntraHost: true, - Source: util.AddressFromString("1.1.1.1"), - Dest: util.AddressFromString("1.1.1.1"), - SPort: 49612, - DPort: 123, Direction: INCOMING, }, direction: INCOMING, @@ -2137,7 +2166,7 @@ func TestIntraHostFixDirection(t *testing.T) { func TestClosedMergingWithAddressCollision(t *testing.T) { const client = "foo" - c1 := ConnectionStats{ + c1 := ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: TCP, Family: AFINET, @@ -2145,6 +2174,7 @@ func TestClosedMergingWithAddressCollision(t *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: 1000, DPort: 8080, + }, Monotonic: StatCounters{ SentBytes: 100, }, @@ -2156,7 +2186,7 @@ func TestClosedMergingWithAddressCollision(t *testing.T) { ReplDstPort: 456, }, } - c2 := ConnectionStats{ + c2 := ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: TCP, Family: AFINET, @@ -2164,6 +2194,7 @@ func TestClosedMergingWithAddressCollision(t *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: 1000, DPort: 8080, + }, Monotonic: StatCounters{ SentBytes: 150, }, @@ -2191,7 +2222,7 @@ func TestClosedMergingWithAddressCollision(t *testing.T) { state.StoreClosedConnection(&c1) state.StoreClosedConnection(&c2) - active := ConnectionStats{ + active := ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: TCP, Family: AFINET, @@ -2199,6 +2230,7 @@ func TestClosedMergingWithAddressCollision(t *testing.T) { Dest: util.AddressFromString("127.0.0.1"), SPort: 1000, DPort: 8080, + }, Monotonic: StatCounters{ SentBytes: 150, }, @@ -2263,12 +2295,12 @@ func TestClosedMergingWithAddressCollision(t *testing.T) { } func TestKafkaStats(t *testing.T) { - c := ConnectionStats{ + c := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("0.0.0.0"), SPort: 1000, DPort: 80, - } + }} key := kafka.NewKey(c.Source, c.Dest, c.SPort, c.DPort, "my-topic", kafka.ProduceAPIKey, 1) @@ -2294,12 +2326,12 @@ func TestKafkaStats(t *testing.T) { } func TestKafkaStatsWithMultipleClients(t *testing.T) { - c := ConnectionStats{ + c := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("1.1.1.1"), Dest: util.AddressFromString("0.0.0.0"), SPort: 1000, DPort: 80, - } + }} getStats := func(topicName string) map[protocols.ProtocolType]interface{} { kafkaStats := make(map[kafka.Key]*kafka.RequestStats) @@ -2362,10 +2394,18 @@ func TestKafkaStatsWithMultipleClients(t *testing.T) { func TestConnectionRollup(t *testing.T) { conns := []ConnectionStats{ - { + {ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("172.29.141.26"), + SPort: 50010, + Family: AFINET, + NetNS: 4026532341, + Pid: 28385, + Dest: util.AddressFromString("10.100.0.10"), + DPort: 53, + Type: UDP, + }, // should be rolled up with next connection Direction: OUTGOING, - Family: AFINET, IntraHost: false, IPTranslation: &IPTranslation{ ReplDstIP: util.AddressFromString("172.29.141.26"), @@ -2374,8 +2414,6 @@ func TestConnectionRollup(t *testing.T) { ReplSrcPort: 53, }, SPortIsEphemeral: EphemeralTrue, - Source: util.AddressFromString("172.29.141.26"), - SPort: 50010, ContainerID: struct{ Source, Dest *intern.Value }{intern.GetByString("4c66f035f6855163dcb6a9e8755b5f81c5f90088cb3938aad617d9992024394f"), nil}, Monotonic: StatCounters{ RecvBytes: 342, @@ -2386,19 +2424,22 @@ func TestConnectionRollup(t *testing.T) { TCPClosed: 0, TCPEstablished: 0, }, - NetNS: 4026532341, - Pid: 28385, - Dest: util.AddressFromString("10.100.0.10"), - DPort: 53, - Type: UDP, Cookie: 1, Duration: time.Second, IsClosed: true, }, - { + {ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("172.29.141.26"), + SPort: 49155, + Family: AFINET, + NetNS: 4026532341, + Pid: 28385, + Dest: util.AddressFromString("10.100.0.10"), + DPort: 53, + Type: UDP, + }, // should be rolled up with previous connection Direction: OUTGOING, - Family: AFINET, IntraHost: false, IPTranslation: &IPTranslation{ ReplDstIP: util.AddressFromString("172.29.141.26"), @@ -2407,8 +2448,6 @@ func TestConnectionRollup(t *testing.T) { ReplSrcPort: 53, }, SPortIsEphemeral: EphemeralTrue, - Source: util.AddressFromString("172.29.141.26"), - SPort: 49155, ContainerID: struct{ Source, Dest *intern.Value }{Source: intern.GetByString("4c66f035f6855163dcb6a9e8755b5f81c5f90088cb3938aad617d9992024394f")}, Monotonic: StatCounters{ RecvBytes: 314, @@ -2419,19 +2458,22 @@ func TestConnectionRollup(t *testing.T) { TCPClosed: 0, TCPEstablished: 0, }, - NetNS: 4026532341, - Pid: 28385, - Dest: util.AddressFromString("10.100.0.10"), - DPort: 53, - Type: UDP, Cookie: 2, Duration: time.Second, IsClosed: true, }, - { + {ConnectionTuple: ConnectionTuple{ + Family: AFINET, + Source: util.AddressFromString("172.29.141.26"), + SPort: 52907, + NetNS: 4026532341, + Pid: 28385, + Dest: util.AddressFromString("10.100.0.10"), + DPort: 53, + Type: UDP, + }, // should be rolled up with next connection Direction: OUTGOING, - Family: AFINET, IntraHost: false, IPTranslation: &IPTranslation{ ReplDstIP: util.AddressFromString("172.29.141.26"), @@ -2440,8 +2482,6 @@ func TestConnectionRollup(t *testing.T) { ReplSrcPort: 53, }, SPortIsEphemeral: EphemeralTrue, - Source: util.AddressFromString("172.29.141.26"), - SPort: 52907, ContainerID: struct{ Source, Dest *intern.Value }{Source: intern.GetByString("4c66f035f6855163dcb6a9e8755b5f81c5f90088cb3938aad617d9992024394f")}, Monotonic: StatCounters{ RecvBytes: 306, @@ -2452,19 +2492,22 @@ func TestConnectionRollup(t *testing.T) { TCPClosed: 0, TCPEstablished: 0, }, - NetNS: 4026532341, - Pid: 28385, - Dest: util.AddressFromString("10.100.0.10"), - DPort: 53, - Type: UDP, Cookie: 3, Duration: time.Second, IsClosed: true, }, - { + {ConnectionTuple: ConnectionTuple{ + Family: AFINET, + Source: util.AddressFromString("172.29.141.26"), + SPort: 52904, + NetNS: 4026532341, + Pid: 28385, + Dest: util.AddressFromString("10.100.0.10"), + DPort: 53, + Type: UDP, + }, // should be rolled up with previous connection Direction: OUTGOING, - Family: AFINET, IntraHost: false, IPTranslation: &IPTranslation{ ReplDstIP: util.AddressFromString("172.29.141.26"), @@ -2473,8 +2516,6 @@ func TestConnectionRollup(t *testing.T) { ReplSrcPort: 53, }, SPortIsEphemeral: EphemeralTrue, - Source: util.AddressFromString("172.29.141.26"), - SPort: 52904, ContainerID: struct{ Source, Dest *intern.Value }{Source: intern.GetByString("4c66f035f6855163dcb6a9e8755b5f81c5f90088cb3938aad617d9992024394f")}, Monotonic: StatCounters{ RecvBytes: 288, @@ -2485,19 +2526,22 @@ func TestConnectionRollup(t *testing.T) { TCPClosed: 0, TCPEstablished: 0, }, - NetNS: 4026532341, - Pid: 28385, - Dest: util.AddressFromString("10.100.0.10"), - DPort: 53, - Type: UDP, Cookie: 4, Duration: time.Second, IsClosed: true, }, - { + {ConnectionTuple: ConnectionTuple{ + Family: AFINET, + Source: util.AddressFromString("172.29.141.26"), + SPort: 37240, + NetNS: 4026532341, + Pid: 28385, + Dest: util.AddressFromString("10.100.0.10"), + DPort: 53, + Type: UDP, + }, // this should not be rolled up as the duration is > 2 mins Direction: OUTGOING, - Family: AFINET, IntraHost: false, IPTranslation: &IPTranslation{ ReplDstIP: util.AddressFromString("172.29.141.26"), @@ -2506,8 +2550,6 @@ func TestConnectionRollup(t *testing.T) { ReplSrcPort: 53, }, SPortIsEphemeral: EphemeralTrue, - Source: util.AddressFromString("172.29.141.26"), - SPort: 37240, ContainerID: struct{ Source, Dest *intern.Value }{Source: intern.GetByString("4c66f035f6855163dcb6a9e8755b5f81c5f90088cb3938aad617d9992024394f")}, Monotonic: StatCounters{ RecvBytes: 594, @@ -2518,24 +2560,21 @@ func TestConnectionRollup(t *testing.T) { TCPClosed: 0, TCPEstablished: 0, }, - NetNS: 4026532341, - Pid: 28385, - Dest: util.AddressFromString("10.100.0.10"), - DPort: 53, - Type: UDP, Cookie: 5, Duration: 3 * time.Minute, IsClosed: true, }, - { - Pid: 5652, - Source: util.AddressFromString("172.29.160.125"), - SPort: 8443, + {ConnectionTuple: ConnectionTuple{ + Pid: 5652, + Source: util.AddressFromString("172.29.160.125"), + SPort: 8443, + Dest: util.AddressFromString("172.29.166.243"), + DPort: 38633, + Family: AFINET, + Type: TCP, + NetNS: 4026531992, + }, ContainerID: struct{ Source, Dest *intern.Value }{Source: intern.GetByString("403ca32ba9b1c3955ba79a84039c9de34d81c83aa3a27ece70b19b3df84c9460")}, - Dest: util.AddressFromString("172.29.166.243"), - DPort: 38633, - Family: AFINET, - Type: TCP, SPortIsEphemeral: EphemeralFalse, Monotonic: StatCounters{ SentBytes: 0, @@ -2546,7 +2585,6 @@ func TestConnectionRollup(t *testing.T) { TCPEstablished: 1, }, Direction: INCOMING, - NetNS: 4026531992, RTT: 262, RTTVar: 131, IntraHost: false, @@ -2554,15 +2592,17 @@ func TestConnectionRollup(t *testing.T) { Duration: time.Second, IsClosed: true, }, - { - Pid: 5652, - Source: util.AddressFromString("172.29.160.125"), - SPort: 8443, + {ConnectionTuple: ConnectionTuple{ + Pid: 5652, + Source: util.AddressFromString("172.29.160.125"), + SPort: 8443, + Dest: util.AddressFromString("172.29.154.189"), + DPort: 60509, + Family: AFINET, + Type: TCP, + NetNS: 4026531992, + }, ContainerID: struct{ Source, Dest *intern.Value }{Source: intern.GetByString("403ca32ba9b1c3955ba79a84039c9de34d81c83aa3a27ece70b19b3df84c9460")}, - Dest: util.AddressFromString("172.29.154.189"), - DPort: 60509, - Family: AFINET, - Type: TCP, SPortIsEphemeral: EphemeralFalse, Monotonic: StatCounters{ SentBytes: 0, @@ -2573,7 +2613,6 @@ func TestConnectionRollup(t *testing.T) { TCPEstablished: 1, }, Direction: INCOMING, - NetNS: 4026531992, RTT: 254, RTTVar: 127, IntraHost: false, @@ -2581,15 +2620,17 @@ func TestConnectionRollup(t *testing.T) { Duration: time.Second, IsClosed: true, }, - { - Pid: 5652, - Source: util.AddressFromString("172.29.160.125"), - SPort: 8443, + {ConnectionTuple: ConnectionTuple{ + Pid: 5652, + Source: util.AddressFromString("172.29.160.125"), + SPort: 8443, + Dest: util.AddressFromString("172.29.166.243"), + DPort: 34715, + Family: AFINET, + Type: TCP, + NetNS: 4026531992, + }, ContainerID: struct{ Source, Dest *intern.Value }{Source: intern.GetByString("403ca32ba9b1c3955ba79a84039c9de34d81c83aa3a27ece70b19b3df84c9460")}, - Dest: util.AddressFromString("172.29.166.243"), - DPort: 34715, - Family: AFINET, - Type: TCP, SPortIsEphemeral: EphemeralFalse, Monotonic: StatCounters{ SentBytes: 2392, @@ -2600,7 +2641,6 @@ func TestConnectionRollup(t *testing.T) { TCPEstablished: 1, }, Direction: INCOMING, - NetNS: 4026531992, RTT: 250, RTTVar: 66, IntraHost: false, @@ -2775,28 +2815,30 @@ func TestFilterConnections(t *testing.T) { func TestDNSPIDCollision(t *testing.T) { conns := []ConnectionStats{ - { - Source: util.AddressFromString("10.1.1.1"), - Dest: util.AddressFromString("8.8.8.8"), - Pid: 1, - SPort: 1000, - DPort: 53, - Type: UDP, - Family: AFINET, + {ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("10.1.1.1"), + Dest: util.AddressFromString("8.8.8.8"), + Pid: 1, + SPort: 1000, + DPort: 53, + Type: UDP, + Family: AFINET, + }, Direction: LOCAL, Cookie: 1, Monotonic: StatCounters{ RecvBytes: 2, }, }, - { - Source: util.AddressFromString("10.1.1.1"), - Dest: util.AddressFromString("8.8.8.8"), - Pid: 2, - SPort: 1000, - DPort: 53, - Type: UDP, - Family: AFINET, + {ConnectionTuple: ConnectionTuple{ + Source: util.AddressFromString("10.1.1.1"), + Dest: util.AddressFromString("8.8.8.8"), + Pid: 2, + SPort: 1000, + DPort: 53, + Type: UDP, + Family: AFINET, + }, Direction: LOCAL, Cookie: 2, Monotonic: StatCounters{ @@ -2838,7 +2880,7 @@ func TestDNSPIDCollision(t *testing.T) { func generateRandConnections(n int) []ConnectionStats { cs := make([]ConnectionStats, 0, n) for i := 0; i < n; i++ { - cs = append(cs, ConnectionStats{ + cs = append(cs, ConnectionStats{ConnectionTuple: ConnectionTuple{ Pid: 123, Type: TCP, Family: AFINET, @@ -2846,6 +2888,7 @@ func generateRandConnections(n int) []ConnectionStats { Dest: util.AddressFromString("127.0.0.1"), SPort: uint16(rand.Intn(math.MaxUint16)), DPort: uint16(rand.Intn(math.MaxUint16)), + }, Monotonic: StatCounters{ RecvBytes: rand.Uint64(), SentBytes: rand.Uint64(), diff --git a/pkg/network/tracer/cached_conntrack.go b/pkg/network/tracer/cached_conntrack.go index de4f6cec213f1..c5ee2d8155641 100644 --- a/pkg/network/tracer/cached_conntrack.go +++ b/pkg/network/tracer/cached_conntrack.go @@ -40,7 +40,9 @@ func newCachedConntrack(procRoot string, conntrackCreator func(netns.NsHandle) ( } cache.cache.OnEvicted = func(_ lru.Key, v interface{}) { - v.(netlink.Conntrack).Close() + if vt, ok := v.(netlink.Conntrack); ok { + vt.Close() + } } return cache @@ -66,6 +68,11 @@ func (cache *cachedConntrack) Exists(c *network.ConnectionStats) (bool, error) { func (cache *cachedConntrack) exists(c *network.ConnectionStats, netns uint32, pid int) (bool, error) { ctrk, err := cache.ensureConntrack(uint64(netns), pid) if err != nil { + // special case for ErrNotPermitted + if errors.Is(err, netlink.ErrNotPermitted) { + return false, nil + } + return false, err } @@ -126,7 +133,16 @@ func (cache *cachedConntrack) ensureConntrack(ino uint64, pid int) (netlink.Conn v, ok := cache.cache.Get(ino) if ok { - return v.(netlink.Conntrack), nil + switch vt := v.(type) { + case netlink.Conntrack: + return vt, nil + case error: + return nil, vt + } + } + + if pid == 0 { + return nil, nil } ns, err := kernel.GetNetNamespaceFromPid(cache.procRoot, pid) @@ -143,6 +159,8 @@ func (cache *cachedConntrack) ensureConntrack(ino uint64, pid int) (netlink.Conn ctrk, err := cache.conntrackCreator(ns) if err != nil { log.Errorf("could not create conntrack object for net ns %d: %s", ino, err) + // negative cache the error + cache.cache.Add(ino, err) return nil, err } diff --git a/pkg/network/tracer/cached_conntrack_test.go b/pkg/network/tracer/cached_conntrack_test.go index cdda2841e5fb0..975b10b140703 100644 --- a/pkg/network/tracer/cached_conntrack_test.go +++ b/pkg/network/tracer/cached_conntrack_test.go @@ -78,6 +78,52 @@ func TestCachedConntrackIgnoreErrExists(t *testing.T) { require.NoError(t, err) } +func TestCachedConntrackIgnoreErrNotPermitted(t *testing.T) { + createCalled := false + cache := newCachedConntrack("/proc", func(_ netns.NsHandle) (netlink.Conntrack, error) { + createCalled = true + return nil, netlink.ErrNotPermitted + }, 1) + + t.Cleanup(func() { cache.Close() }) + + c := &network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ + NetNS: 123455, + Pid: 1, + }} + + exists, err := cache.Exists(c) + require.True(t, createCalled, "conntrack creator not called") + assert.NoError(t, err) + assert.False(t, exists) +} + +func TestCachedConntrackCacheCreatorError(t *testing.T) { + createCalled := false + cache := newCachedConntrack("/proc", func(_ netns.NsHandle) (netlink.Conntrack, error) { + createCalled = true + return nil, assert.AnError + }, 1) + + t.Cleanup(func() { cache.Close() }) + + c := &network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ + NetNS: 123455, + Pid: 1, + }} + + exists, err := cache.Exists(c) + require.True(t, createCalled, "conntrack creator not called") + assert.ErrorIs(t, err, assert.AnError) + assert.False(t, exists) + + createCalled = false + exists, err = cache.Exists(c) + require.False(t, createCalled, "conntrack creator called") + assert.ErrorIs(t, err, assert.AnError) + assert.False(t, exists) +} + func TestCachedConntrackExists(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -98,7 +144,7 @@ func TestCachedConntrackExists(t *testing.T) { daddr := util.AddressFromString("2.3.4.5") var sport uint16 = 23 var dport uint16 = 223 - ct := &network.ConnectionStats{ + ct := &network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Pid: uint32(os.Getpid()), NetNS: 1234, Source: saddr, @@ -107,7 +153,7 @@ func TestCachedConntrackExists(t *testing.T) { DPort: dport, Type: network.TCP, Family: network.AFINET, - } + }} m.EXPECT().Exists(gomock.Not(gomock.Nil())).Times(1).DoAndReturn(func(c *netlink.Con) (bool, error) { require.Equal(t, saddr.String(), c.Origin.Src.Addr().String()) diff --git a/pkg/network/tracer/connection/ebpf_tracer.go b/pkg/network/tracer/connection/ebpf_tracer.go index 4792e6f2aca5a..de5bbf3ccd25a 100644 --- a/pkg/network/tracer/connection/ebpf_tracer.go +++ b/pkg/network/tracer/connection/ebpf_tracer.go @@ -69,6 +69,8 @@ var EbpfTracerTelemetry = struct { tcpDoneFailedTuple *prometheus.Desc tcpFinishConnectFailedTuple *prometheus.Desc tcpCloseTargetFailures *prometheus.Desc + tcpDoneConnectionFlush *prometheus.Desc + tcpCloseConnectionFlush *prometheus.Desc ongoingConnectPidCleaned telemetry.Counter PidCollisions *telemetry.StatCounterWrapper iterationDups telemetry.Counter @@ -93,6 +95,8 @@ var EbpfTracerTelemetry = struct { lastTcpDoneFailedTuple *atomic.Int64 lastTcpFinishConnectFailedTuple *atomic.Int64 lastTcpCloseTargetFailures *atomic.Int64 + lastTcpDoneConnectionFlush *atomic.Int64 + lastTcpCloseConnectionFlush *atomic.Int64 }{ telemetry.NewGauge(connTracerModuleName, "connections", []string{"ip_proto", "family"}, "Gauge measuring the number of active connections in the EBPF map"), prometheus.NewDesc(connTracerModuleName+"__tcp_failed_connects", "Counter measuring the number of failed TCP connections in the EBPF map", nil, nil), @@ -110,6 +114,8 @@ var EbpfTracerTelemetry = struct { prometheus.NewDesc(connTracerModuleName+"__tcp_done_failed_tuple", "Counter measuring the number of failed TCP connections due to tuple collisions", nil, nil), prometheus.NewDesc(connTracerModuleName+"__tcp_finish_connect_failed_tuple", "Counter measuring the number of failed TCP connections due to tuple collisions", nil, nil), prometheus.NewDesc(connTracerModuleName+"__tcp_close_target_failures", "Counter measuring the number of failed TCP connections in tcp_close", nil, nil), + prometheus.NewDesc(connTracerModuleName+"__tcp_done_connection_flush", "Counter measuring the number of connection flushes performed in tcp_done", nil, nil), + prometheus.NewDesc(connTracerModuleName+"__tcp_close_connection_flush", "Counter measuring the number of connection flushes performed in tcp_close", nil, nil), telemetry.NewCounter(connTracerModuleName, "ongoing_connect_pid_cleaned", []string{}, "Counter measuring the number of tcp_ongoing_connect_pid entries cleaned in userspace"), telemetry.NewStatCounterWrapper(connTracerModuleName, "pid_collisions", []string{}, "Counter measuring number of process collisions"), telemetry.NewCounter(connTracerModuleName, "iteration_dups", []string{}, "Counter measuring the number of connections iterated more than once"), @@ -129,6 +135,8 @@ var EbpfTracerTelemetry = struct { atomic.NewInt64(0), atomic.NewInt64(0), atomic.NewInt64(0), + atomic.NewInt64(0), + atomic.NewInt64(0), } type ebpfTracer struct { @@ -362,14 +370,12 @@ func (t *ebpfTracer) Stop() { }) } -func (t *ebpfTracer) GetMap(name string) *ebpf.Map { - switch name { - case probes.ConnectionProtocolMap: - default: - return nil +func (t *ebpfTracer) GetMap(name string) (*ebpf.Map, error) { + m, _, err := t.m.GetMap(name) + if err != nil { + return nil, fmt.Errorf("error getting map %s: %w", name, err) } - m, _, _ := t.m.GetMap(name) - return m + return m, nil } func (t *ebpfTracer) GetConnections(buffer *network.ConnectionBuffer, filter func(*network.ConnectionStats) bool) error { @@ -470,7 +476,7 @@ func removeConnectionFromTelemetry(conn *network.ConnectionStats) { } func (t *ebpfTracer) Remove(conn *network.ConnectionStats) error { - util.ConnStatsToTuple(conn, t.removeTuple) + util.ConnTupleToEBPFTuple(&conn.ConnectionTuple, t.removeTuple) err := t.conns.Delete(t.removeTuple) if err != nil { @@ -533,6 +539,8 @@ func (t *ebpfTracer) Describe(ch chan<- *prometheus.Desc) { ch <- EbpfTracerTelemetry.tcpDoneFailedTuple ch <- EbpfTracerTelemetry.tcpFinishConnectFailedTuple ch <- EbpfTracerTelemetry.tcpCloseTargetFailures + ch <- EbpfTracerTelemetry.tcpDoneConnectionFlush + ch <- EbpfTracerTelemetry.tcpCloseConnectionFlush } // Collect returns the current state of all metrics of the collector @@ -600,6 +608,14 @@ func (t *ebpfTracer) Collect(ch chan<- prometheus.Metric) { delta = int64(ebpfTelemetry.Tcp_close_target_failures) - EbpfTracerTelemetry.lastTcpCloseTargetFailures.Load() EbpfTracerTelemetry.lastTcpCloseTargetFailures.Store(int64(ebpfTelemetry.Tcp_close_target_failures)) ch <- prometheus.MustNewConstMetric(EbpfTracerTelemetry.tcpCloseTargetFailures, prometheus.CounterValue, float64(delta)) + + delta = int64(ebpfTelemetry.Tcp_done_connection_flush) - EbpfTracerTelemetry.lastTcpDoneConnectionFlush.Load() + EbpfTracerTelemetry.lastTcpDoneConnectionFlush.Store(int64(ebpfTelemetry.Tcp_done_connection_flush)) + ch <- prometheus.MustNewConstMetric(EbpfTracerTelemetry.tcpDoneConnectionFlush, prometheus.CounterValue, float64(delta)) + + delta = int64(ebpfTelemetry.Tcp_close_connection_flush) - EbpfTracerTelemetry.lastTcpCloseConnectionFlush.Load() + EbpfTracerTelemetry.lastTcpCloseConnectionFlush.Store(int64(ebpfTelemetry.Tcp_close_connection_flush)) + ch <- prometheus.MustNewConstMetric(EbpfTracerTelemetry.tcpCloseConnectionFlush, prometheus.CounterValue, float64(delta)) } // DumpMaps (for debugging purpose) returns all maps content by default or selected maps from maps parameter. @@ -717,13 +733,14 @@ func (t *ebpfTracer) setupMapCleaner(m *manager.Manager) { } func populateConnStats(stats *network.ConnectionStats, t *netebpf.ConnTuple, s *netebpf.ConnStats, ch *cookieHasher) { - *stats = network.ConnectionStats{ + *stats = network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Pid: t.Pid, NetNS: t.Netns, Source: t.SourceAddress(), Dest: t.DestAddress(), SPort: t.Sport, DPort: t.Dport, + }, Monotonic: network.StatCounters{ SentBytes: s.Sent_bytes, RecvBytes: s.Recv_bytes, @@ -781,8 +798,8 @@ func updateTCPStats(conn *network.ConnectionStats, tcpStats *netebpf.TCPStats, r conn.Monotonic.Retransmits = retransmits if tcpStats != nil { - conn.Monotonic.TCPEstablished = uint32(tcpStats.State_transitions >> netebpf.Established & 1) - conn.Monotonic.TCPClosed = uint32(tcpStats.State_transitions >> netebpf.Close & 1) + conn.Monotonic.TCPEstablished = tcpStats.State_transitions >> netebpf.Established & 1 + conn.Monotonic.TCPClosed = tcpStats.State_transitions >> netebpf.Close & 1 conn.RTT = tcpStats.Rtt conn.RTTVar = tcpStats.Rtt_var } diff --git a/pkg/network/tracer/connection/ebpfless_tracer.go b/pkg/network/tracer/connection/ebpfless_tracer.go index 2c467a114aa4b..215df996158dc 100644 --- a/pkg/network/tracer/connection/ebpfless_tracer.go +++ b/pkg/network/tracer/connection/ebpfless_tracer.go @@ -54,14 +54,13 @@ type ebpfLessTracer struct { packetSrc *filter.AFPacketSource exit chan struct{} - keyBuf []byte scratchConn *network.ConnectionStats udp *udpProcessor tcp *tcpProcessor // connection maps - conns map[string]*network.ConnectionStats + conns map[network.ConnectionTuple]*network.ConnectionStats boundPorts *ebpfless.BoundPorts cookieHasher *cookieHasher @@ -81,11 +80,10 @@ func newEbpfLessTracer(cfg *config.Config) (*ebpfLessTracer, error) { config: cfg, packetSrc: packetSrc, exit: make(chan struct{}), - keyBuf: make([]byte, network.ConnectionByteKeyMaxLen), scratchConn: &network.ConnectionStats{}, udp: &udpProcessor{}, tcp: newTCPProcessor(), - conns: make(map[string]*network.ConnectionStats, cfg.MaxTrackedConnections), + conns: make(map[network.ConnectionTuple]*network.ConnectionStats, cfg.MaxTrackedConnections), boundPorts: ebpfless.NewBoundPorts(cfg), cookieHasher: newCookieHasher(), } @@ -99,7 +97,7 @@ func newEbpfLessTracer(cfg *config.Config) (*ebpfLessTracer, error) { } // Start begins collecting network connection data. -func (t *ebpfLessTracer) Start(func(*network.ConnectionStats)) error { +func (t *ebpfLessTracer) Start(_ func(*network.ConnectionStats)) error { if err := t.boundPorts.Start(); err != nil { return fmt.Errorf("could not update bound ports: %w", err) } @@ -190,8 +188,7 @@ func (t *ebpfLessTracer) processConnection( t.m.Lock() defer t.m.Unlock() - key := string(t.scratchConn.ByteKey(t.keyBuf)) - conn := t.conns[key] + conn := t.conns[t.scratchConn.ConnectionTuple] if conn == nil { conn = &network.ConnectionStats{} *conn = *t.scratchConn @@ -219,7 +216,7 @@ func (t *ebpfLessTracer) processConnection( return fmt.Errorf("error getting last updated timestamp for connection: %w", err) } conn.LastUpdateEpoch = uint64(ts) - t.conns[key] = conn + t.conns[t.scratchConn.ConnectionTuple] = conn } log.TraceFunc(func() string { @@ -300,13 +297,13 @@ func (t *ebpfLessTracer) Remove(conn *network.ConnectionStats) error { t.m.Lock() defer t.m.Unlock() - delete(t.conns, string(conn.ByteKey(t.keyBuf))) + delete(t.conns, conn.ConnectionTuple) return nil } // GetMap returns the underlying named map. This is useful if any maps are shared with other eBPF components. // An individual ebpfLessTracer implementation may choose which maps to expose via this function. -func (t *ebpfLessTracer) GetMap(string) *ebpf.Map { return nil } +func (t *ebpfLessTracer) GetMap(string) (*ebpf.Map, error) { return nil, nil } // DumpMaps (for debugging purpose) returns all maps content by default or selected maps from maps parameter. func (t *ebpfLessTracer) DumpMaps(_ io.Writer, _ ...string) error { @@ -359,8 +356,7 @@ func (u *udpProcessor) process(conn *network.ConnectionStats, pktType uint8, udp } type tcpProcessor struct { - buf []byte - conns map[string]struct { + conns map[network.ConnectionTuple]struct { established bool closed bool } @@ -368,8 +364,7 @@ type tcpProcessor struct { func newTCPProcessor() *tcpProcessor { return &tcpProcessor{ - buf: make([]byte, network.ConnectionByteKeyMaxLen), - conns: map[string]struct { + conns: map[network.ConnectionTuple]struct { established bool closed bool }{}, @@ -385,8 +380,7 @@ func (t *tcpProcessor) process(conn *network.ConnectionStats, pktType uint8, ip4 log.TraceFunc(func() string { return fmt.Sprintf("tcp processor: pktType=%+v seq=%+v ack=%+v fin=%+v rst=%+v syn=%+v ack=%+v", pktType, tcp.Seq, tcp.Ack, tcp.FIN, tcp.RST, tcp.SYN, tcp.ACK) }) - key := string(conn.ByteKey(t.buf)) - c := t.conns[key] + c := t.conns[conn.ConnectionTuple] log.TraceFunc(func() string { return fmt.Sprintf("pre ack_seq=%+v", c) }) @@ -405,7 +399,7 @@ func (t *tcpProcessor) process(conn *network.ConnectionStats, pktType uint8, ip4 conn.Monotonic.TCPClosed++ conn.Duration = time.Duration(time.Now().UnixNano() - int64(conn.Duration)) } - delete(t.conns, key) + delete(t.conns, conn.ConnectionTuple) return nil } @@ -417,6 +411,6 @@ func (t *tcpProcessor) process(conn *network.ConnectionStats, pktType uint8, ip4 log.TraceFunc(func() string { return fmt.Sprintf("ack_seq=%+v", c) }) - t.conns[key] = c + t.conns[conn.ConnectionTuple] = c return nil } diff --git a/pkg/network/tracer/connection/failure/failed_conn_consumer.go b/pkg/network/tracer/connection/failure/failed_conn_consumer.go index 4df1a90f29705..cb67e1de88767 100644 --- a/pkg/network/tracer/connection/failure/failed_conn_consumer.go +++ b/pkg/network/tracer/connection/failure/failed_conn_consumer.go @@ -61,10 +61,10 @@ func (c *TCPFailedConnConsumer) Stop() { } func (c *TCPFailedConnConsumer) extractConn(data []byte) { - failedConn := (*netebpf.FailedConn)(unsafe.Pointer(&data[0])) + failedConn := (*Conn)(unsafe.Pointer(&data[0])) failedConnConsumerTelemetry.eventsReceived.Inc() - c.FailedConns.upsertConn(failedConn) + c.FailedConns.UpsertConn(failedConn) } // Start starts the consumer diff --git a/pkg/network/tracer/connection/failure/matching.go b/pkg/network/tracer/connection/failure/matching.go index 4ad1c8ff31c1d..41de01c7f4468 100644 --- a/pkg/network/tracer/connection/failure/matching.go +++ b/pkg/network/tracer/connection/failure/matching.go @@ -20,7 +20,6 @@ import ( "github.com/DataDog/datadog-agent/pkg/network" "github.com/DataDog/datadog-agent/pkg/network/ebpf" "github.com/DataDog/datadog-agent/pkg/network/ebpf/probes" - "github.com/DataDog/datadog-agent/pkg/network/tracer/connection/util" "github.com/DataDog/datadog-agent/pkg/telemetry" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -55,14 +54,10 @@ func (t FailedConnStats) String() string { ) } -// FailedConnMap is a map of connection tuples to failed connection stats -type FailedConnMap map[ebpf.ConnTuple]*FailedConnStats - // FailedConns is a struct to hold failed connections type FailedConns struct { - FailedConnMap map[ebpf.ConnTuple]*FailedConnStats + FailedConnMap map[network.ConnectionTuple]*FailedConnStats maxFailuresBuffered uint32 - failureTuple *ebpf.ConnTuple connCloseFlushedCleaner *ddebpf.MapCleaner[ebpf.ConnTuple, int64] sync.Mutex } @@ -70,16 +65,15 @@ type FailedConns struct { // NewFailedConns returns a new FailedConns struct func NewFailedConns(m *manager.Manager, maxFailedConnsBuffered uint32) *FailedConns { fc := &FailedConns{ - FailedConnMap: make(map[ebpf.ConnTuple]*FailedConnStats), + FailedConnMap: make(map[network.ConnectionTuple]*FailedConnStats), maxFailuresBuffered: maxFailedConnsBuffered, - failureTuple: &ebpf.ConnTuple{}, } fc.setupMapCleaner(m) return fc } -// upsertConn adds or updates the failed connection in the failed connection map -func (fc *FailedConns) upsertConn(failedConn *ebpf.FailedConn) { +// UpsertConn adds or updates the failed connection in the failed connection map +func (fc *FailedConns) UpsertConn(failedConn *Conn) { if fc == nil { return } @@ -91,7 +85,7 @@ func (fc *FailedConns) upsertConn(failedConn *ebpf.FailedConn) { failureTelemetry.failedConnsDropped.Inc() return } - connTuple := failedConn.Tup + connTuple := failedConn.Tuple() stats, ok := fc.FailedConnMap[connTuple] if !ok { @@ -114,16 +108,14 @@ func (fc *FailedConns) MatchFailedConn(conn *network.ConnectionStats) { fc.Lock() defer fc.Unlock() - util.ConnStatsToTuple(conn, fc.failureTuple) - - if failedConn, ok := fc.FailedConnMap[*fc.failureTuple]; ok { + if failedConn, ok := fc.FailedConnMap[conn.ConnectionTuple]; ok { // found matching failed connection conn.TCPFailures = failedConn.CountByErrCode for errCode := range failedConn.CountByErrCode { failureTelemetry.failedConnMatches.Add(1, unix.ErrnoName(syscall.Errno(errCode))) } - delete(fc.FailedConnMap, *fc.failureTuple) + delete(fc.FailedConnMap, conn.ConnectionTuple) } } diff --git a/pkg/network/tracer/connection/failure/types.go b/pkg/network/tracer/connection/failure/types.go new file mode 100644 index 0000000000000..33ff19d928952 --- /dev/null +++ b/pkg/network/tracer/connection/failure/types.go @@ -0,0 +1,43 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024-present Datadog, Inc. + +//go:build linux_bpf + +package failure + +import ( + "github.com/DataDog/datadog-agent/pkg/network" + "github.com/DataDog/datadog-agent/pkg/network/ebpf" +) + +// Conn represents a failed connection +type Conn ebpf.FailedConn + +// Tuple returns a network.ConnectionTuple +func (c Conn) Tuple() network.ConnectionTuple { + ct := network.ConnectionTuple{ + Source: c.Tup.SourceAddress(), + Dest: c.Tup.DestAddress(), + Pid: c.Tup.Pid, + NetNS: c.Tup.Netns, + SPort: c.Tup.Sport, + DPort: c.Tup.Dport, + } + + if c.Tup.Type() == ebpf.TCP { + ct.Type = network.TCP + } else { + ct.Type = network.UDP + } + + switch c.Tup.Family() { + case ebpf.IPv4: + ct.Family = network.AFINET + case ebpf.IPv6: + ct.Family = network.AFINET6 + } + + return ct +} diff --git a/pkg/network/tracer/connection/kprobe/tracer.go b/pkg/network/tracer/connection/kprobe/tracer.go index 9fa6888a53d98..6b2ce3ac7cf1d 100644 --- a/pkg/network/tracer/connection/kprobe/tracer.go +++ b/pkg/network/tracer/connection/kprobe/tracer.go @@ -16,6 +16,7 @@ import ( ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/ebpf/bytecode" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" ebpftelemetry "github.com/DataDog/datadog-agent/pkg/ebpf/telemetry" "github.com/DataDog/datadog-agent/pkg/network/config" netebpf "github.com/DataDog/datadog-agent/pkg/network/ebpf" @@ -138,8 +139,8 @@ func LoadTracer(cfg *config.Config, mgrOpts manager.Options, connCloseEventHandl if cfg.EnableRuntimeCompiler && cfg.AllowRuntimeCompiledFallback { log.Warnf("error loading CO-RE network tracer, falling back to runtime compiled: %s", err) - } else if cfg.AllowPrecompiledFallback { - log.Warnf("error loading CO-RE network tracer, falling back to pre-compiled: %s", err) + } else if cfg.AllowPrebuiltFallback { + log.Warnf("error loading CO-RE network tracer, falling back to prebuilt: %s", err) } else { return nil, nil, TracerTypeCORE, fmt.Errorf("error loading CO-RE network tracer: %w", err) } @@ -151,16 +152,20 @@ func LoadTracer(cfg *config.Config, mgrOpts manager.Options, connCloseEventHandl return m, closeFn, TracerTypeRuntimeCompiled, err } - if !cfg.AllowPrecompiledFallback { + if !cfg.AllowPrebuiltFallback { return nil, nil, TracerTypeRuntimeCompiled, fmt.Errorf("error compiling network tracer: %w", err) } - log.Warnf("error compiling network tracer, falling back to pre-compiled: %s", err) + log.Warnf("error compiling network tracer, falling back to prebuilt: %s", err) + } + + if prebuilt.IsDeprecated() { + log.Warn("using deprecated prebuilt network tracer") } offsets, err := tracerOffsetGuesserRunner(cfg) if err != nil { - return nil, nil, TracerTypePrebuilt, fmt.Errorf("error loading prebuilt tracer: error guessing offsets: %s", err) + return nil, nil, TracerTypePrebuilt, fmt.Errorf("error loading prebuilt tracer: error guessing offsets: %w", err) } mgrOpts.ConstantEditors = append(mgrOpts.ConstantEditors, offsets...) diff --git a/pkg/network/tracer/connection/kprobe/tracer_test.go b/pkg/network/tracer/connection/kprobe/tracer_test.go index f36f6ca060594..4ffa64609bcfc 100644 --- a/pkg/network/tracer/connection/kprobe/tracer_test.go +++ b/pkg/network/tracer/connection/kprobe/tracer_test.go @@ -213,7 +213,7 @@ func runFallbackTests(t *testing.T, desc string, coreErr, rcErr bool, tests []st cfg.EnableCORE = te.enableCORE cfg.AllowRuntimeCompiledFallback = te.allowRCFallback cfg.EnableRuntimeCompiler = te.enableRC - cfg.AllowPrecompiledFallback = te.allowPrebuiltFallback + cfg.AllowPrebuiltFallback = te.allowPrebuiltFallback prevOffsetGuessingRun := offsetGuessingRun _, closeFn, tracerType, err := LoadTracer(cfg, manager.Options{}, nil, nil) diff --git a/pkg/network/tracer/connection/tracer.go b/pkg/network/tracer/connection/tracer.go index c1d318d9108e2..daceae161da79 100644 --- a/pkg/network/tracer/connection/tracer.go +++ b/pkg/network/tracer/connection/tracer.go @@ -54,7 +54,7 @@ type Tracer interface { Remove(conn *network.ConnectionStats) error // GetMap returns the underlying named map. This is useful if any maps are shared with other eBPF components. // An individual tracer implementation may choose which maps to expose via this function. - GetMap(string) *ebpf.Map + GetMap(string) (*ebpf.Map, error) // DumpMaps (for debugging purpose) returns all maps content by default or selected maps from maps parameter. DumpMaps(w io.Writer, maps ...string) error // Type returns the type of the underlying ebpf tracer that is currently loaded diff --git a/pkg/network/tracer/connection/util/conn_tracer.go b/pkg/network/tracer/connection/util/conn_tracer.go index 724e60ec4c4eb..b515cebfcf7f5 100644 --- a/pkg/network/tracer/connection/util/conn_tracer.go +++ b/pkg/network/tracer/connection/util/conn_tracer.go @@ -147,8 +147,8 @@ func AddBoolConst(options *manager.Options, name string, flag bool) { ) } -// ConnStatsToTuple converts a ConnectionStats to a ConnTuple -func ConnStatsToTuple(c *network.ConnectionStats, tup *netebpf.ConnTuple) { +// ConnTupleToEBPFTuple converts a ConnectionTuple to an eBPF ConnTuple +func ConnTupleToEBPFTuple(c *network.ConnectionTuple, tup *netebpf.ConnTuple) { tup.Sport = c.SPort tup.Dport = c.DPort tup.Netns = c.NetNS diff --git a/pkg/network/tracer/conntracker_test.go b/pkg/network/tracer/conntracker_test.go index 3fbc698c70b10..948d1a795bbfb 100644 --- a/pkg/network/tracer/conntracker_test.go +++ b/pkg/network/tracer/conntracker_test.go @@ -21,6 +21,7 @@ import ( "go4.org/netipx" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" "github.com/DataDog/datadog-agent/pkg/network" "github.com/DataDog/datadog-agent/pkg/network/config" "github.com/DataDog/datadog-agent/pkg/network/netlink" @@ -40,7 +41,7 @@ func TestConntrackers(t *testing.T) { if ebpfCOREConntrackerSupportedOnKernelT(t) { modes = append([]ebpftest.BuildMode{ebpftest.CORE}, modes...) } - if ebpfPrebuiltConntrackerSupportedOnKernelT(t) { + if !prebuilt.IsDeprecated() && ebpfPrebuiltConntrackerSupportedOnKernelT(t) { modes = append([]ebpftest.BuildMode{ebpftest.Prebuilt}, modes...) } ebpftest.TestBuildModes(t, modes, "", func(t *testing.T) { @@ -147,7 +148,7 @@ func testConntracker(t *testing.T, serverIP, clientIP net.IP, ct netlink.Conntra localAddr := nettestutil.MustPingTCP(t, clientIP, natPort).LocalAddr().(*net.TCPAddr) var trans *network.IPTranslation - cs := network.ConnectionStats{ + cs := network.ConnectionTuple{ Source: util.AddressFromNetIP(localAddr.IP), SPort: uint16(localAddr.Port), Dest: util.AddressFromNetIP(clientIP), @@ -165,7 +166,7 @@ func testConntracker(t *testing.T, serverIP, clientIP net.IP, ct netlink.Conntra // now dial TCP directly localAddr = nettestutil.MustPingTCP(t, serverIP, nonNatPort).LocalAddr().(*net.TCPAddr) - cs = network.ConnectionStats{ + cs = network.ConnectionTuple{ Source: util.AddressFromNetIP(localAddr.IP), SPort: uint16(localAddr.Port), Dest: util.AddressFromNetIP(serverIP), @@ -189,7 +190,7 @@ func testConntracker(t *testing.T, serverIP, clientIP net.IP, ct netlink.Conntra localAddrUDP := nettestutil.MustPingUDP(t, clientIP, natPort).LocalAddr().(*net.UDPAddr) var trans *network.IPTranslation - cs := network.ConnectionStats{ + cs := network.ConnectionTuple{ Source: util.AddressFromNetIP(localAddrUDP.IP), SPort: uint16(localAddrUDP.Port), Dest: util.AddressFromNetIP(clientIP), @@ -221,7 +222,7 @@ func testConntrackerCrossNamespace(t *testing.T, ct netlink.Conntracker) { t.Logf("test ns: %d", testIno) var trans *network.IPTranslation - cs := network.ConnectionStats{ + cs := network.ConnectionTuple{ Source: util.AddressFromNetIP(laddr.IP), SPort: uint16(laddr.Port), Dest: util.AddressFromString("2.2.2.4"), @@ -277,7 +278,7 @@ func testConntrackerCrossNamespaceNATonRoot(t *testing.T, ct netlink.Conntracker require.NotNil(t, laddr) var trans *network.IPTranslation - cs := network.ConnectionStats{ + cs := network.ConnectionTuple{ Source: util.AddressFromNetIP(laddr.IP), SPort: uint16(laddr.Port), Dest: util.AddressFromString("3.3.3.3"), diff --git a/pkg/network/tracer/ebpf_conntracker.go b/pkg/network/tracer/ebpf_conntracker.go index 87974ca8c06fc..5c97b4983418f 100644 --- a/pkg/network/tracer/ebpf_conntracker.go +++ b/pkg/network/tracer/ebpf_conntracker.go @@ -26,6 +26,7 @@ import ( ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/ebpf/bytecode" "github.com/DataDog/datadog-agent/pkg/ebpf/maps" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" ebpftelemetry "github.com/DataDog/datadog-agent/pkg/ebpf/telemetry" "github.com/DataDog/datadog-agent/pkg/network" "github.com/DataDog/datadog-agent/pkg/network/config" @@ -92,9 +93,9 @@ func NewEBPFConntracker(cfg *config.Config, telemetrycomp telemetryComp.Componen if err != nil { if cfg.EnableRuntimeCompiler && cfg.AllowRuntimeCompiledFallback { log.Warnf("error loading CO-RE conntracker, falling back to runtime compiled: %s", err) - } else if cfg.AllowPrecompiledFallback { + } else if cfg.AllowPrebuiltFallback { allowRC = false - log.Warnf("error loading CO-RE conntracker, falling back to pre-compiled: %s", err) + log.Warnf("error loading CO-RE conntracker, falling back to prebuilt: %s", err) } else { return nil, fmt.Errorf("error loading CO-RE conntracker: %w", err) } @@ -104,7 +105,7 @@ func NewEBPFConntracker(cfg *config.Config, telemetrycomp telemetryComp.Componen if m == nil && allowRC { m, err = ebpfConntrackerRCCreator(cfg) if err != nil { - if !cfg.AllowPrecompiledFallback { + if !cfg.AllowPrebuiltFallback { return nil, fmt.Errorf("unable to compile ebpf conntracker: %w", err) } @@ -112,6 +113,10 @@ func NewEBPFConntracker(cfg *config.Config, telemetrycomp telemetryComp.Componen } } + if prebuilt.IsDeprecated() { + log.Warn("using deprecated prebuilt conntracker") + } + var isPrebuilt bool if m == nil { m, err = ebpfConntrackerPrebuiltCreator(cfg) @@ -203,7 +208,7 @@ func (e *ebpfConntracker) processEvents(ctx context.Context, done <-chan bool) e } } -func toConntrackTupleFromStats(src *netebpf.ConntrackTuple, stats *network.ConnectionStats) { +func toConntrackTupleFromTuple(src *netebpf.ConntrackTuple, stats *network.ConnectionTuple) { src.Sport = stats.SPort src.Dport = stats.DPort src.Saddr_l, src.Saddr_h = util.ToLowHigh(stats.Source) @@ -228,12 +233,12 @@ func (e *ebpfConntracker) GetType() string { return "ebpf" } -func (e *ebpfConntracker) GetTranslationForConn(stats *network.ConnectionStats) *network.IPTranslation { +func (e *ebpfConntracker) GetTranslationForConn(stats *network.ConnectionTuple) *network.IPTranslation { start := time.Now() src := tuplePool.Get() defer tuplePool.Put(src) - toConntrackTupleFromStats(src, stats) + toConntrackTupleFromTuple(src, stats) if log.ShouldLog(seelog.TraceLvl) { log.Tracef("looking up in conntrack (stats): %s", stats) } @@ -319,11 +324,11 @@ func (e *ebpfConntracker) deleteTranslationNs(key *netebpf.ConntrackTuple, ns ui return dst } -func (e *ebpfConntracker) DeleteTranslation(stats *network.ConnectionStats) { +func (e *ebpfConntracker) DeleteTranslation(stats *network.ConnectionTuple) { key := tuplePool.Get() defer tuplePool.Put(key) - toConntrackTupleFromStats(key, stats) + toConntrackTupleFromTuple(key, stats) // attempt a delete from both root and connection's network namespace if dst := e.deleteTranslationNs(key, e.rootNS); dst != nil { diff --git a/pkg/network/tracer/ebpf_conntracker_test.go b/pkg/network/tracer/ebpf_conntracker_test.go index 5acb888ab2b24..e36e60de2000b 100644 --- a/pkg/network/tracer/ebpf_conntracker_test.go +++ b/pkg/network/tracer/ebpf_conntracker_test.go @@ -82,7 +82,7 @@ func TestCOREEbpfConntrackerSkipsLoadOnOlderKernels(t *testing.T) { cfg := testConfig() cfg.EnableRuntimeCompiler = false cfg.EnableCORE = true - cfg.AllowPrecompiledFallback = false + cfg.AllowPrebuiltFallback = false conntracker, err := NewEBPFConntracker(cfg, nil) assert.Error(t, err) assert.ErrorIs(t, err, errCOREConntrackerUnsupported) @@ -114,7 +114,7 @@ func TestEbpfConntrackerEnsureMapType(t *testing.T) { cfg := testConfig() cfg.EnableRuntimeCompiler = true cfg.EnableCORE = false - cfg.AllowPrecompiledFallback = false + cfg.AllowPrebuiltFallback = false checkMap(t, cfg) }) @@ -129,7 +129,7 @@ func TestEbpfConntrackerEnsureMapType(t *testing.T) { cfg := testConfig() cfg.EnableRuntimeCompiler = false cfg.EnableCORE = true - cfg.AllowPrecompiledFallback = false + cfg.AllowPrebuiltFallback = false checkMap(t, cfg) }) } diff --git a/pkg/network/tracer/offsetguess_test.go b/pkg/network/tracer/offsetguess_test.go index 4ae13c0e8e0f8..58080b66f510f 100644 --- a/pkg/network/tracer/offsetguess_test.go +++ b/pkg/network/tracer/offsetguess_test.go @@ -25,6 +25,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/ebpf/bytecode/runtime" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" "github.com/DataDog/datadog-agent/pkg/ebpf/maps" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" netebpf "github.com/DataDog/datadog-agent/pkg/network/ebpf" nettestutil "github.com/DataDog/datadog-agent/pkg/network/testutil" "github.com/DataDog/datadog-agent/pkg/network/tracer/offsetguess" @@ -129,6 +130,9 @@ func (o offsetT) String() string { } func TestOffsetGuess(t *testing.T) { + if prebuilt.IsDeprecated() { + t.Skip("skipping because prebuilt is deprecated on this platform") + } ebpftest.LogLevel(t, "trace") ebpftest.TestBuildMode(t, ebpftest.RuntimeCompiled, "", testOffsetGuess) } @@ -326,6 +330,10 @@ func testOffsetGuess(t *testing.T) { } func TestOffsetGuessPortIPv6Overlap(t *testing.T) { + if prebuilt.IsDeprecated() { + t.Skip("skipping because prebuilt is deprecated on this platform") + } + ebpftest.TestBuildMode(t, ebpftest.RuntimeCompiled, "", func(t *testing.T) { addrs, err := offsetguess.GetIPv6LinkLocalAddress() require.NoError(t, err) diff --git a/pkg/network/tracer/testutil/conntrack.go b/pkg/network/tracer/testutil/conntrack.go index 23b6938006208..9f13ea51cd337 100644 --- a/pkg/network/tracer/testutil/conntrack.go +++ b/pkg/network/tracer/testutil/conntrack.go @@ -19,7 +19,7 @@ type delayedConntracker struct { mux sync.Mutex numDelays int - delayPerConn map[string]int + delayPerConn map[network.ConnectionTuple]int } // NewDelayedConntracker returns a netlink.Conntracker that returns `nil` for `numDelays` @@ -28,18 +28,17 @@ func NewDelayedConntracker(ctr netlink.Conntracker, numDelays int) netlink.Connt return &delayedConntracker{ Conntracker: ctr, numDelays: numDelays, - delayPerConn: make(map[string]int), + delayPerConn: make(map[network.ConnectionTuple]int), } } -func (ctr *delayedConntracker) GetTranslationForConn(c *network.ConnectionStats) *network.IPTranslation { +func (ctr *delayedConntracker) GetTranslationForConn(c *network.ConnectionTuple) *network.IPTranslation { ctr.mux.Lock() defer ctr.mux.Unlock() - key := c.ByteKey(make([]byte, 64)) - delays := ctr.delayPerConn[string(key)] + delays := ctr.delayPerConn[*c] if delays < ctr.numDelays { - ctr.delayPerConn[string(key)]++ + ctr.delayPerConn[*c]++ return nil } diff --git a/pkg/network/tracer/tracer.go b/pkg/network/tracer/tracer.go index a836a4f74ce4b..1a586b3ad9d84 100644 --- a/pkg/network/tracer/tracer.go +++ b/pkg/network/tracer/tracer.go @@ -101,6 +101,9 @@ type Tracer struct { timeResolver *ktime.Resolver telemetryComp telemetryComponent.Component + + // Used for connection_protocol data expiration + connectionProtocolMapCleaner *ddebpf.MapCleaner[netebpf.ConnTuple, netebpf.ProtocolStackWrapper] } // NewTracer creates a Tracer @@ -182,6 +185,19 @@ func newTracer(cfg *config.Config, telemetryComponent telemetryComponent.Compone tr.reverseDNS = newReverseDNS(cfg, telemetryComponent) tr.usmMonitor = newUSMMonitor(cfg, tr.ebpfTracer) + // Set up the connection_protocol map cleaner if protocol classification is enabled + if cfg.ProtocolClassificationEnabled || usmconfig.IsUSMSupportedAndEnabled(cfg) { + connectionProtocolMap, err := tr.ebpfTracer.GetMap(probes.ConnectionProtocolMap) + if err == nil { + tr.connectionProtocolMapCleaner, err = setupConnectionProtocolMapCleaner(connectionProtocolMap) + if err != nil { + log.Warnf("could not set up connection protocol map cleaner: %s", err) + } + } else { + log.Warnf("couldn't get %q map, will not be able to expire connection protocol data: %s", probes.ConnectionProtocolMap, err) + } + } + if cfg.EnableProcessEventMonitoring { if tr.processCache, err = newProcessCache(cfg.MaxProcessesTracked); err != nil { return nil, fmt.Errorf("could not create process cache; %w", err) @@ -304,10 +320,10 @@ func (t *Tracer) storeClosedConnection(cs *network.ConnectionStats) { return } - cs.IPTranslation = t.conntracker.GetTranslationForConn(cs) + cs.IPTranslation = t.conntracker.GetTranslationForConn(&cs.ConnectionTuple) t.connVia(cs) if cs.IPTranslation != nil { - t.conntracker.DeleteTranslation(cs) + t.conntracker.DeleteTranslation(&cs.ConnectionTuple) } t.addProcessInfo(cs) @@ -391,6 +407,7 @@ func (t *Tracer) Stop() { t.processCache.Stop() telemetry.GetCompatComponent().UnregisterCollector(t.processCache) } + t.connectionProtocolMapCleaner.Stop() } // GetActiveConnections returns the delta for connection info from the last time it was called with the same clientID @@ -537,7 +554,7 @@ func (t *Tracer) getConnections(activeBuffer *network.ConnectionBuffer) (latestU activeConnections = activeBuffer.Connections() for i := range activeConnections { - activeConnections[i].IPTranslation = t.conntracker.GetTranslationForConn(&activeConnections[i]) + activeConnections[i].IPTranslation = t.conntracker.GetTranslationForConn(&activeConnections[i].ConnectionTuple) // do gateway resolution only on active connections outside // the map iteration loop to not add to connections while // iterating (leads to ever-increasing connections in the map, @@ -590,7 +607,7 @@ func (t *Tracer) removeEntries(entries []network.ConnectionStats) { } // Delete conntrack entry for this connection - t.conntracker.DeleteTranslation(entry) + t.conntracker.DeleteTranslation(&entry.ConnectionTuple) // Append the connection key to the keys to remove from the userspace state toRemove = append(toRemove, entry) @@ -740,7 +757,8 @@ func (t *Tracer) connectionExpired(conn *network.ConnectionStats, latestTime uin // skip connection check for udp connections or if // the pid for the connection is dead - if conn.Type == network.UDP || !procutil.PidExists(int(conn.Pid)) { + // conn.Pid can be 0 when ebpf-less tracer is running + if conn.Type == network.UDP || (conn.Pid > 0 && !procutil.PidExists(int(conn.Pid))) { return true } @@ -834,8 +852,11 @@ func newUSMMonitor(c *config.Config, tracer connection.Tracer) *usm.Monitor { return nil } - // Shared with the USM program - connectionProtocolMap := tracer.GetMap(probes.ConnectionProtocolMap) + // Shared map between NPM and USM + connectionProtocolMap, err := tracer.GetMap(probes.ConnectionProtocolMap) + if err != nil { + log.Warnf("couldn't get %q map: %s", probes.ConnectionProtocolMap, err) + } monitor, err := usm.NewMonitor(c, connectionProtocolMap) if err != nil { @@ -864,3 +885,22 @@ func (t *Tracer) GetNetworkID(context context.Context) (string, error) { } return id, nil } + +const connProtoTTL = 3 * time.Minute +const connProtoCleaningInterval = 5 * time.Minute + +// setupConnectionProtocolMapCleaner sets up a map cleaner for the connectionProtocolMap. +// It will run every connProtoCleaningInterval and delete entries older than connProtoTTL. +func setupConnectionProtocolMapCleaner(connectionProtocolMap *ebpf.Map) (*ddebpf.MapCleaner[netebpf.ConnTuple, netebpf.ProtocolStackWrapper], error) { + mapCleaner, err := ddebpf.NewMapCleaner[netebpf.ConnTuple, netebpf.ProtocolStackWrapper](connectionProtocolMap, 1024) + if err != nil { + return nil, err + } + + ttl := connProtoTTL.Nanoseconds() + mapCleaner.Clean(connProtoCleaningInterval, nil, nil, func(now int64, _ netebpf.ConnTuple, val netebpf.ProtocolStackWrapper) bool { + return (now - int64(val.Updated)) > ttl + }) + + return mapCleaner, nil +} diff --git a/pkg/network/tracer/tracer_linux_test.go b/pkg/network/tracer/tracer_linux_test.go index 24d577113acca..40ffc8abee4cd 100644 --- a/pkg/network/tracer/tracer_linux_test.go +++ b/pkg/network/tracer/tracer_linux_test.go @@ -443,7 +443,7 @@ func (s *TracerSuite) TestConntrackExpiration() { if !assert.True(collect, ok, "connection not found") { return } - assert.NotNil(collect, tr.conntracker.GetTranslationForConn(conn), "connection does not have NAT translation") + assert.NotNil(collect, tr.conntracker.GetTranslationForConn(&conn.ConnectionTuple), "connection does not have NAT translation") }, 3*time.Second, 100*time.Millisecond, "failed to find connection translation") // This will force the connection to be expired next time we call getConnections, but @@ -452,7 +452,7 @@ func (s *TracerSuite) TestConntrackExpiration() { tr.config.TCPConnTimeout = time.Duration(-1) _ = getConnections(t, tr) - assert.NotNil(t, tr.conntracker.GetTranslationForConn(conn), "translation should not have been deleted") + assert.NotNil(t, tr.conntracker.GetTranslationForConn(&conn.ConnectionTuple), "translation should not have been deleted") // delete the connection from system conntrack cmd := exec.Command("conntrack", "-D", "-s", c.LocalAddr().(*net.TCPAddr).IP.String(), "-d", c.RemoteAddr().(*net.TCPAddr).IP.String(), "-p", "tcp") @@ -460,7 +460,7 @@ func (s *TracerSuite) TestConntrackExpiration() { require.NoError(t, err, "conntrack delete failed, output: %s", out) _ = getConnections(t, tr) - assert.Nil(t, tr.conntracker.GetTranslationForConn(conn), "translation should have been deleted") + assert.Nil(t, tr.conntracker.GetTranslationForConn(&conn.ConnectionTuple), "translation should have been deleted") // write newline so server connections will exit _, err = c.Write([]byte("\n")) @@ -502,7 +502,7 @@ func (s *TracerSuite) TestConntrackDelays() { require.Eventually(t, func() bool { connections := getConnections(t, tr) conn, ok := findConnection(c.LocalAddr(), c.RemoteAddr(), connections) - return ok && tr.conntracker.GetTranslationForConn(conn) != nil + return ok && tr.conntracker.GetTranslationForConn(&conn.ConnectionTuple) != nil }, 3*time.Second, 100*time.Millisecond, "failed to find connection with translation") // write newline so server connections will exit @@ -542,16 +542,16 @@ func (s *TracerSuite) TestTranslationBindingRegression() { // wait for conntrack update laddr := c.LocalAddr().(*net.TCPAddr) raddr := c.RemoteAddr().(*net.TCPAddr) - cs := network.ConnectionStats{ + cs := network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ DPort: uint16(raddr.Port), Dest: util.AddressFromNetIP(raddr.IP), Family: network.AFINET, SPort: uint16(laddr.Port), Source: util.AddressFromNetIP(laddr.IP), Type: network.TCP, - } + }} require.Eventually(t, func() bool { - return tr.conntracker.GetTranslationForConn(&cs) != nil + return tr.conntracker.GetTranslationForConn(&cs.ConnectionTuple) != nil }, 3*time.Second, 100*time.Millisecond, "timed out waiting for conntrack update") // Assert that the connection to 2.2.2.2 has an IPTranslation object bound to it @@ -1353,8 +1353,7 @@ func (s *TracerSuite) TestUDPPythonReusePort() { t.Logf("port is %d", port) - conns := map[string]network.ConnectionStats{} - buf := make([]byte, network.ConnectionByteKeyMaxLen) + conns := map[network.ConnectionTuple]network.ConnectionStats{} require.Eventually(t, func() bool { _conns := network.FilterConnections(getConnections(t, tr), func(cs network.ConnectionStats) bool { return cs.Type == network.UDP && @@ -1364,7 +1363,7 @@ func (s *TracerSuite) TestUDPPythonReusePort() { }) for _, c := range _conns { - conns[string(c.ByteKey(buf))] = c + conns[c.ConnectionTuple] = c } t.Log(conns) @@ -2048,7 +2047,7 @@ func testPreexistingEmptyIncomingConnectionDirection(t *testing.T, config *confi assert.Zero(t, m.SentPackets, "sent packets should be 0") assert.Zero(t, m.RecvPackets, "recv packets should be 0") assert.Zero(t, m.TCPEstablished, "tcp established should be 0") - assert.Equal(t, uint32(1), m.TCPClosed, "tcp closed should be 1") + assert.Equal(t, uint16(1), m.TCPClosed, "tcp closed should be 1") assert.Equal(t, network.INCOMING, conn.Direction, "connection direction should be incoming") } @@ -2111,13 +2110,13 @@ func TestEbpfConntrackerFallback(t *testing.T) { } type testCase struct { - enableCORE bool - allowRuntimeFallback bool - enableRuntimeCompiler bool - allowPrecompiledFallback bool - coreError bool - rcError bool - prebuiltError bool + enableCORE bool + allowRuntimeFallback bool + enableRuntimeCompiler bool + allowPrebuiltFallback bool + coreError bool + rcError bool + prebuiltError bool err error isPrebuilt bool @@ -2127,18 +2126,18 @@ func TestEbpfConntrackerFallback(t *testing.T) { for _, enableCORE := range []bool{false, true} { for _, allowRuntimeFallback := range []bool{false, true} { for _, enableRuntimeCompiler := range []bool{false, true} { - for _, allowPrecompiledFallback := range []bool{false, true} { + for _, allowPrebuiltFallback := range []bool{false, true} { for _, coreError := range coreErrorValues { for _, rcError := range []bool{false, true} { for _, prebuiltError := range prebuiltErrorValues { tc := testCase{ - enableCORE: enableCORE, - allowRuntimeFallback: allowRuntimeFallback, - enableRuntimeCompiler: enableRuntimeCompiler, - allowPrecompiledFallback: allowPrecompiledFallback, - coreError: coreError, - rcError: rcError, - prebuiltError: prebuiltError, + enableCORE: enableCORE, + allowRuntimeFallback: allowRuntimeFallback, + enableRuntimeCompiler: enableRuntimeCompiler, + allowPrebuiltFallback: allowPrebuiltFallback, + coreError: coreError, + rcError: rcError, + prebuiltError: prebuiltError, isPrebuilt: !prebuiltError, } @@ -2159,7 +2158,7 @@ func TestEbpfConntrackerFallback(t *testing.T) { } pberr := prebuiltError - if (enableCORE || rcEnabled) && !allowPrecompiledFallback { + if (enableCORE || rcEnabled) && !allowPrebuiltFallback { pberr = true // not enabled, so assume always failed tc.isPrebuilt = false } @@ -2198,7 +2197,7 @@ func TestEbpfConntrackerFallback(t *testing.T) { cfg.EnableCORE = te.enableCORE cfg.AllowRuntimeCompiledFallback = te.allowRuntimeFallback cfg.EnableRuntimeCompiler = te.enableRuntimeCompiler - cfg.AllowPrecompiledFallback = te.allowPrecompiledFallback + cfg.AllowPrebuiltFallback = te.allowPrebuiltFallback ebpfConntrackerPrebuiltCreator = getPrebuiltConntracker ebpfConntrackerRCCreator = getRCConntracker diff --git a/pkg/network/tracer/tracer_test.go b/pkg/network/tracer/tracer_test.go index d552f29b95bec..c1ef311086fa9 100644 --- a/pkg/network/tracer/tracer_test.go +++ b/pkg/network/tracer/tracer_test.go @@ -262,8 +262,8 @@ func (s *TracerSuite) TestTCPShortLived() { assert.True(t, conn.IntraHost) // Verify the short lived connection is accounting for both TCP_ESTABLISHED and TCP_CLOSED events - assert.Equal(t, uint32(1), m.TCPEstablished) - assert.Equal(t, uint32(1), m.TCPClosed) + assert.Equal(t, uint16(1), m.TCPEstablished) + assert.Equal(t, uint16(1), m.TCPClosed) _, ok := findConnection(c.LocalAddr(), c.RemoteAddr(), getConnections(t, tr)) assert.False(t, ok) @@ -660,57 +660,57 @@ func (s *TracerSuite) TestShouldExcludeEmptyStatsConnection() { func TestSkipConnectionDNS(t *testing.T) { t.Run("CollectLocalDNS disabled", func(t *testing.T) { tr := &Tracer{config: &config.Config{CollectLocalDNS: false}} - assert.True(t, tr.shouldSkipConnection(&network.ConnectionStats{ + assert.True(t, tr.shouldSkipConnection(&network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.1"), Dest: util.AddressFromString("127.0.0.1"), SPort: 1000, DPort: 53, - })) + }})) - assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ + assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.1"), Dest: util.AddressFromString("127.0.0.1"), SPort: 1000, DPort: 8080, - })) + }})) - assert.True(t, tr.shouldSkipConnection(&network.ConnectionStats{ + assert.True(t, tr.shouldSkipConnection(&network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("::3f::45"), Dest: util.AddressFromString("::1"), SPort: 53, DPort: 1000, - })) + }})) - assert.True(t, tr.shouldSkipConnection(&network.ConnectionStats{ + assert.True(t, tr.shouldSkipConnection(&network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("::3f::45"), Dest: util.AddressFromString("::1"), SPort: 53, DPort: 1000, - })) + }})) }) t.Run("CollectLocalDNS disabled", func(t *testing.T) { tr := &Tracer{config: &config.Config{CollectLocalDNS: true}} - assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ + assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.1"), Dest: util.AddressFromString("127.0.0.1"), SPort: 1000, DPort: 53, - })) + }})) - assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ + assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("10.0.0.1"), Dest: util.AddressFromString("127.0.0.1"), SPort: 1000, DPort: 8080, - })) + }})) - assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ + assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("::3f::45"), Dest: util.AddressFromString("::1"), SPort: 53, DPort: 1000, - })) + }})) - assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ + assert.False(t, tr.shouldSkipConnection(&network.ConnectionStats{ConnectionTuple: network.ConnectionTuple{ Source: util.AddressFromString("::3f::45"), Dest: util.AddressFromString("::1"), SPort: 53, DPort: 1000, - })) + }})) }) } @@ -1075,8 +1075,8 @@ func (s *TracerSuite) TestTCPEstablished() { conn, ok := findConnection(laddr, raddr, connections) require.True(t, ok) - assert.Equal(t, uint32(1), conn.Last.TCPEstablished) - assert.Equal(t, uint32(0), conn.Last.TCPClosed) + assert.Equal(t, uint16(1), conn.Last.TCPEstablished) + assert.Equal(t, uint16(0), conn.Last.TCPClosed) c.Close() @@ -1088,8 +1088,8 @@ func (s *TracerSuite) TestTCPEstablished() { }, 3*time.Second, 100*time.Millisecond, "couldn't find connection") require.True(t, ok) - assert.Equal(t, uint32(0), conn.Last.TCPEstablished) - assert.Equal(t, uint32(1), conn.Last.TCPClosed) + assert.Equal(t, uint16(0), conn.Last.TCPEstablished) + assert.Equal(t, uint16(1), conn.Last.TCPClosed) } func (s *TracerSuite) TestTCPEstablishedPreExistingConn() { @@ -1122,8 +1122,8 @@ func (s *TracerSuite) TestTCPEstablishedPreExistingConn() { }, 3*time.Second, 100*time.Millisecond, "couldn't find connection") m := conn.Monotonic - assert.Equal(t, uint32(0), m.TCPEstablished) - assert.Equal(t, uint32(1), m.TCPClosed) + assert.Equal(t, uint16(0), m.TCPEstablished) + assert.Equal(t, uint16(1), m.TCPClosed) } func (s *TracerSuite) TestUnconnectedUDPSendIPv4() { @@ -1407,3 +1407,42 @@ func findFailedConnectionByRemoteAddr(remoteAddr string, conns *network.Connecti } return network.FirstConnection(conns, failureFilter) } + +func BenchmarkGetActiveConnections(b *testing.B) { + cfg := testConfig() + tr := setupTracer(b, cfg) + server := testutil.NewTCPServer(func(c net.Conn) { + io.Copy(io.Discard, c) + c.Close() + }) + b.Cleanup(server.Shutdown) + require.NoError(b, server.Run()) + + b.ReportAllocs() + b.ResetTimer() + + for range b.N { + c, err := net.DialTimeout("tcp", server.Address(), 50*time.Millisecond) + require.NoError(b, err) + laddr, raddr := c.LocalAddr(), c.RemoteAddr() + c.Write([]byte("hello")) + connections := getConnections(b, tr) + conn, ok := findConnection(laddr, raddr, connections) + + require.True(b, ok) + assert.Equal(b, uint32(1), conn.Last.TCPEstablished) + assert.Equal(b, uint32(0), conn.Last.TCPClosed) + c.Close() + + // Wait for the connection to be sent from the perf buffer + require.Eventually(b, func() bool { + var ok bool + conn, ok = findConnection(laddr, raddr, getConnections(b, tr)) + return ok + }, 3*time.Second, 10*time.Millisecond, "couldn't find connection") + + require.True(b, ok) + assert.Equal(b, uint32(0), conn.Last.TCPEstablished) + assert.Equal(b, uint32(1), conn.Last.TCPClosed) + } +} diff --git a/pkg/network/usm/ebpf_gotls.go b/pkg/network/usm/ebpf_gotls.go index 3ae119471d71d..a36d2ba399442 100644 --- a/pkg/network/usm/ebpf_gotls.go +++ b/pkg/network/usm/ebpf_gotls.go @@ -25,6 +25,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/network/usm/buildmode" usmconfig "github.com/DataDog/datadog-agent/pkg/network/usm/config" "github.com/DataDog/datadog-agent/pkg/network/usm/utils" + "github.com/DataDog/datadog-agent/pkg/process/monitor" ) const ( @@ -54,6 +55,7 @@ type goTLSProgram struct { attacher *uprobes.UprobeAttacher inspector *goTLSBinaryInspector cfg *config.Config + procMon *monitor.ProcessMonitor } var goTLSSpec = &protocols.ProtocolSpec{ @@ -145,7 +147,8 @@ func newGoTLSProgramProtocolFactory(m *manager.Manager) protocols.ProtocolFactor binNoSymbolsMetric: libtelemetry.NewCounter("usm.go_tls.missing_symbols", libtelemetry.OptPrometheus), } - attacher, err := uprobes.NewUprobeAttacher(GoTLSAttacherName, attacherCfg, m, nil, inspector) + procMon := monitor.GetProcessMonitor() + attacher, err := uprobes.NewUprobeAttacher(GoTLSAttacherName, attacherCfg, m, nil, inspector, procMon) if err != nil { return nil, fmt.Errorf("cannot create uprobe attacher: %w", err) } @@ -154,6 +157,7 @@ func newGoTLSProgramProtocolFactory(m *manager.Manager) protocols.ProtocolFactor cfg: c, inspector: inspector, attacher: attacher, + procMon: procMon, }, nil } } @@ -208,6 +212,7 @@ func (p *goTLSProgram) GetStats() *protocols.ProtocolStats { // Stop terminates the uprobe attacher for GoTLS programs. func (p *goTLSProgram) Stop(*manager.Manager) { + p.procMon.Stop() p.attacher.Stop() } diff --git a/pkg/network/usm/ebpf_main.go b/pkg/network/usm/ebpf_main.go index cc1bec4f89bf4..b771e85118be5 100644 --- a/pkg/network/usm/ebpf_main.go +++ b/pkg/network/usm/ebpf_main.go @@ -13,17 +13,16 @@ import ( "io" "math" "slices" - "time" "unsafe" + manager "github.com/DataDog/ebpf-manager" "github.com/cilium/ebpf" "github.com/davecgh/go-spew/spew" "golang.org/x/sys/unix" - manager "github.com/DataDog/ebpf-manager" - ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/ebpf/bytecode" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" ebpftelemetry "github.com/DataDog/datadog-agent/pkg/ebpf/telemetry" "github.com/DataDog/datadog-agent/pkg/network" "github.com/DataDog/datadog-agent/pkg/network/config" @@ -89,9 +88,7 @@ type ebpfProgram struct { enabledProtocols []*protocols.ProtocolSpec disabledProtocols []*protocols.ProtocolSpec - // Used for connection_protocol data expiration - mapCleaner *ddebpf.MapCleaner[netebpf.ConnTuple, netebpf.ProtocolStackWrapper] - buildMode buildmode.Type + buildMode buildmode.Type } func newEBPFProgram(c *config.Config, connectionProtocolMap *ebpf.Map) (*ebpfProgram, error) { @@ -188,7 +185,7 @@ func (e *ebpfProgram) Init() error { return nil } - if !e.cfg.AllowRuntimeCompiledFallback && !e.cfg.AllowPrecompiledFallback { + if !e.cfg.AllowRuntimeCompiledFallback && !e.cfg.AllowPrebuiltFallback { return fmt.Errorf("co-re load failed: %w", err) } log.Warnf("co-re load failed. attempting fallback: %s", err) @@ -201,12 +198,16 @@ func (e *ebpfProgram) Init() error { return nil } - if !e.cfg.AllowPrecompiledFallback { + if !e.cfg.AllowPrebuiltFallback { return fmt.Errorf("runtime compilation failed: %w", err) } log.Warnf("runtime compilation failed: attempting fallback: %s", err) } + if prebuilt.IsDeprecated() { + log.Warn("using deprecated prebuilt USM monitor") + } + e.buildMode = buildmode.Prebuilt err = e.initPrebuilt() return err @@ -226,12 +227,6 @@ func (e *ebpfProgram) Start() error { } e.connectionProtocolMap = m } - mapCleaner, err := e.setupMapCleaner() - if err != nil { - log.Errorf("error creating map cleaner: %s", err) - } else { - e.mapCleaner = mapCleaner - } e.enabledProtocols = e.executePerProtocol(e.enabledProtocols, "pre-start", func(protocol protocols.Protocol, m *manager.Manager) error { return protocol.PreStart(m) }, @@ -242,7 +237,7 @@ func (e *ebpfProgram) Start() error { return errNoProtocols } - err = e.Manager.Start() + err := e.Manager.Start() if err != nil { return err } @@ -271,7 +266,6 @@ func (e *ebpfProgram) Start() error { // Close stops the ebpf program and cleans up all resources. func (e *ebpfProgram) Close() error { - e.mapCleaner.Stop() ebpftelemetry.UnregisterTelemetry(e.Manager.Manager) var err error // We need to stop the perf maps and ring buffers before stopping the protocols, as we need to stop sending events @@ -485,23 +479,6 @@ func (e *ebpfProgram) init(buf bytecode.AssetReader, options manager.Options) er return err } -const connProtoTTL = 3 * time.Minute -const connProtoCleaningInterval = 5 * time.Minute - -func (e *ebpfProgram) setupMapCleaner() (*ddebpf.MapCleaner[netebpf.ConnTuple, netebpf.ProtocolStackWrapper], error) { - mapCleaner, err := ddebpf.NewMapCleaner[netebpf.ConnTuple, netebpf.ProtocolStackWrapper](e.connectionProtocolMap, 1024) - if err != nil { - return nil, err - } - - ttl := connProtoTTL.Nanoseconds() - mapCleaner.Clean(connProtoCleaningInterval, nil, nil, func(now int64, _ netebpf.ConnTuple, val netebpf.ProtocolStackWrapper) bool { - return (now - int64(val.Updated)) > ttl - }) - - return mapCleaner, nil -} - func getAssetName(module string, debug bool) string { if debug { return fmt.Sprintf("%s-debug.o", module) diff --git a/pkg/network/usm/ebpf_ssl.go b/pkg/network/usm/ebpf_ssl.go index d7dcbdafeedea..aed0ffac49216 100644 --- a/pkg/network/usm/ebpf_ssl.go +++ b/pkg/network/usm/ebpf_ssl.go @@ -592,6 +592,10 @@ func isBuildKit(procRoot string, pid uint32) bool { } } } + if err != nil { + return false + } + defer file.Close() buf := taskCommLenBufferPool.Get() defer taskCommLenBufferPool.Put(buf) diff --git a/pkg/network/usm/kafka_monitor_test.go b/pkg/network/usm/kafka_monitor_test.go index 39533158c152a..703be195d3b37 100644 --- a/pkg/network/usm/kafka_monitor_test.go +++ b/pkg/network/usm/kafka_monitor_test.go @@ -34,6 +34,7 @@ import ( ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" "github.com/DataDog/datadog-agent/pkg/network" "github.com/DataDog/datadog-agent/pkg/network/config" "github.com/DataDog/datadog-agent/pkg/network/protocols" @@ -122,7 +123,11 @@ func TestKafkaProtocolParsing(t *testing.T) { serverHost := "127.0.0.1" require.NoError(t, kafka.RunServer(t, serverHost, kafkaPort)) - ebpftest.TestBuildModes(t, []ebpftest.BuildMode{ebpftest.Prebuilt, ebpftest.RuntimeCompiled, ebpftest.CORE}, "", func(t *testing.T) { + modes := []ebpftest.BuildMode{ebpftest.RuntimeCompiled, ebpftest.CORE} + if !prebuilt.IsDeprecated() { + modes = append(modes, ebpftest.Prebuilt) + } + ebpftest.TestBuildModes(t, modes, "", func(t *testing.T) { suite.Run(t, new(KafkaProtocolParsingSuite)) }) } @@ -1681,7 +1686,11 @@ func newKafkaMonitor(t *testing.T, cfg *config.Config) *Monitor { func TestLoadKafkaBinary(t *testing.T) { skipTestIfKernelNotSupported(t) - ebpftest.TestBuildModes(t, []ebpftest.BuildMode{ebpftest.Prebuilt, ebpftest.RuntimeCompiled, ebpftest.CORE}, "", func(t *testing.T) { + modes := []ebpftest.BuildMode{ebpftest.RuntimeCompiled, ebpftest.CORE} + if !prebuilt.IsDeprecated() { + modes = append(modes, ebpftest.Prebuilt) + } + ebpftest.TestBuildModes(t, modes, "", func(t *testing.T) { t.Run("debug", func(t *testing.T) { loadKafkaBinary(t, true) }) diff --git a/pkg/network/usm/monitor_test.go b/pkg/network/usm/monitor_test.go index bbbe03202b32e..595ce9593ac6f 100644 --- a/pkg/network/usm/monitor_test.go +++ b/pkg/network/usm/monitor_test.go @@ -31,6 +31,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" "github.com/DataDog/datadog-agent/pkg/network/config" netlink "github.com/DataDog/datadog-agent/pkg/network/netlink/testutil" "github.com/DataDog/datadog-agent/pkg/network/protocols" @@ -100,7 +101,11 @@ func TestHTTP(t *testing.T) { if kv < usmconfig.MinimumKernelVersion { t.Skipf("USM is not supported on %v", kv) } - ebpftest.TestBuildModes(t, []ebpftest.BuildMode{ebpftest.Prebuilt, ebpftest.RuntimeCompiled, ebpftest.CORE}, "", func(t *testing.T) { + modes := []ebpftest.BuildMode{ebpftest.RuntimeCompiled, ebpftest.CORE} + if !prebuilt.IsDeprecated() { + modes = append(modes, ebpftest.Prebuilt) + } + ebpftest.TestBuildModes(t, modes, "", func(t *testing.T) { suite.Run(t, new(HTTPTestSuite)) }) } diff --git a/pkg/network/usm/monitor_tls_test.go b/pkg/network/usm/monitor_tls_test.go index 9a73386d17d8f..90966c91c2cdc 100644 --- a/pkg/network/usm/monitor_tls_test.go +++ b/pkg/network/usm/monitor_tls_test.go @@ -30,6 +30,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" eventmonitortestutil "github.com/DataDog/datadog-agent/pkg/eventmonitor/testutil" "github.com/DataDog/datadog-agent/pkg/network" "github.com/DataDog/datadog-agent/pkg/network/config" @@ -51,7 +52,11 @@ type tlsSuite struct { } func TestTLSSuite(t *testing.T) { - ebpftest.TestBuildModes(t, []ebpftest.BuildMode{ebpftest.Prebuilt, ebpftest.RuntimeCompiled, ebpftest.CORE}, "", func(t *testing.T) { + modes := []ebpftest.BuildMode{ebpftest.RuntimeCompiled, ebpftest.CORE} + if !prebuilt.IsDeprecated() { + modes = append(modes, ebpftest.Prebuilt) + } + ebpftest.TestBuildModes(t, modes, "", func(t *testing.T) { if !usmconfig.TLSSupported(config.New()) { t.Skip("TLS not supported for this setup") } diff --git a/pkg/network/usm/nodejs.go b/pkg/network/usm/nodejs.go index 4b5996830c2b4..053bd34ef66d0 100644 --- a/pkg/network/usm/nodejs.go +++ b/pkg/network/usm/nodejs.go @@ -15,6 +15,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/ebpf/uprobes" "github.com/DataDog/datadog-agent/pkg/network/config" + "github.com/DataDog/datadog-agent/pkg/process/monitor" "github.com/DataDog/datadog-agent/pkg/util/kernel" "github.com/DataDog/datadog-agent/pkg/util/log" ) @@ -107,7 +108,8 @@ var ( // nodeJSMonitor essentially scans for Node processes and attaches SSL uprobes // to them. type nodeJSMonitor struct { - attacher *uprobes.UprobeAttacher + attacher *uprobes.UprobeAttacher + processMonitor *monitor.ProcessMonitor } func newNodeJSMonitor(c *config.Config, mgr *manager.Manager) (*nodeJSMonitor, error) { @@ -127,13 +129,15 @@ func newNodeJSMonitor(c *config.Config, mgr *manager.Manager) (*nodeJSMonitor, e EnablePeriodicScanNewProcesses: true, } - attacher, err := uprobes.NewUprobeAttacher(nodeJsAttacherName, attachCfg, mgr, uprobes.NopOnAttachCallback, &uprobes.NativeBinaryInspector{}) + procMon := monitor.GetProcessMonitor() + attacher, err := uprobes.NewUprobeAttacher(nodeJsAttacherName, attachCfg, mgr, uprobes.NopOnAttachCallback, &uprobes.NativeBinaryInspector{}, procMon) if err != nil { return nil, fmt.Errorf("cannot create uprobe attacher: %w", err) } return &nodeJSMonitor{ - attacher: attacher, + attacher: attacher, + processMonitor: procMon, }, nil } @@ -153,6 +157,7 @@ func (m *nodeJSMonitor) Stop() { return } + m.processMonitor.Stop() m.attacher.Stop() } diff --git a/pkg/network/usm/postgres_monitor_test.go b/pkg/network/usm/postgres_monitor_test.go index 1016cb10601d0..4cf4bfd185053 100644 --- a/pkg/network/usm/postgres_monitor_test.go +++ b/pkg/network/usm/postgres_monitor_test.go @@ -22,6 +22,7 @@ import ( "github.com/stretchr/testify/suite" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" "github.com/DataDog/datadog-agent/pkg/network" "github.com/DataDog/datadog-agent/pkg/network/config" "github.com/DataDog/datadog-agent/pkg/network/protocols" @@ -103,7 +104,11 @@ type postgresProtocolParsingSuite struct { func TestPostgresMonitoring(t *testing.T) { skipTestIfKernelNotSupported(t) - ebpftest.TestBuildModes(t, []ebpftest.BuildMode{ebpftest.Prebuilt, ebpftest.RuntimeCompiled, ebpftest.CORE}, "", func(t *testing.T) { + modes := []ebpftest.BuildMode{ebpftest.RuntimeCompiled, ebpftest.CORE} + if !prebuilt.IsDeprecated() { + modes = append(modes, ebpftest.Prebuilt) + } + ebpftest.TestBuildModes(t, modes, "", func(t *testing.T) { suite.Run(t, new(postgresProtocolParsingSuite)) }) } diff --git a/pkg/network/usm/sharedlibraries/ebpf.go b/pkg/network/usm/sharedlibraries/ebpf.go index 4b32417132add..98d7c281a6be0 100644 --- a/pkg/network/usm/sharedlibraries/ebpf.go +++ b/pkg/network/usm/sharedlibraries/ebpf.go @@ -108,7 +108,7 @@ func (e *EbpfProgram) Init() error { return nil } - if !e.cfg.AllowRuntimeCompiledFallback && !e.cfg.AllowPrecompiledFallback { + if !e.cfg.AllowRuntimeCompiledFallback && !e.cfg.AllowPrebuiltFallback { return fmt.Errorf("co-re load failed: %w", err) } log.Warnf("co-re load failed. attempting fallback: %s", err) @@ -120,7 +120,7 @@ func (e *EbpfProgram) Init() error { return nil } - if !e.cfg.AllowPrecompiledFallback { + if !e.cfg.AllowPrebuiltFallback { return fmt.Errorf("runtime compilation failed: %w", err) } log.Warnf("runtime compilation failed: attempting fallback: %s", err) diff --git a/pkg/network/usm/sharedlibraries/watcher_test.go b/pkg/network/usm/sharedlibraries/watcher_test.go index 079ad0b996969..72871f57dfe20 100644 --- a/pkg/network/usm/sharedlibraries/watcher_test.go +++ b/pkg/network/usm/sharedlibraries/watcher_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/require" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" eventmonitortestutil "github.com/DataDog/datadog-agent/pkg/eventmonitor/testutil" "github.com/DataDog/datadog-agent/pkg/network/config" usmconfig "github.com/DataDog/datadog-agent/pkg/network/usm/config" @@ -55,7 +56,12 @@ func TestSharedLibrary(t *testing.T) { t.Skip("shared library tracing not supported for this platform") } - ebpftest.TestBuildModes(t, []ebpftest.BuildMode{ebpftest.Prebuilt, ebpftest.RuntimeCompiled, ebpftest.CORE}, "", func(t *testing.T) { + modes := []ebpftest.BuildMode{ebpftest.RuntimeCompiled, ebpftest.CORE} + if !prebuilt.IsDeprecated() { + modes = append(modes, ebpftest.Prebuilt) + } + + ebpftest.TestBuildModes(t, modes, "", func(t *testing.T) { t.Run("netlink", func(t *testing.T) { launchProcessMonitor(t, false) suite.Run(t, new(SharedLibrarySuite)) diff --git a/pkg/network/usm/usm_grpc_monitor_test.go b/pkg/network/usm/usm_grpc_monitor_test.go index c56d2ce5ef5a4..d153a50298a17 100644 --- a/pkg/network/usm/usm_grpc_monitor_test.go +++ b/pkg/network/usm/usm_grpc_monitor_test.go @@ -20,6 +20,7 @@ import ( "google.golang.org/grpc/metadata" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" "github.com/DataDog/datadog-agent/pkg/network/config" "github.com/DataDog/datadog-agent/pkg/network/protocols" "github.com/DataDog/datadog-agent/pkg/network/protocols/http" @@ -56,7 +57,12 @@ func TestGRPCScenarios(t *testing.T) { t.Skipf("HTTP2 monitoring can not run on kernel before %v", http2.MinimumKernelVersion) } - ebpftest.TestBuildModes(t, []ebpftest.BuildMode{ebpftest.Prebuilt, ebpftest.RuntimeCompiled, ebpftest.CORE}, "", func(t *testing.T) { + modes := []ebpftest.BuildMode{ebpftest.RuntimeCompiled, ebpftest.CORE} + if !prebuilt.IsDeprecated() { + modes = append(modes, ebpftest.Prebuilt) + } + + ebpftest.TestBuildModes(t, modes, "", func(t *testing.T) { for _, tc := range []struct { name string isTLS bool diff --git a/pkg/network/usm/usm_http2_monitor_test.go b/pkg/network/usm/usm_http2_monitor_test.go index 8a56e0df1bb9f..4a3fba2c48c99 100644 --- a/pkg/network/usm/usm_http2_monitor_test.go +++ b/pkg/network/usm/usm_http2_monitor_test.go @@ -35,6 +35,7 @@ import ( ddebpf "github.com/DataDog/datadog-agent/pkg/ebpf" "github.com/DataDog/datadog-agent/pkg/ebpf/ebpftest" + "github.com/DataDog/datadog-agent/pkg/ebpf/prebuilt" "github.com/DataDog/datadog-agent/pkg/network" "github.com/DataDog/datadog-agent/pkg/network/config" "github.com/DataDog/datadog-agent/pkg/network/protocols" @@ -93,7 +94,12 @@ func skipIfKernelNotSupported(t *testing.T) { func TestHTTP2Scenarios(t *testing.T) { skipIfKernelNotSupported(t) - ebpftest.TestBuildModes(t, []ebpftest.BuildMode{ebpftest.Prebuilt, ebpftest.RuntimeCompiled, ebpftest.CORE}, "", func(t *testing.T) { + modes := []ebpftest.BuildMode{ebpftest.RuntimeCompiled, ebpftest.CORE} + if !prebuilt.IsDeprecated() { + modes = append(modes, ebpftest.Prebuilt) + } + + ebpftest.TestBuildModes(t, modes, "", func(t *testing.T) { for _, tc := range []struct { name string isTLS bool diff --git a/pkg/network/usm/utils/debugger.go b/pkg/network/usm/utils/debugger.go index 7d3c1d2f00fde..ce24d8d1ba3ac 100644 --- a/pkg/network/usm/utils/debugger.go +++ b/pkg/network/usm/utils/debugger.go @@ -60,6 +60,11 @@ func BlockedPathIDEndpoint(w http.ResponseWriter, _ *http.Request) { otherutils.WriteAsJSON(w, debugger.GetAllBlockedPathIDs()) } +// ClearBlockedEndpoint clears the lists of blocked paths. +func ClearBlockedEndpoint(_ http.ResponseWriter, _ *http.Request) { + debugger.ClearBlocked() +} + var debugger *tlsDebugger type tlsDebugger struct { @@ -162,6 +167,18 @@ func (d *tlsDebugger) GetBlockedPathIDs(programType string) []PathIdentifier { return nil } +// ClearBlocked clears the list of blocked paths for all registries. +func (d *tlsDebugger) ClearBlocked() { + d.mux.Lock() + defer d.mux.Unlock() + + for _, registry := range d.registries { + registry.m.Lock() + registry.blocklistByID.Purge() + registry.m.Unlock() + } +} + // GetBlockedPathIDsWithSamplePath returns a list of PathIdentifiers with a matching sample path blocked in the // registry for the specified program type. func (d *tlsDebugger) GetBlockedPathIDsWithSamplePath(programType string) []PathIdentifierWithSamplePath { diff --git a/pkg/network/usm/utils/debugger_windows.go b/pkg/network/usm/utils/debugger_windows.go index 4cf1b36757ab5..93a4b0c8d8587 100644 --- a/pkg/network/usm/utils/debugger_windows.go +++ b/pkg/network/usm/utils/debugger_windows.go @@ -20,6 +20,11 @@ func BlockedPathIDEndpoint(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(404) } +// ClearBlockedEndpoint is not supported on Windows +func ClearBlockedEndpoint(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(404) +} + // AttachPIDEndpoint is not supported on Windows func AttachPIDEndpoint(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(404) diff --git a/pkg/network/usm/utils/file_registry_test.go b/pkg/network/usm/utils/file_registry_test.go index d63515a46049f..376590a59958d 100644 --- a/pkg/network/usm/utils/file_registry_test.go +++ b/pkg/network/usm/utils/file_registry_test.go @@ -238,6 +238,10 @@ func TestFailedRegistration(t *testing.T) { // Assert that the number of callback executions hasn't changed for this pathID // This is because we have block-listed this file assert.Equal(t, 1, registerRecorder.CallsForPathID(pathID)) + + assert.Contains(t, debugger.GetBlockedPathIDs(""), pathID) + debugger.ClearBlocked() + assert.Empty(t, debugger.GetBlockedPathIDs("")) } func TestShortLivedProcess(t *testing.T) { @@ -398,5 +402,6 @@ func createSymlink(t *testing.T, old, new string) { func newFileRegistry() *FileRegistry { // Ensure that tests relying on telemetry data will always have a clean slate telemetry.Clear() + ResetDebugger() return NewFileRegistry("") } diff --git a/pkg/network/usm_connection_keys_test.go b/pkg/network/usm_connection_keys_test.go index 0a40ea948cd7d..b88a0d6d26926 100644 --- a/pkg/network/usm_connection_keys_test.go +++ b/pkg/network/usm_connection_keys_test.go @@ -10,19 +10,20 @@ package network import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/pkg/network/types" "github.com/DataDog/datadog-agent/pkg/process/util" - "github.com/stretchr/testify/assert" ) func TestWithKey(t *testing.T) { t.Run("without NAT", func(t *testing.T) { - c := ConnectionStats{ + c := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("10.1.1.1"), Dest: util.AddressFromString("10.2.2.2"), SPort: 60000, DPort: 80, - } + }} shouldGenerateKeys(t, c, types.NewConnectionKey(c.Source, c.Dest, c.SPort, c.DPort), @@ -31,11 +32,12 @@ func TestWithKey(t *testing.T) { }) t.Run("with NAT", func(t *testing.T) { - c := ConnectionStats{ + c := ConnectionStats{ConnectionTuple: ConnectionTuple{ Source: util.AddressFromString("10.1.1.1"), Dest: util.AddressFromString("10.2.2.2"), SPort: 60000, DPort: 80, + }, IPTranslation: &IPTranslation{ ReplSrcIP: util.AddressFromString("3.3.3.3"), ReplDstIP: util.AddressFromString("4.4.4.4"), diff --git a/pkg/networkpath/traceroute/runner.go b/pkg/networkpath/traceroute/runner.go index d75738e6c5260..316f2daa5a852 100644 --- a/pkg/networkpath/traceroute/runner.go +++ b/pkg/networkpath/traceroute/runner.go @@ -235,10 +235,9 @@ func (r *Runner) processTCPResults(res *tcp.Results, hname string, destinationHo NetworkID: r.networkID, }, Destination: payload.NetworkPathDestination{ - Hostname: destinationHost, - Port: destinationPort, - IPAddress: destinationIP.String(), - ReverseDNSHostname: getReverseDNSForIP(destinationIP), + Hostname: destinationHost, + Port: destinationPort, + IPAddress: destinationIP.String(), }, } @@ -267,7 +266,6 @@ func (r *Runner) processTCPResults(res *tcp.Results, hname string, destinationHo if !hop.IP.Equal(net.IP{}) { isReachable = true hopname = hop.IP.String() - hostname = getHostname(hop.IP.String()) } npHop := payload.NetworkPathHop{ @@ -299,10 +297,9 @@ func (r *Runner) processUDPResults(res *results.Results, hname string, destinati NetworkID: r.networkID, }, Destination: payload.NetworkPathDestination{ - Hostname: destinationHost, - Port: destinationPort, - IPAddress: destinationIP.String(), - ReverseDNSHostname: getReverseDNSForIP(destinationIP), + Hostname: destinationHost, + Port: destinationPort, + IPAddress: destinationIP.String(), }, } @@ -381,7 +378,6 @@ func (r *Runner) processUDPResults(res *results.Results, hname string, destinati hop := payload.NetworkPathHop{ TTL: idx, IPAddress: ip, - Hostname: getHostname(cur.node), RTT: durationMs, Reachable: isReachable, } diff --git a/pkg/networkpath/traceroute/utils.go b/pkg/networkpath/traceroute/utils.go index de67843a8330a..760c3a03acc38 100644 --- a/pkg/networkpath/traceroute/utils.go +++ b/pkg/networkpath/traceroute/utils.go @@ -15,14 +15,16 @@ import ( var lookupAddrFn = net.DefaultResolver.LookupAddr -func getReverseDNSForIP(destIP net.IP) string { +// GetReverseDNSForIP returns the reverse DNS for the given IP address as a net.IP. +func GetReverseDNSForIP(destIP net.IP) string { if destIP == nil { return "" } - return getHostname(destIP.String()) + return GetHostname(destIP.String()) } -func getHostname(ipAddr string) string { +// GetHostname returns the hostname for the given IP address as a string. +func GetHostname(ipAddr string) string { currHost := "" ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() diff --git a/pkg/networkpath/traceroute/utils_test.go b/pkg/networkpath/traceroute/utils_test.go index a7f42d875ee7c..df128d299c531 100644 --- a/pkg/networkpath/traceroute/utils_test.go +++ b/pkg/networkpath/traceroute/utils_test.go @@ -14,15 +14,15 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_getReverseDnsForIP(t *testing.T) { +func Test_GetReverseDnsForIP(t *testing.T) { t.Run("reverse dns lookup successful", func(t *testing.T) { lookupAddrFn = func(_ context.Context, _ string) ([]string, error) { return []string{"domain-a.com", "domain-b.com"}, nil } defer func() { lookupAddrFn = net.DefaultResolver.LookupAddr }() - assert.Equal(t, "domain-a.com", getReverseDNSForIP(net.ParseIP("1.2.3.4"))) - assert.Equal(t, "", getReverseDNSForIP(nil)) + assert.Equal(t, "domain-a.com", GetReverseDNSForIP(net.ParseIP("1.2.3.4"))) + assert.Equal(t, "", GetReverseDNSForIP(nil)) }) t.Run("reverse dns lookup failure", func(t *testing.T) { lookupAddrFn = func(_ context.Context, _ string) ([]string, error) { @@ -30,8 +30,8 @@ func Test_getReverseDnsForIP(t *testing.T) { } defer func() { lookupAddrFn = net.DefaultResolver.LookupAddr }() - assert.Equal(t, "1.2.3.4", getReverseDNSForIP(net.ParseIP("1.2.3.4"))) - assert.Equal(t, "", getReverseDNSForIP(nil)) + assert.Equal(t, "1.2.3.4", GetReverseDNSForIP(net.ParseIP("1.2.3.4"))) + assert.Equal(t, "", GetReverseDNSForIP(nil)) }) } @@ -42,7 +42,7 @@ func Test_getHostname(t *testing.T) { } defer func() { lookupAddrFn = net.DefaultResolver.LookupAddr }() - assert.Equal(t, "domain-a.com", getHostname("1.2.3.4")) + assert.Equal(t, "domain-a.com", GetHostname("1.2.3.4")) }) t.Run("reverse dns lookup failure", func(t *testing.T) { lookupAddrFn = func(_ context.Context, _ string) ([]string, error) { @@ -50,6 +50,6 @@ func Test_getHostname(t *testing.T) { } defer func() { lookupAddrFn = net.DefaultResolver.LookupAddr }() - assert.Equal(t, "1.2.3.4", getHostname("1.2.3.4")) + assert.Equal(t, "1.2.3.4", GetHostname("1.2.3.4")) }) } diff --git a/pkg/obfuscate/ip_address.go b/pkg/obfuscate/ip_address.go index 7639453bd958b..fa3c4a21c41a3 100644 --- a/pkg/obfuscate/ip_address.go +++ b/pkg/obfuscate/ip_address.go @@ -6,6 +6,7 @@ package obfuscate import ( + "fmt" "net" "net/netip" "regexp" @@ -30,7 +31,8 @@ func QuantizePeerIPAddresses(raw string) string { return strings.Join(uniq, ",") } -var protocolRegex = regexp.MustCompile(`((?:dnspoll|ftp|file|http|https):/{2,3}).*`) +var schemes = []string{"dnspoll", "ftp", "file", "http", "https"} +var protocolRegex = regexp.MustCompile(fmt.Sprintf(`((?:%s):/{2,3}).*`, strings.Join(schemes, "|"))) var allowedIPAddresses = map[string]bool{ // localhost @@ -47,10 +49,22 @@ func splitPrefix(raw string) (prefix, after string) { if after, ok := strings.CutPrefix(raw, "ip-"); ok { // AWS EC2 hostnames e.g. ip-10-123-4-567.ec2.internal return "ip-", after } - subMatches := protocolRegex.FindStringSubmatch(raw) - if len(subMatches) >= 2 { - prefix = subMatches[1] + + isHintFound := false + for _, hint := range schemes { + if strings.Contains(raw, hint) { + isHintFound = true + break + } + } + + if isHintFound { + subMatches := protocolRegex.FindStringSubmatch(raw) + if len(subMatches) >= 2 { + prefix = subMatches[1] + } } + return prefix, raw[len(prefix):] } diff --git a/pkg/obfuscate/ip_address_test.go b/pkg/obfuscate/ip_address_test.go index b037f9c37183d..5e01f5ef448e2 100644 --- a/pkg/obfuscate/ip_address_test.go +++ b/pkg/obfuscate/ip_address_test.go @@ -61,3 +61,23 @@ func TestQuantizePeerIpAddresses(t *testing.T) { }) } } + +func BenchmarkSplitPrefix(b *testing.B) { + b.Run("matching", func(b *testing.B) { + for i := 0; i < b.N; i++ { + prefix, after := splitPrefix("dnspoll:///abc.cluster.local:50051") + if prefix != "dnspoll:///" || after != "abc.cluster.local:50051" { + b.Error("unexpected result") + } + } + }) + + b.Run("not matching", func(b *testing.B) { + for i := 0; i < b.N; i++ { + prefix, after := splitPrefix("2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF") + if prefix != "" || after != "2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF" { + b.Error("unexpected result") + } + } + }) +} diff --git a/pkg/process/checks/container.go b/pkg/process/checks/container.go index 8d9c8330ebd47..533c6f55a050f 100644 --- a/pkg/process/checks/container.go +++ b/pkg/process/checks/container.go @@ -53,11 +53,14 @@ type ContainerCheck struct { // Init initializes a ContainerCheck instance. func (c *ContainerCheck) Init(syscfg *SysProbeConfig, info *HostInfo, _ bool) error { - c.containerProvider = proccontainers.GetSharedContainerProvider(c.wmeta) + sharedContainerProvider, err := proccontainers.GetSharedContainerProvider() + if err != nil { + return err + } + c.containerProvider = sharedContainerProvider c.hostInfo = info var tu net.SysProbeUtil - var err error if syscfg.NetworkTracerModuleEnabled { // Calling the remote tracer will cause it to initialize and check connectivity tu, err = net.GetRemoteSystemProbeUtil(syscfg.SystemProbeAddress) diff --git a/pkg/process/checks/container_rt.go b/pkg/process/checks/container_rt.go index 452323de8e7a5..3050d32275213 100644 --- a/pkg/process/checks/container_rt.go +++ b/pkg/process/checks/container_rt.go @@ -44,7 +44,11 @@ type RTContainerCheck struct { func (r *RTContainerCheck) Init(_ *SysProbeConfig, hostInfo *HostInfo, _ bool) error { r.maxBatchSize = getMaxBatchSize(r.config) r.hostInfo = hostInfo - r.containerProvider = proccontainers.GetSharedContainerProvider(r.wmeta) + sharedContainerProvider, err := proccontainers.GetSharedContainerProvider() + if err != nil { + return err + } + r.containerProvider = sharedContainerProvider return nil } diff --git a/pkg/process/checks/net.go b/pkg/process/checks/net.go index 816ae56a42134..9c87179f85508 100644 --- a/pkg/process/checks/net.go +++ b/pkg/process/checks/net.go @@ -122,7 +122,11 @@ func (c *ConnectionsCheck) Init(syscfg *SysProbeConfig, hostInfo *HostInfo, _ bo c.processData.Register(c.serviceExtractor) // LocalResolver is a singleton LocalResolver - c.localresolver = resolver.NewLocalResolver(proccontainers.GetSharedContainerProvider(c.wmeta), clock.New(), maxResolverAddrCacheSize, maxResolverPidCacheSize) + sharedContainerProvider, err := proccontainers.GetSharedContainerProvider() + if err != nil { + return err + } + c.localresolver = resolver.NewLocalResolver(sharedContainerProvider, clock.New(), maxResolverAddrCacheSize, maxResolverPidCacheSize) c.localresolver.Run() return nil diff --git a/pkg/process/checks/process.go b/pkg/process/checks/process.go index 05a7ac5c72d28..f1837d183e540 100644 --- a/pkg/process/checks/process.go +++ b/pkg/process/checks/process.go @@ -132,12 +132,16 @@ func (p *ProcessCheck) Init(syscfg *SysProbeConfig, info *HostInfo, oneShot bool p.probe = newProcessProbe(p.config, procutil.WithPermission(syscfg.ProcessModuleEnabled), procutil.WithIgnoreZombieProcesses(p.config.GetBool(configIgnoreZombies))) - p.containerProvider = proccontainers.GetSharedContainerProvider(p.wmeta) + sharedContainerProvider, err := proccontainers.GetSharedContainerProvider() + if err != nil { + return err + } + p.containerProvider = sharedContainerProvider p.notInitializedLogLimit = log.NewLogLimit(1, time.Minute*10) var tu net.SysProbeUtil - var err error + if syscfg.NetworkTracerModuleEnabled { // Calling the remote tracer will cause it to initialize and check connectivity tu, err = net.GetRemoteSystemProbeUtil(syscfg.SystemProbeAddress) diff --git a/pkg/process/checks/process_test.go b/pkg/process/checks/process_test.go index 4512db04f03de..b54f53b1ff3e2 100644 --- a/pkg/process/checks/process_test.go +++ b/pkg/process/checks/process_test.go @@ -87,12 +87,11 @@ func mockContainerProvider(t *testing.T) proccontainers.ContainerProvider { )) fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() // Finally, container provider filter, err := containers.GetPauseContainerFilter() assert.NoError(t, err) - return proccontainers.NewContainerProvider(metricsProvider, metadataProvider, filter) + return proccontainers.NewContainerProvider(metricsProvider, metadataProvider, filter, fakeTagger) } func TestProcessCheckFirstRun(t *testing.T) { diff --git a/pkg/process/events/consumer/events_consumer.go b/pkg/process/events/consumer/events_consumer.go index 732e18b11c3ff..3901ee202676d 100644 --- a/pkg/process/events/consumer/events_consumer.go +++ b/pkg/process/events/consumer/events_consumer.go @@ -47,7 +47,7 @@ func NewProcessConsumer(evm *eventmonitor.EventMonitor) (*ProcessConsumer, error api.RegisterEventMonitoringModuleServer(evm.GRPCServer, p) - if err := evm.AddEventConsumer(p); err != nil { + if err := evm.AddEventConsumerHandler(p); err != nil { return nil, err } diff --git a/pkg/process/metadata/workloadmeta/collector/process.go b/pkg/process/metadata/workloadmeta/collector/process.go index bc9d9ea14ea0c..dfaa794ad3b08 100644 --- a/pkg/process/metadata/workloadmeta/collector/process.go +++ b/pkg/process/metadata/workloadmeta/collector/process.go @@ -70,7 +70,13 @@ func (c *Collector) Start(ctx context.Context, store workloadmeta.Component) err ) if c.containerProvider == nil { - c.containerProvider = proccontainers.GetSharedContainerProvider(store) + sharedContainerProvider, err := proccontainers.GetSharedContainerProvider() + + if err != nil { + return err + } + + c.containerProvider = sharedContainerProvider } go c.run(ctx, c.containerProvider, collectionTicker) diff --git a/pkg/process/monitor/process_monitor.go b/pkg/process/monitor/process_monitor.go index 498d54751eab8..1b9e30eb1ec84 100644 --- a/pkg/process/monitor/process_monitor.go +++ b/pkg/process/monitor/process_monitor.go @@ -30,7 +30,7 @@ const ( // The size of the process events queue of netlink. processMonitorEventQueueSize = 2048 // The size of the callbacks queue for pending tasks. - pendingCallbacksQueueSize = 1000 + pendingCallbacksQueueSize = 5000 ) var ( @@ -131,7 +131,7 @@ type ProcessMonitor struct { } // ProcessCallback is a callback function that is called on a given pid that represents a new process. -type ProcessCallback func(pid uint32) +type ProcessCallback = func(pid uint32) // GetProcessMonitor create a monitor (only once) that register to netlink process events. // @@ -526,13 +526,13 @@ type EventConsumer struct{} // NewProcessMonitorEventConsumer returns a new process monitor event consumer func NewProcessMonitorEventConsumer(em *eventmonitor.EventMonitor) (*EventConsumer, error) { consumer := &EventConsumer{} - err := em.AddEventConsumer(consumer) + err := em.AddEventConsumerHandler(consumer) return consumer, err } // ChanSize returns the channel size used by this consumer func (ec *EventConsumer) ChanSize() int { - return 100 + return 500 } // ID returns the ID of this consumer diff --git a/pkg/process/net/common_linux.go b/pkg/process/net/common_linux.go index 5f7e4365fe3fb..330010c6bcfb7 100644 --- a/pkg/process/net/common_linux.go +++ b/pkg/process/net/common_linux.go @@ -10,6 +10,7 @@ package net import ( "context" "fmt" + "io" "net" "net/http" "os" @@ -32,6 +33,7 @@ const ( telemetryURL = "http://unix/telemetry" conntrackCachedURL = "http://unix/" + string(sysconfig.NetworkTracerModule) + "/debug/conntrack/cached" conntrackHostURL = "http://unix/" + string(sysconfig.NetworkTracerModule) + "/debug/conntrack/host" + ebpfBTFLoaderURL = "http://unix/debug/ebpf_btf_loader_info" netType = "unix" ) @@ -83,3 +85,28 @@ func newSystemProbe(path string) *RemoteSysProbeUtil { }, } } + +// GetBTFLoaderInfo queries ebpf_btf_loader_info to get information about where btf files came from +func (r *RemoteSysProbeUtil) GetBTFLoaderInfo() ([]byte, error) { + req, err := http.NewRequest(http.MethodGet, ebpfBTFLoaderURL, nil) + if err != nil { + return nil, err + } + + resp, err := r.httpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + data, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf(`GetEbpfBtfInfo got non-success status code: path %s, url: %s, status_code: %d, response: "%s"`, r.path, req.URL, resp.StatusCode, data) + } + + return data, nil +} diff --git a/pkg/process/net/common_unsupported.go b/pkg/process/net/common_unsupported.go index 7604578d4b9cd..49bdc772284bb 100644 --- a/pkg/process/net/common_unsupported.go +++ b/pkg/process/net/common_unsupported.go @@ -89,6 +89,9 @@ func (r *RemoteSysProbeUtil) GetConnTrackCached() ([]byte, error) { return nil, // GetConnTrackHost is not supported func (r *RemoteSysProbeUtil) GetConnTrackHost() ([]byte, error) { return nil, ErrNotImplemented } +// GetBTFLoaderInfo is not supported +func (r *RemoteSysProbeUtil) GetBTFLoaderInfo() ([]byte, error) { return nil, ErrNotImplemented } + func (r *RemoteSysProbeUtil) GetDiscoveryServices() (*discoverymodel.ServicesResponse, error) { return nil, ErrNotImplemented } diff --git a/pkg/process/net/common_windows.go b/pkg/process/net/common_windows.go index afa0073ea9486..ccf70d591b1ac 100644 --- a/pkg/process/net/common_windows.go +++ b/pkg/process/net/common_windows.go @@ -9,6 +9,7 @@ package net import ( "context" + "errors" "fmt" "net" "net/http" @@ -103,3 +104,8 @@ func newSystemProbe(path string) *RemoteSysProbeUtil { }, } } + +// GetBTFLoaderInfo is not implemented on windows +func (r *RemoteSysProbeUtil) GetBTFLoaderInfo() ([]byte, error) { + return nil, errors.New("GetBTFLoaderInfo is not supported on windows") +} diff --git a/pkg/process/net/mocks/sys_probe_util.go b/pkg/process/net/mocks/sys_probe_util.go index 413f115e47169..d0a26d64392b7 100644 --- a/pkg/process/net/mocks/sys_probe_util.go +++ b/pkg/process/net/mocks/sys_probe_util.go @@ -88,6 +88,63 @@ func (_c *SysProbeUtil_DetectLanguage_Call) RunAndReturn(run func([]int32) ([]la return _c } +// GetBTFLoaderInfo provides a mock function with given fields: +func (_m *SysProbeUtil) GetBTFLoaderInfo() ([]byte, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetBTFLoaderInfo") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func() ([]byte, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() []byte); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SysProbeUtil_GetBTFLoaderInfo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBTFLoaderInfo' +type SysProbeUtil_GetBTFLoaderInfo_Call struct { + *mock.Call +} + +// GetBTFLoaderInfo is a helper method to define mock.On call +func (_e *SysProbeUtil_Expecter) GetBTFLoaderInfo() *SysProbeUtil_GetBTFLoaderInfo_Call { + return &SysProbeUtil_GetBTFLoaderInfo_Call{Call: _e.mock.On("GetBTFLoaderInfo")} +} + +func (_c *SysProbeUtil_GetBTFLoaderInfo_Call) Run(run func()) *SysProbeUtil_GetBTFLoaderInfo_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *SysProbeUtil_GetBTFLoaderInfo_Call) Return(_a0 []byte, _a1 error) *SysProbeUtil_GetBTFLoaderInfo_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SysProbeUtil_GetBTFLoaderInfo_Call) RunAndReturn(run func() ([]byte, error)) *SysProbeUtil_GetBTFLoaderInfo_Call { + _c.Call.Return(run) + return _c +} + // GetCheck provides a mock function with given fields: module func (_m *SysProbeUtil) GetCheck(module types.ModuleName) (interface{}, error) { ret := _m.Called(module) diff --git a/pkg/process/net/shared.go b/pkg/process/net/shared.go index 34a3dcf5e4b85..3d6bd59f892fc 100644 --- a/pkg/process/net/shared.go +++ b/pkg/process/net/shared.go @@ -30,6 +30,7 @@ type SysProbeUtil interface { GetTelemetry() ([]byte, error) GetConnTrackCached() ([]byte, error) GetConnTrackHost() ([]byte, error) + GetBTFLoaderInfo() ([]byte, error) DetectLanguage(pids []int32) ([]languagemodels.Language, error) GetPprof(path string) ([]byte, error) GetDiscoveryServices() (*discoverymodel.ServicesResponse, error) diff --git a/pkg/process/util/containers/containers.go b/pkg/process/util/containers/containers.go index 6ab0b27c1e32c..962037789758b 100644 --- a/pkg/process/util/containers/containers.go +++ b/pkg/process/util/containers/containers.go @@ -62,39 +62,49 @@ type ContainerProvider interface { GetPidToCid(cacheValidity time.Duration) map[int]string } -// GetSharedContainerProvider returns a shared ContainerProvider -func GetSharedContainerProvider(wmeta workloadmeta.Component) ContainerProvider { +// InitSharedContainerProvider init shared ContainerProvider +func InitSharedContainerProvider(wmeta workloadmeta.Component, tagger tagger.Component) ContainerProvider { initContainerProvider.Do(func() { - sharedContainerProvider = NewDefaultContainerProvider(wmeta) + sharedContainerProvider = NewDefaultContainerProvider(wmeta, tagger) }) return sharedContainerProvider } +// GetSharedContainerProvider returns a shared ContainerProvider +func GetSharedContainerProvider() (ContainerProvider, error) { + if sharedContainerProvider == nil { + return nil, log.Errorf("Shared container provider not initialized") + } + return sharedContainerProvider, nil +} + // containerProvider provides data about containers usable by process-agent type containerProvider struct { metricsProvider metrics.Provider metadataStore workloadmeta.Component filter *containers.Filter + tagger tagger.Component } // NewContainerProvider returns a ContainerProvider instance -func NewContainerProvider(provider metrics.Provider, metadataStore workloadmeta.Component, filter *containers.Filter) ContainerProvider { +func NewContainerProvider(provider metrics.Provider, metadataStore workloadmeta.Component, filter *containers.Filter, tagger tagger.Component) ContainerProvider { return &containerProvider{ metricsProvider: provider, metadataStore: metadataStore, filter: filter, + tagger: tagger, } } // NewDefaultContainerProvider returns a ContainerProvider built with default metrics provider and metadata provider -func NewDefaultContainerProvider(wmeta workloadmeta.Component) ContainerProvider { +func NewDefaultContainerProvider(wmeta workloadmeta.Component, tagger tagger.Component) ContainerProvider { containerFilter, err := containers.GetSharedMetricFilter() if err != nil { log.Warnf("Can't get container include/exclude filter, no filtering will be applied: %v", err) } // TODO(components): stop relying on globals and use injected components instead whenever possible. - return NewContainerProvider(metrics.GetProvider(optional.NewOption(wmeta)), wmeta, containerFilter) + return NewContainerProvider(metrics.GetProvider(optional.NewOption(wmeta)), wmeta, containerFilter, tagger) } // GetContainers returns containers found on the machine @@ -120,7 +130,7 @@ func (p *containerProvider) GetContainers(cacheValidity time.Duration, previousC } entityID := types.NewEntityID(types.ContainerID, container.ID) - tags, err := tagger.Tag(entityID, types.HighCardinality) + tags, err := p.tagger.Tag(entityID, types.HighCardinality) if err != nil { log.Debugf("Could not collect tags for container %q, err: %v", container.ID[:12], err) } diff --git a/pkg/process/util/containers/containers_test.go b/pkg/process/util/containers/containers_test.go index 29ace1b864c76..0de7a55879890 100644 --- a/pkg/process/util/containers/containers_test.go +++ b/pkg/process/util/containers/containers_test.go @@ -47,13 +47,12 @@ func TestGetContainers(t *testing.T) { )) fakeTagger := taggerimpl.SetupFakeTagger(t) - defer fakeTagger.ResetTagger() // Finally, container provider testTime := time.Now() filter, err := containers.GetPauseContainerFilter() assert.NoError(t, err) - containerProvider := NewContainerProvider(metricsProvider, metadataProvider, filter) + containerProvider := NewContainerProvider(metricsProvider, metadataProvider, filter, fakeTagger) // Containers: // cID1 full stats diff --git a/pkg/security/agent/client.go b/pkg/security/agent/client.go index 317cd472695c4..81e2cf630b549 100644 --- a/pkg/security/agent/client.go +++ b/pkg/security/agent/client.go @@ -32,7 +32,7 @@ type RuntimeSecurityClient struct { // SecurityModuleClientWrapper represents a security module client type SecurityModuleClientWrapper interface { DumpDiscarders() (string, error) - DumpProcessCache(withArgs bool) (string, error) + DumpProcessCache(withArgs bool, format string) (string, error) GenerateActivityDump(request *api.ActivityDumpParams) (*api.ActivityDumpMessage, error) ListActivityDumps() (*api.ActivityDumpListMessage, error) StopActivityDump(name, containerid string) (*api.ActivityDumpStopMessage, error) @@ -61,8 +61,8 @@ func (c *RuntimeSecurityClient) DumpDiscarders() (string, error) { } // DumpProcessCache sends a process cache dump request -func (c *RuntimeSecurityClient) DumpProcessCache(withArgs bool) (string, error) { - response, err := c.apiClient.DumpProcessCache(context.Background(), &api.DumpProcessCacheParams{WithArgs: withArgs}) +func (c *RuntimeSecurityClient) DumpProcessCache(withArgs bool, format string) (string, error) { + response, err := c.apiClient.DumpProcessCache(context.Background(), &api.DumpProcessCacheParams{WithArgs: withArgs, Format: format}) if err != nil { return "", err } diff --git a/pkg/security/agent/mocks/security_module_client_wrapper.go b/pkg/security/agent/mocks/security_module_client_wrapper.go index 96f7e677e55ee..7cca38514d827 100644 --- a/pkg/security/agent/mocks/security_module_client_wrapper.go +++ b/pkg/security/agent/mocks/security_module_client_wrapper.go @@ -75,9 +75,9 @@ func (_m *SecurityModuleClientWrapper) DumpNetworkNamespace(snapshotInterfaces b return r0, r1 } -// DumpProcessCache provides a mock function with given fields: withArgs -func (_m *SecurityModuleClientWrapper) DumpProcessCache(withArgs bool) (string, error) { - ret := _m.Called(withArgs) +// DumpProcessCache provides a mock function with given fields: withArgs, format +func (_m *SecurityModuleClientWrapper) DumpProcessCache(withArgs bool, format string) (string, error) { + ret := _m.Called(withArgs, format) if len(ret) == 0 { panic("no return value specified for DumpProcessCache") @@ -85,17 +85,17 @@ func (_m *SecurityModuleClientWrapper) DumpProcessCache(withArgs bool) (string, var r0 string var r1 error - if rf, ok := ret.Get(0).(func(bool) (string, error)); ok { - return rf(withArgs) + if rf, ok := ret.Get(0).(func(bool, string) (string, error)); ok { + return rf(withArgs, format) } - if rf, ok := ret.Get(0).(func(bool) string); ok { - r0 = rf(withArgs) + if rf, ok := ret.Get(0).(func(bool, string) string); ok { + r0 = rf(withArgs, format) } else { r0 = ret.Get(0).(string) } - if rf, ok := ret.Get(1).(func(bool) error); ok { - r1 = rf(withArgs) + if rf, ok := ret.Get(1).(func(bool, string) error); ok { + r1 = rf(withArgs, format) } else { r1 = ret.Error(1) } diff --git a/pkg/security/config/config.go b/pkg/security/config/config.go index 8ca5c7ef33ae8..c28f98dc7f473 100644 --- a/pkg/security/config/config.go +++ b/pkg/security/config/config.go @@ -80,6 +80,8 @@ type RuntimeSecurityConfig struct { OnDemandEnabled bool // OnDemandRateLimiterEnabled defines whether the on-demand probes rate limit getting hit disabled the on demand probes OnDemandRateLimiterEnabled bool + // ReducedProcPidCacheSize defines whether the `proc_cache` and `pid_cache` map should use reduced size + ReducedProcPidCacheSize bool // InternalMonitoringEnabled determines if the monitoring events of the agent should be sent to Datadog InternalMonitoringEnabled bool @@ -342,6 +344,7 @@ func NewRuntimeSecurityConfig() (*RuntimeSecurityConfig, error) { OnDemandEnabled: pkgconfigsetup.SystemProbe().GetBool("runtime_security_config.on_demand.enabled"), OnDemandRateLimiterEnabled: pkgconfigsetup.SystemProbe().GetBool("runtime_security_config.on_demand.rate_limiter.enabled"), + ReducedProcPidCacheSize: pkgconfigsetup.SystemProbe().GetBool("runtime_security_config.reduced_proc_pid_cache_size"), // policy & ruleset PoliciesDir: pkgconfigsetup.SystemProbe().GetString("runtime_security_config.policies.dir"), diff --git a/pkg/security/ebpf/c/include/constants/enums.h b/pkg/security/ebpf/c/include/constants/enums.h index c547f141b662f..4837192476a36 100644 --- a/pkg/security/ebpf/c/include/constants/enums.h +++ b/pkg/security/ebpf/c/include/constants/enums.h @@ -44,6 +44,7 @@ enum event_type EVENT_NET_DEVICE, EVENT_VETH_PAIR, EVENT_BIND, + EVENT_CONNECT, EVENT_UNSHARE_MNTNS, EVENT_SYSCALLS, EVENT_IMDS, diff --git a/pkg/security/ebpf/c/include/events_definition.h b/pkg/security/ebpf/c/include/events_definition.h index b7c8195c35dbe..c5e01954e45e5 100644 --- a/pkg/security/ebpf/c/include/events_definition.h +++ b/pkg/security/ebpf/c/include/events_definition.h @@ -23,6 +23,18 @@ struct bind_event_t { u16 port; }; +struct connect_event_t { + struct kevent_t event; + struct process_context_t process; + struct span_context_t span; + struct container_context_t container; + struct syscall_t syscall; + + u64 addr[2]; + u16 family; + u16 port; +}; + struct bpf_event_t { struct kevent_t event; struct process_context_t process; diff --git a/pkg/security/ebpf/c/include/helpers/exec.h b/pkg/security/ebpf/c/include/helpers/exec.h index f26ca0e0976b1..4a67cf4f011ef 100644 --- a/pkg/security/ebpf/c/include/helpers/exec.h +++ b/pkg/security/ebpf/c/include/helpers/exec.h @@ -19,7 +19,7 @@ int __attribute__((always_inline)) handle_exec_event(ctx_t *ctx, struct syscall_ // set mount_id to 0 is this is a fileless exec, meaning that the vfs type is tmpfs and that is an internal mount u32 mount_id = is_tmpfs(syscall->exec.dentry) && get_path_mount_flags(path) & MNT_INTERNAL ? 0 : get_path_mount_id(path); - syscall->exec.file.path_key.ino = get_inode_ino(inode); + syscall->exec.file.path_key.ino = inode ? get_inode_ino(inode) : get_path_ino(path); syscall->exec.file.path_key.mount_id = mount_id; syscall->exec.file.path_key.path_id = get_path_id(mount_id, 0); diff --git a/pkg/security/ebpf/c/include/helpers/filesystem.h b/pkg/security/ebpf/c/include/helpers/filesystem.h index 7f8ca08b7f489..07ca0431d7382 100644 --- a/pkg/security/ebpf/c/include/helpers/filesystem.h +++ b/pkg/security/ebpf/c/include/helpers/filesystem.h @@ -107,6 +107,17 @@ void __attribute__((always_inline)) fill_file(struct dentry *dentry, struct file bpf_probe_read(&file->metadata.uid, sizeof(file->metadata.uid), &d_inode->i_uid); bpf_probe_read(&file->metadata.gid, sizeof(file->metadata.gid), &d_inode->i_gid); + u64 inode_ctime_sec_offset; + LOAD_CONSTANT("inode_ctime_sec_offset", inode_ctime_sec_offset); + u64 inode_ctime_nsec_offset; + LOAD_CONSTANT("inode_ctime_nsec_offset", inode_ctime_nsec_offset); + + if (inode_ctime_sec_offset && inode_ctime_nsec_offset) { + bpf_probe_read(&file->metadata.ctime.tv_sec, sizeof(file->metadata.ctime.tv_sec), (void *)d_inode + inode_ctime_sec_offset); + u32 nsec; + bpf_probe_read(&nsec, sizeof(nsec), (void *)d_inode + inode_ctime_nsec_offset); + file->metadata.ctime.tv_nsec = nsec; + } else { #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) bpf_probe_read(&file->metadata.ctime, sizeof(file->metadata.ctime), &d_inode->i_ctime); #elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0) @@ -115,7 +126,19 @@ void __attribute__((always_inline)) fill_file(struct dentry *dentry, struct file bpf_probe_read(&file->metadata.ctime.tv_sec, sizeof(file->metadata.ctime.tv_sec), &d_inode->i_ctime_sec); bpf_probe_read(&file->metadata.ctime.tv_nsec, sizeof(file->metadata.ctime.tv_nsec), &d_inode->i_ctime_nsec); #endif - + } + + u64 inode_mtime_sec_offset; + LOAD_CONSTANT("inode_mtime_sec_offset", inode_mtime_sec_offset); + u64 inode_mtime_nsec_offset; + LOAD_CONSTANT("inode_mtime_nsec_offset", inode_mtime_nsec_offset); + + if (inode_mtime_sec_offset && inode_mtime_nsec_offset) { + bpf_probe_read(&file->metadata.mtime.tv_sec, sizeof(file->metadata.mtime.tv_sec), (void *)d_inode + inode_mtime_sec_offset); + u32 nsec; + bpf_probe_read(&nsec, sizeof(nsec), (void *)d_inode + inode_mtime_nsec_offset); + file->metadata.mtime.tv_nsec = nsec; + } else { #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0) bpf_probe_read(&file->metadata.mtime, sizeof(file->metadata.mtime), &d_inode->i_mtime); #elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0) @@ -124,6 +147,7 @@ void __attribute__((always_inline)) fill_file(struct dentry *dentry, struct file bpf_probe_read(&file->metadata.mtime.tv_sec, sizeof(file->metadata.mtime.tv_sec), &d_inode->i_mtime_sec); bpf_probe_read(&file->metadata.mtime.tv_nsec, sizeof(file->metadata.mtime.tv_nsec), &d_inode->i_mtime_nsec); #endif + } } #define get_dentry_key_path(dentry, path) \ diff --git a/pkg/security/ebpf/c/include/hooks/all.h b/pkg/security/ebpf/c/include/hooks/all.h index fcfa5fd5624fa..5fc9709eb528c 100644 --- a/pkg/security/ebpf/c/include/hooks/all.h +++ b/pkg/security/ebpf/c/include/hooks/all.h @@ -37,6 +37,7 @@ #include "chdir.h" #include "network/bind.h" +#include "network/connect.h" #ifndef DO_NOT_USE_TC #include "network/dns.h" diff --git a/pkg/security/ebpf/c/include/hooks/network/connect.h b/pkg/security/ebpf/c/include/hooks/network/connect.h new file mode 100644 index 0000000000000..fbf374f580b64 --- /dev/null +++ b/pkg/security/ebpf/c/include/hooks/network/connect.h @@ -0,0 +1,124 @@ +#ifndef _HOOKS_CONNECT_H_ +#define _HOOKS_CONNECT_H_ + +#include "constants/offsets/netns.h" +#include "constants/syscall_macro.h" +#include "helpers/discarders.h" + +HOOK_SYSCALL_ENTRY3(connect, int, socket, struct sockaddr *, addr, unsigned int, addr_len) { + if (!addr) { + return 0; + } + + struct syscall_cache_t syscall = { + .type = EVENT_CONNECT, + }; + cache_syscall(&syscall); + return 0; +} + +int __attribute__((always_inline)) sys_connect_ret(void *ctx, int retval) { + struct syscall_cache_t *syscall = pop_syscall(EVENT_CONNECT); + if (!syscall) { + return 0; + } + + if (IS_UNHANDLED_ERROR(retval)) { + return 0; + } + + /* pre-fill the event */ + struct connect_event_t event = { + .syscall.retval = retval, + .addr[0] = syscall->connect.addr[0], + .addr[1] = syscall->connect.addr[1], + .family = syscall->connect.family, + .port = syscall->connect.port, + }; + + struct proc_cache_t *entry = fill_process_context(&event.process); + fill_container_context(entry, &event.container); + fill_span_context(&event.span); + + // Check if we should sample this event for activity dumps + struct activity_dump_config *config = lookup_or_delete_traced_pid(event.process.pid, bpf_ktime_get_ns(), NULL); + if (config) { + if (mask_has_event(config->event_mask, EVENT_CONNECT)) { + event.event.flags |= EVENT_FLAGS_ACTIVITY_DUMP_SAMPLE; + } + } + + send_event(ctx, EVENT_CONNECT, event); + return 0; +} + +HOOK_SYSCALL_EXIT(connect) { + int retval = SYSCALL_PARMRET(ctx); + return sys_connect_ret(ctx, retval); +} + +HOOK_ENTRY("security_socket_connect") +int hook_security_socket_connect(ctx_t *ctx) { + struct socket *sk = (struct socket *)CTX_PARM1(ctx); + struct sockaddr *address = (struct sockaddr *)CTX_PARM2(ctx); + struct pid_route_t key = {}; + u16 family = 0; + + + // Extract IP and port from the sockaddr structure + bpf_probe_read(&family, sizeof(family), &address->sa_family); + + if (family == AF_INET) { + struct sockaddr_in *addr_in = (struct sockaddr_in *)address; + bpf_probe_read(&key.port, sizeof(addr_in->sin_port), &addr_in->sin_port); + bpf_probe_read(&key.addr, sizeof(addr_in->sin_addr.s_addr), &addr_in->sin_addr.s_addr); + } else if (family == AF_INET6) { + struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)address; + bpf_probe_read(&key.port, sizeof(addr_in6->sin6_port), &addr_in6->sin6_port); + bpf_probe_read(&key.addr, sizeof(u64) * 2, (char *)addr_in6 + offsetof(struct sockaddr_in6, sin6_addr)); + } + + // fill syscall_cache if necessary + struct syscall_cache_t *syscall = peek_syscall(EVENT_CONNECT); + if (syscall) { + syscall->connect.addr[0] = key.addr[0]; + syscall->connect.addr[1] = key.addr[1]; + syscall->connect.port = key.port; + syscall->connect.family = family; + } + + // Only handle AF_INET and AF_INET6 + if (family != AF_INET && family != AF_INET6) { + return 0; + } + + // Register service PID + if (key.port != 0) { + u64 id = bpf_get_current_pid_tgid(); + u32 tid = (u32)id; + + // add netns information + key.netns = get_netns_from_socket(sk); + if (key.netns != 0) { + bpf_map_update_elem(&netns_cache, &tid, &key.netns, BPF_ANY); + } + +#ifndef DO_NOT_USE_TC + u32 pid = id >> 32; + bpf_map_update_elem(&flow_pid, &key, &pid, BPF_ANY); +#endif + +#if defined(DEBUG_CONNECT) + __bpf_printk("------------# registered (connect) pid:%d", pid); + __bpf_printk("------------# p:%d a:%d a:%d", key.port, key.addr[0], key.addr[1]); +#endif + } + return 0; +} + +SEC("tracepoint/handle_sys_connect_exit") +int tracepoint_handle_sys_connect_exit(struct tracepoint_raw_syscalls_sys_exit_t *args) { + return sys_connect_ret(args, args->ret); +} + +#endif /* _CONNECT_H_ */ diff --git a/pkg/security/ebpf/c/include/hooks/open.h b/pkg/security/ebpf/c/include/hooks/open.h index 105a04d31edfd..c66a00ea5b84a 100644 --- a/pkg/security/ebpf/c/include/hooks/open.h +++ b/pkg/security/ebpf/c/include/hooks/open.h @@ -190,7 +190,14 @@ int hook_do_dentry_open(ctx_t *ctx) { } struct file *file = (struct file *)CTX_PARM1(ctx); - struct inode *inode = (struct inode *)CTX_PARM2(ctx); + + u64 do_dentry_open_without_inode; + LOAD_CONSTANT("do_dentry_open_without_inode", do_dentry_open_without_inode); + + struct inode *inode = NULL; + if (!do_dentry_open_without_inode) { + inode = (struct inode *)CTX_PARM2(ctx); + } return handle_exec_event(ctx, syscall, file, inode); } diff --git a/pkg/security/ebpf/c/include/structs/syscalls.h b/pkg/security/ebpf/c/include/structs/syscalls.h index 7217ec8a54810..e7db82fa396ee 100644 --- a/pkg/security/ebpf/c/include/structs/syscalls.h +++ b/pkg/security/ebpf/c/include/structs/syscalls.h @@ -208,6 +208,12 @@ struct syscall_cache_t { u16 port; } bind; + struct { + u64 addr[2]; + u16 family; + u16 port; + } connect; + struct { struct dentry *dentry; struct path *path; diff --git a/pkg/security/ebpf/kernel/kernel.go b/pkg/security/ebpf/kernel/kernel.go index f6e6060a5be42..e710b4a29eb9b 100644 --- a/pkg/security/ebpf/kernel/kernel.go +++ b/pkg/security/ebpf/kernel/kernel.go @@ -102,6 +102,10 @@ var ( Kernel6_5 = kernel.VersionCode(6, 5, 0) // Kernel6_6 is the KernelVersion representation of kernel version 6.6 Kernel6_6 = kernel.VersionCode(6, 6, 0) + // Kernel6_10 is the KernelVersion representation of kernel version 6.10 + Kernel6_10 = kernel.VersionCode(6, 10, 0) + // Kernel6_11 is the KernelVersion representation of kernel version 6.11 + Kernel6_11 = kernel.VersionCode(6, 11, 0) ) // Version defines a kernel version helper diff --git a/pkg/security/ebpf/probes/all.go b/pkg/security/ebpf/probes/all.go index 1d1c52a936186..ece52381b31f3 100644 --- a/pkg/security/ebpf/probes/all.go +++ b/pkg/security/ebpf/probes/all.go @@ -24,7 +24,7 @@ const ( minPathnamesEntries = 64000 // ~27 MB maxPathnamesEntries = 96000 - minProcEntries = 16394 + minProcEntries = 16384 maxProcEntries = 131072 ) @@ -78,6 +78,7 @@ func AllProbes(fentry bool) []*manager.Probe { allProbes = append(allProbes, getNetDeviceProbes()...) allProbes = append(allProbes, GetTCProbes(true)...) allProbes = append(allProbes, getBindProbes(fentry)...) + allProbes = append(allProbes, getConnectProbes(fentry)...) allProbes = append(allProbes, getSyscallMonitorProbes()...) allProbes = append(allProbes, getChdirProbes(fentry)...) allProbes = append(allProbes, GetOnDemandProbes()...) @@ -151,21 +152,29 @@ type MapSpecEditorOpts struct { RingBufferSize uint32 PathResolutionEnabled bool SecurityProfileMaxCount int + ReducedProcPidCacheSize bool } // AllMapSpecEditors returns the list of map editors func AllMapSpecEditors(numCPU int, opts MapSpecEditorOpts) map[string]manager.MapSpecEditor { + var procPidCacheMaxEntries uint32 + if opts.ReducedProcPidCacheSize { + procPidCacheMaxEntries = getMaxEntries(numCPU, minProcEntries, maxProcEntries/2) + } else { + procPidCacheMaxEntries = getMaxEntries(numCPU, minProcEntries, maxProcEntries) + } + editors := map[string]manager.MapSpecEditor{ "syscalls": { MaxEntries: 8192, EditorFlag: manager.EditMaxEntries, }, "proc_cache": { - MaxEntries: getMaxEntries(numCPU, minProcEntries, maxProcEntries), + MaxEntries: procPidCacheMaxEntries, EditorFlag: manager.EditMaxEntries, }, "pid_cache": { - MaxEntries: getMaxEntries(numCPU, minProcEntries, maxProcEntries), + MaxEntries: procPidCacheMaxEntries, EditorFlag: manager.EditMaxEntries, }, diff --git a/pkg/security/ebpf/probes/connect.go b/pkg/security/ebpf/probes/connect.go new file mode 100644 index 0000000000000..c96f49a7f4016 --- /dev/null +++ b/pkg/security/ebpf/probes/connect.go @@ -0,0 +1,30 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build linux + +// Package probes holds probes related files +package probes + +import manager "github.com/DataDog/ebpf-manager" + +func getConnectProbes(fentry bool) []*manager.Probe { + var connectProbes []*manager.Probe + connectProbes = append(connectProbes, ExpandSyscallProbes(&manager.Probe{ + ProbeIdentificationPair: manager.ProbeIdentificationPair{ + UID: SecurityAgentUID, + }, + SyscallFuncName: "connect", + }, fentry, EntryAndExit)...) + + connectProbes = append(connectProbes, &manager.Probe{ + ProbeIdentificationPair: manager.ProbeIdentificationPair{ + UID: SecurityAgentUID, + EBPFFuncName: "hook_security_socket_connect", + }, + }) + + return connectProbes +} diff --git a/pkg/security/ebpf/probes/event_types.go b/pkg/security/ebpf/probes/event_types.go index d882f048fb299..b70447dba6a59 100644 --- a/pkg/security/ebpf/probes/event_types.go +++ b/pkg/security/ebpf/probes/event_types.go @@ -41,6 +41,7 @@ func NetworkSelectors() []manager.ProbesSelector { // flow classification probes &manager.AllOf{Selectors: []manager.ProbesSelector{ kprobeOrFentry("security_socket_bind"), + kprobeOrFentry("security_socket_connect"), kprobeOrFentry("security_sk_classify_flow"), kprobeOrFentry("path_get"), kprobeOrFentry("proc_fd_link"), @@ -448,6 +449,13 @@ func GetSelectorsPerEventType(fentry bool) map[eval.EventType][]manager.ProbesSe }}, &manager.BestEffort{Selectors: ExpandSyscallProbesSelector(SecurityAgentUID, "bind", fentry, EntryAndExit)}, }, + // List of probes required to capture connect events + "connect": { + &manager.AllOf{Selectors: []manager.ProbesSelector{ + kprobeOrFentry("security_socket_connect"), + }}, + &manager.BestEffort{Selectors: ExpandSyscallProbesSelector(SecurityAgentUID, "connect", fentry, EntryAndExit)}, + }, // List of probes required to capture chdir events "chdir": { diff --git a/pkg/security/ebpf/probes/raw_sys_exit.go b/pkg/security/ebpf/probes/raw_sys_exit.go index 2210aab6d4221..14e489cb47a58 100644 --- a/pkg/security/ebpf/probes/raw_sys_exit.go +++ b/pkg/security/ebpf/probes/raw_sys_exit.go @@ -170,6 +170,13 @@ func getSysExitTailCallRoutes() []manager.TailCallRoute { EBPFFuncName: "tracepoint_handle_sys_bind_exit", }, }, + { + ProgArrayName: "sys_exit_progs", + Key: uint32(model.ConnectEventType), + ProbeIdentificationPair: manager.ProbeIdentificationPair{ + EBPFFuncName: "tracepoint_handle_sys_connect_exit", + }, + }, { ProgArrayName: "sys_exit_progs", Key: uint32(model.LoadModuleEventType), diff --git a/pkg/security/module/server_linux.go b/pkg/security/module/server_linux.go index 8792568894686..2ffde0ce911e2 100644 --- a/pkg/security/module/server_linux.go +++ b/pkg/security/module/server_linux.go @@ -11,6 +11,7 @@ import ( "context" "errors" "fmt" + "os" "github.com/DataDog/datadog-agent/pkg/security/probe" "github.com/DataDog/datadog-agent/pkg/security/proto/api" @@ -36,9 +37,39 @@ func (a *APIServer) DumpProcessCache(_ context.Context, params *api.DumpProcessC return nil, fmt.Errorf("not supported") } - filename, err := p.Resolvers.ProcessResolver.ToDot(params.WithArgs) - if err != nil { - return nil, err + var ( + filename string + err error + ) + + switch params.Format { + case "json": + jsonContent, err := p.Resolvers.ProcessResolver.ToJSON(true) + if err != nil { + return nil, err + } + + dump, err := os.CreateTemp("/tmp", "process-cache-dump-*.json") + if err != nil { + return nil, err + } + + defer dump.Close() + + filename = dump.Name() + if err := os.Chmod(dump.Name(), 0400); err != nil { + return nil, err + } + + if _, err := dump.Write(jsonContent); err != nil { + return nil, err + } + + case "dot", "": + filename, err = p.Resolvers.ProcessResolver.ToDot(params.WithArgs) + if err != nil { + return nil, err + } } return &api.SecurityDumpProcessCacheMessage{ diff --git a/pkg/security/probe/constantfetch/constant_names.go b/pkg/security/probe/constantfetch/constant_names.go index 764d294840e07..c5ee88a4452f6 100644 --- a/pkg/security/probe/constantfetch/constant_names.go +++ b/pkg/security/probe/constantfetch/constant_names.go @@ -30,6 +30,12 @@ const ( OffsetNameFileFpath = "file_f_path_offset" OffsetNameMountMntID = "mount_id_offset" + // inode times + OffsetNameInodeCtimeSec = "inode_ctime_sec_offset" + OffsetNameInodeCtimeNsec = "inode_ctime_nsec_offset" + OffsetNameInodeMtimeSec = "inode_mtime_sec_offset" + OffsetNameInodeMtimeNsec = "inode_mtime_nsec_offset" + // rename OffsetNameRenameStructOldDentry = "vfs_rename_src_dentry_offset" OffsetNameRenameStructNewDentry = "vfs_rename_target_dentry_offset" diff --git a/pkg/security/probe/coredump.go b/pkg/security/probe/coredump.go index 156cf73682740..7446d6be299b3 100644 --- a/pkg/security/probe/coredump.go +++ b/pkg/security/probe/coredump.go @@ -50,7 +50,7 @@ func (cd *CoreDump) ToJSON() ([]byte, error) { } if cd.definition.Process { - data, _ := cd.resolvers.ProcessResolver.ToJSON() + data, _ := cd.resolvers.ProcessResolver.ToJSON(false) content.Process = data } diff --git a/pkg/security/probe/eventconsumer.go b/pkg/security/probe/eventconsumer.go new file mode 100644 index 0000000000000..8e4dc77258247 --- /dev/null +++ b/pkg/security/probe/eventconsumer.go @@ -0,0 +1,39 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022-present Datadog, Inc. + +package probe + +import ( + "github.com/DataDog/datadog-agent/pkg/security/events" + "github.com/DataDog/datadog-agent/pkg/security/secl/model" + "github.com/DataDog/datadog-agent/pkg/security/secl/rules" +) + +// this file contain common platform-agnostic interfaces (no go:build tags) + +// EventHandler represents a handler for events sent by the probe that needs access to all the fields in the SECL model +type EventHandler interface { + HandleEvent(event *model.Event) +} + +// EventConsumerHandler represents a handler for events sent by the probe. This handler makes a copy of the event upon receipt +type EventConsumerHandler interface { + IDer + ChanSize() int + HandleEvent(_ any) + Copy(_ *model.Event) any + EventTypes() []model.EventType +} + +// IDer provides unique ID for each event consumer +type IDer interface { + // ID returns the ID of the event consumer + ID() string +} + +// CustomEventHandler represents an handler for the custom events sent by the probe +type CustomEventHandler interface { + HandleCustomEvent(rule *rules.Rule, event *events.CustomEvent) +} diff --git a/pkg/security/probe/field_handlers_ebpf.go b/pkg/security/probe/field_handlers_ebpf.go index 0f3d8d66b1d05..8ec11f9a3e6ab 100644 --- a/pkg/security/probe/field_handlers_ebpf.go +++ b/pkg/security/probe/field_handlers_ebpf.go @@ -292,6 +292,11 @@ func (fh *EBPFFieldHandlers) ResolveProcessEnvs(_ *model.Event, process *model.P return envs } +// ResolveProcessIsThread returns true is the process is a thread +func (fh *EBPFFieldHandlers) ResolveProcessIsThread(_ *model.Event, process *model.Process) bool { + return !process.IsExec +} + // ResolveSetuidUser resolves the user of the Setuid event func (fh *EBPFFieldHandlers) ResolveSetuidUser(ev *model.Event, e *model.SetuidEvent) string { if len(e.User) == 0 { diff --git a/pkg/security/probe/field_handlers_ebpfless.go b/pkg/security/probe/field_handlers_ebpfless.go index e170eb5076c87..c4bf87a17423d 100644 --- a/pkg/security/probe/field_handlers_ebpfless.go +++ b/pkg/security/probe/field_handlers_ebpfless.go @@ -126,6 +126,11 @@ func (fh *EBPFLessFieldHandlers) ResolveProcessEnvs(_ *model.Event, process *mod return envs } +// ResolveProcessIsThread returns true is the process is a thread +func (fh *EBPFLessFieldHandlers) ResolveProcessIsThread(_ *model.Event, process *model.Process) bool { + return !process.IsExec +} + // GetProcessCacheEntry queries the ProcessResolver to retrieve the ProcessContext of the event func (fh *EBPFLessFieldHandlers) GetProcessCacheEntry(ev *model.Event) (*model.ProcessCacheEntry, bool) { ev.ProcessCacheEntry = fh.resolvers.ProcessResolver.Resolve(sprocess.CacheResolverKey{ diff --git a/pkg/security/probe/probe.go b/pkg/security/probe/probe.go index 18c91108643e7..ef19e6e39fea1 100644 --- a/pkg/security/probe/probe.go +++ b/pkg/security/probe/probe.go @@ -57,26 +57,11 @@ type PlatformProbe interface { GetEventTags(_ string) []string GetProfileManager() interface{} EnableEnforcement(bool) - PlaySnapshot() -} - -// EventHandler represents a handler for events sent by the probe that needs access to all the fields in the SECL model -type EventHandler interface { - HandleEvent(event *model.Event) -} - -// EventConsumerInterface represents a handler for events sent by the probe. This handler makes a copy of the event upon receipt -type EventConsumerInterface interface { - ID() string - ChanSize() int - HandleEvent(_ any) - Copy(_ *model.Event) any - EventTypes() []model.EventType } // EventConsumer defines a probe event consumer type EventConsumer struct { - consumer EventConsumerInterface + consumer EventConsumerHandler eventCh chan any eventDropped *atomic.Int64 } @@ -98,11 +83,6 @@ func (p *EventConsumer) Start(ctx context.Context, wg *sync.WaitGroup) { }() } -// CustomEventHandler represents an handler for the custom events sent by the probe -type CustomEventHandler interface { - HandleCustomEvent(rule *rules.Rule, event *events.CustomEvent) -} - // DiscarderPushedCallback describe the callback used to retrieve pushed discarders information type DiscarderPushedCallback func(eventType string, event *model.Event, field string) @@ -280,7 +260,7 @@ func (p *Probe) HandleActions(rule *rules.Rule, event eval.Event) { } // AddEventConsumer sets a probe event consumer -func (p *Probe) AddEventConsumer(consumer EventConsumerInterface) error { +func (p *Probe) AddEventConsumer(consumer EventConsumerHandler) error { chanSize := consumer.ChanSize() if chanSize <= 0 { chanSize = defaultConsumerChanSize @@ -461,8 +441,3 @@ func (p *Probe) IsSecurityProfileEnabled() bool { func (p *Probe) EnableEnforcement(state bool) { p.PlatformProbe.EnableEnforcement(state) } - -// PlaySnapshot plays the snapshot -func (p *Probe) PlaySnapshot() { - p.PlatformProbe.PlaySnapshot() -} diff --git a/pkg/security/probe/probe_ebpf.go b/pkg/security/probe/probe_ebpf.go index 70fd49e0af48d..4d2506f4f0005 100644 --- a/pkg/security/probe/probe_ebpf.go +++ b/pkg/security/probe/probe_ebpf.go @@ -23,6 +23,7 @@ import ( lib "github.com/cilium/ebpf" "github.com/hashicorp/go-multierror" "github.com/moby/sys/mountinfo" + "go.uber.org/atomic" "golang.org/x/sys/unix" "golang.org/x/time/rate" "gopkg.in/yaml.v3" @@ -75,9 +76,11 @@ type EventStream interface { Resume() error } -// MaxOnDemandEventsPerSecond represents the maximum number of on demand events per second -// allowed before we switch off the subsystem -const MaxOnDemandEventsPerSecond = 1_000 +const ( + // MaxOnDemandEventsPerSecond represents the maximum number of on demand events per second + // allowed before we switch off the subsystem + MaxOnDemandEventsPerSecond = 1_000 +) var ( // defaultEventTypes event types used whatever the event handlers or the rules @@ -151,6 +154,10 @@ type EBPFProbe struct { // hash action fileHasher *FileHasher + + // snapshot + ruleSetVersion uint64 + playSnapShotState *atomic.Bool } // GetProfileManager returns the Profile Managers @@ -407,7 +414,7 @@ func (p *EBPFProbe) Setup() error { // Start the probe func (p *EBPFProbe) Start() error { // Apply rules to the snapshotted data before starting the event stream to avoid concurrency issues - p.PlaySnapshot() + p.playSnapshot(true) // start new tc classifier loop go p.startSetupNewTCClassifierLoop() @@ -416,13 +423,13 @@ func (p *EBPFProbe) Start() error { } // PlaySnapshot plays a snapshot -func (p *EBPFProbe) PlaySnapshot() { +func (p *EBPFProbe) playSnapshot(notifyConsumers bool) { seclog.Debugf("playing the snapshot") // Get the snapshotted data var events []*model.Event entryToEvent := func(entry *model.ProcessCacheEntry) { - if entry.Source != model.ProcessCacheEntryFromSnapshot { + if entry.Source != model.ProcessCacheEntryFromSnapshot && !entry.IsExec { return } entry.Retain() @@ -443,7 +450,7 @@ func (p *EBPFProbe) PlaySnapshot() { } p.Resolvers.ProcessResolver.Walk(entryToEvent) for _, event := range events { - p.DispatchEvent(event) + p.DispatchEvent(event, notifyConsumers) event.ProcessCacheEntry.Release() } } @@ -466,7 +473,7 @@ func (p *EBPFProbe) AddActivityDumpHandler(handler dump.ActivityDumpHandler) { } // DispatchEvent sends an event to the probe event handler -func (p *EBPFProbe) DispatchEvent(event *model.Event) { +func (p *EBPFProbe) DispatchEvent(event *model.Event, notifyConsumers bool) { traceEvent("Dispatching event %s", func() ([]byte, model.EventType, error) { eventJSON, err := serializers.MarshalEvent(event, nil) return eventJSON, event.GetEventType(), err @@ -489,7 +496,9 @@ func (p *EBPFProbe) DispatchEvent(event *model.Event) { p.probe.sendEventToHandlers(event) // send event to specific event handlers, like the event monitor consumers, subsequently - p.probe.sendEventToConsumers(event) + if notifyConsumers { + p.probe.sendEventToConsumers(event) + } // handle anomaly detections if event.IsAnomalyDetectionEvent() { @@ -631,6 +640,12 @@ func (p *EBPFProbe) zeroEvent() *model.Event { } func (p *EBPFProbe) handleEvent(CPU int, data []byte) { + // handle play snapshot + if p.playSnapShotState.Swap(false) { + // do not notify consumers as we are replaying the snapshot after a ruleset reload + p.playSnapshot(false) + } + offset := 0 event := p.zeroEvent() @@ -1075,6 +1090,11 @@ func (p *EBPFProbe) handleEvent(CPU int, data []byte) { seclog.Errorf("failed to decode bind event: %s (offset %d, len %d)", err, offset, len(data)) return } + case model.ConnectEventType: + if _, err = event.Connect.UnmarshalBinary(data[offset:]); err != nil { + seclog.Errorf("failed to decode connect event: %s (offset %d, len %d)", err, offset, len(data)) + return + } case model.SyscallsEventType: if _, err = event.Syscalls.UnmarshalBinary(data[offset:]); err != nil { seclog.Errorf("failed to decode syscalls event: %s (offset %d, len %d)", err, offset, len(data)) @@ -1096,7 +1116,7 @@ func (p *EBPFProbe) handleEvent(CPU int, data []byte) { // resolve the container context event.ContainerContext, _ = p.fieldHandlers.ResolveContainerContext(event) - p.DispatchEvent(event) + p.DispatchEvent(event, true) if eventType == model.ExitEventType { p.Resolvers.ProcessResolver.DeleteEntry(event.ProcessContext.Pid, event.ResolveEventTime()) @@ -1684,6 +1704,13 @@ func (p *EBPFProbe) ApplyRuleSet(rs *rules.RuleSet) (*kfilters.ApplyRuleSetRepor } } + // do not replay the snapshot if we are in the first rule set version, this was already done in the start method + if p.ruleSetVersion != 0 { + p.playSnapShotState.Store(true) + } + + p.ruleSetVersion++ + return ars, nil } @@ -1747,6 +1774,7 @@ func NewEBPFProbe(probe *Probe, config *config.Config, opts Opts, telemetry tele newTCNetDevices: make(chan model.NetDevice, 16), processKiller: processKiller, onDemandRateLimiter: rate.NewLimiter(onDemandRate, 1), + playSnapShotState: atomic.NewBool(false), } if err := p.detectKernelVersion(); err != nil { @@ -1843,6 +1871,10 @@ func NewEBPFProbe(probe *Probe, config *config.Config, opts Opts, telemetry tele Name: "do_fork_input", Value: getDoForkInput(p.kernelVersion), }, + manager.ConstantEditor{ + Name: "do_dentry_open_without_inode", + Value: getDoDentryOpenWithoutInode(p.kernelVersion), + }, manager.ConstantEditor{ Name: "has_usernamespace_first_arg", Value: getHasUsernamespaceFirstArg(p.kernelVersion), @@ -2059,6 +2091,13 @@ func getDoForkInput(kernelVersion *kernel.Version) uint64 { return doForkListInput } +func getDoDentryOpenWithoutInode(kernelversion *kernel.Version) uint64 { + if kernelversion.Code != 0 && kernelversion.Code >= kernel.Kernel6_10 { + return 1 + } + return 0 +} + func getHasUsernamespaceFirstArg(kernelVersion *kernel.Version) uint64 { if val, err := constantfetch.GetHasUsernamespaceFirstArgWithBtf(); err == nil { if val { @@ -2176,6 +2215,16 @@ func AppendProbeRequestsToFetcher(constantFetcher constantfetch.ConstantFetcher, constantFetcher.AppendOffsetofRequest(constantfetch.OffsetNameKernelCloneArgsExitSignal, "struct kernel_clone_args", "exit_signal", "linux/sched/task.h") } + // inode time offsets + // no runtime compilation for those, we expect them to default to 0 if not there and use the fallback + // in the eBPF code itself in that case + if kv.Code >= kernel.Kernel6_11 { + constantFetcher.AppendOffsetofRequest(constantfetch.OffsetNameInodeCtimeSec, "struct inode", "i_ctime_sec", "") + constantFetcher.AppendOffsetofRequest(constantfetch.OffsetNameInodeCtimeNsec, "struct inode", "i_ctime_nsec", "") + constantFetcher.AppendOffsetofRequest(constantfetch.OffsetNameInodeMtimeSec, "struct inode", "i_mtime_sec", "") + constantFetcher.AppendOffsetofRequest(constantfetch.OffsetNameInodeMtimeNsec, "struct inode", "i_mtime_nsec", "") + } + // rename offsets if kv.Code >= kernel.Kernel5_12 || (kv.IsInRangeCloseOpen(kernel.Kernel5_10, kernel.Kernel5_11) && kv.Code.Patch() >= 220) { constantFetcher.AppendOffsetofRequest(constantfetch.OffsetNameRenameStructOldDentry, "struct renamedata", "old_dentry", "linux/fs.h") diff --git a/pkg/security/probe/probe_ebpfless.go b/pkg/security/probe/probe_ebpfless.go index ec7a807e2360a..4ca6146e185b9 100644 --- a/pkg/security/probe/probe_ebpfless.go +++ b/pkg/security/probe/probe_ebpfless.go @@ -703,8 +703,3 @@ func NewEBPFLessProbe(probe *Probe, config *config.Config, opts Opts, telemetry return p, nil } - -// PlaySnapshot plays a snapshot -func (p *EBPFLessProbe) PlaySnapshot() { - // TODO: Implement this method if needed. -} diff --git a/pkg/security/probe/probe_others.go b/pkg/security/probe/probe_others.go index c3f168ab03414..61d972b2bd94d 100644 --- a/pkg/security/probe/probe_others.go +++ b/pkg/security/probe/probe_others.go @@ -17,21 +17,6 @@ import ( "github.com/DataDog/datadog-agent/pkg/security/secl/rules" ) -// EventConsumerInterface represents a handler for events sent by the probe. This handler makes a copy of the event upon receipt -type EventConsumerInterface interface { - ID() string - ChanSize() int - HandleEvent(_ any) - Copy(_ *model.Event) any - EventTypes() []model.EventType -} - -// EventHandler represents an handler for the events sent by the probe -type EventHandler interface{} - -// CustomEventHandler represents an handler for the custom events sent by the probe -type CustomEventHandler interface{} - // PlatformProbe represents the no-op platform probe on unsupported platforms type PlatformProbe struct { } @@ -120,8 +105,3 @@ func (p *Probe) HandleActions(_ *rules.Rule, _ eval.Event) {} // EnableEnforcement sets the enforcement mode func (p *Probe) EnableEnforcement(_ bool) {} - -// PlaySnapshot plays the snapshot -func (p *Probe) PlaySnapshot() { - // TODO: Implement this method if needed. -} diff --git a/pkg/security/probe/probe_windows.go b/pkg/security/probe/probe_windows.go index 600551cf9d646..ef3a1ae606844 100644 --- a/pkg/security/probe/probe_windows.go +++ b/pkg/security/probe/probe_windows.go @@ -1444,8 +1444,3 @@ func (p *WindowsProbe) setApprovers(_ eval.EventType, approvers rules.Approvers) return nil } - -// PlaySnapshot plays a snapshot -func (p *WindowsProbe) PlaySnapshot() { - // TODO: Implement this method if needed. -} diff --git a/pkg/security/proto/api/api.pb.go b/pkg/security/proto/api/api.pb.go index def5bb8076c25..60cc167d246f9 100644 --- a/pkg/security/proto/api/api.pb.go +++ b/pkg/security/proto/api/api.pb.go @@ -134,7 +134,8 @@ type DumpProcessCacheParams struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - WithArgs bool `protobuf:"varint,1,opt,name=WithArgs,proto3" json:"WithArgs,omitempty"` + WithArgs bool `protobuf:"varint,1,opt,name=WithArgs,proto3" json:"WithArgs,omitempty"` + Format string `protobuf:"bytes,2,opt,name=Format,proto3" json:"Format,omitempty"` } func (x *DumpProcessCacheParams) Reset() { @@ -176,6 +177,13 @@ func (x *DumpProcessCacheParams) GetWithArgs() bool { return false } +func (x *DumpProcessCacheParams) GetFormat() string { + if x != nil { + return x.Format + } + return "" +} + type SecurityDumpProcessCacheMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3135,478 +3143,479 @@ var file_pkg_security_proto_api_api_proto_rawDesc = []byte{ 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x34, 0x0a, 0x16, 0x44, + 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x4c, 0x0a, 0x16, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x57, 0x69, 0x74, 0x68, 0x41, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x57, 0x69, 0x74, 0x68, 0x41, 0x72, 0x67, - 0x73, 0x22, 0x3d, 0x0a, 0x1f, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, - 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x22, 0x4c, 0x0a, 0x1a, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2e, - 0x0a, 0x12, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, - 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x53, 0x6e, 0x61, 0x70, - 0x73, 0x68, 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x22, 0x7d, - 0x0a, 0x1b, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x44, 0x75, 0x6d, 0x70, 0x46, - 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x47, 0x72, 0x61, 0x70, 0x68, - 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x47, 0x72, 0x61, 0x70, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x11, 0x0a, - 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x22, 0x91, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x52, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x46, 0x49, 0x4d, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x46, 0x49, 0x4d, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, - 0x6d, 0x70, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x13, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x22, 0x48, 0x0a, 0x14, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x08, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x71, - 0x0a, 0x0f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x4d, - 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x70, 0x70, - 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x52, 0x09, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, - 0x73, 0x22, 0x61, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x12, 0x3e, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x74, - 0x61, 0x69, 0x6c, 0x73, 0x22, 0x51, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, - 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, - 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x22, 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x52, 0x75, - 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x22, 0x84, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, - 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x4d, 0x0a, 0x14, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x14, 0x52, 0x75, - 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x16, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x6f, - 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x22, 0x1d, 0x0a, 0x1b, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x13, 0x0a, 0x11, 0x52, 0x75, 0x6e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x22, 0x45, 0x0a, 0x1d, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, - 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x02, 0x4f, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x11, 0x0a, 0x0f, 0x47, - 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x56, - 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x41, - 0x6e, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x67, 0x0a, 0x0f, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, - 0x73, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x4c, 0x61, 0x73, - 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, - 0x18, 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x61, 0x69, - 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x22, - 0x4a, 0x0a, 0x0a, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, - 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x16, 0x0a, - 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x63, 0x0a, 0x0c, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x75, - 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x22, 0xb1, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x45, - 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, - 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0b, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x09, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, - 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, - 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, - 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x69, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x22, 0x68, 0x0a, 0x15, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, - 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, - 0x08, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x08, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x73, 0x12, 0x33, 0x0a, 0x06, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x41, 0x6e, 0x64, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xe1, - 0x01, 0x0a, 0x11, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x38, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x74, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x09, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x4b, 0x65, - 0x72, 0x6e, 0x65, 0x6c, 0x4c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, - 0x77, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x4d, 0x6d, 0x61, 0x70, 0x61, 0x62, 0x6c, - 0x65, 0x4d, 0x61, 0x70, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x55, 0x73, 0x65, - 0x4d, 0x6d, 0x61, 0x70, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x73, 0x12, 0x24, 0x0a, 0x0d, - 0x55, 0x73, 0x65, 0x52, 0x69, 0x6e, 0x67, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0d, 0x55, 0x73, 0x65, 0x52, 0x69, 0x6e, 0x67, 0x42, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x22, 0x16, 0x0a, 0x14, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, - 0x64, 0x65, 0x72, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3b, 0x0a, 0x15, 0x44, 0x75, - 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x44, 0x75, 0x6d, 0x70, 0x46, - 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xa8, 0x02, 0x0a, 0x14, 0x53, 0x74, 0x6f, 0x72, - 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x12, 0x34, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x44, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, - 0x61, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x46, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, - 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, - 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0xb3, 0x01, 0x0a, 0x12, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, - 0x75, 0x6d, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x54, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, - 0x69, 0x61, 0x74, 0x65, 0x41, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, - 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65, 0x41, 0x72, 0x67, - 0x73, 0x12, 0x33, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x07, 0x53, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x22, 0xcf, 0x03, 0x0a, 0x0f, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x0c, - 0x41, 0x67, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x20, 0x0a, 0x0b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x4b, 0x65, 0x72, 0x6e, 0x65, - 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x11, 0x4c, 0x69, 0x6e, 0x75, - 0x78, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x11, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, - 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x69, 0x66, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65, 0x41, 0x72, 0x67, 0x73, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x11, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x74, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x04, 0x43, 0x6f, 0x6d, 0x6d, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, 0x43, 0x6f, 0x6d, 0x6d, 0x12, 0x20, - 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0a, 0x20, + 0x73, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x3d, 0x0a, 0x1f, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x4c, 0x0a, 0x1a, 0x44, 0x75, 0x6d, 0x70, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, + 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x12, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x22, 0x7d, 0x0a, 0x1b, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x44, + 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x24, 0x0a, 0x0d, 0x47, 0x72, 0x61, 0x70, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x47, 0x72, 0x61, 0x70, 0x68, 0x46, 0x69, 0x6c, + 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x11, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x52, 0x75, 0x6e, 0x74, + 0x69, 0x6d, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x46, 0x49, + 0x4d, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, + 0x46, 0x49, 0x4d, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x44, 0x75, 0x6d, 0x70, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x48, 0x0a, 0x14, + 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x71, 0x0a, 0x0f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x09, 0x41, + 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x52, 0x09, + 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x22, 0x61, 0x0a, 0x09, 0x41, 0x70, 0x70, + 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x3e, 0x0a, 0x0f, + 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x70, 0x70, 0x72, + 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x41, 0x70, 0x70, + 0x72, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x51, 0x0a, 0x0f, + 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, + 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x22, + 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x84, 0x01, 0x0a, 0x1d, 0x47, 0x65, + 0x74, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x4d, 0x0a, 0x14, 0x52, + 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x14, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x22, 0x16, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, + 0x65, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x1d, 0x0a, 0x1b, 0x52, 0x65, 0x6c, 0x6f, + 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x13, 0x0a, 0x11, 0x52, 0x75, 0x6e, 0x53, 0x65, + 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x45, 0x0a, 0x1d, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, + 0x02, 0x4f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x4f, 0x6b, 0x12, 0x14, 0x0a, + 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x22, 0x11, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x56, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x41, 0x6e, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, + 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x67, + 0x0a, 0x0f, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x46, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x4a, 0x0a, 0x0a, 0x52, 0x75, 0x6c, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, + 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x22, 0x63, 0x0a, 0x0c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, + 0x27, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x45, + 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x0b, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x32, 0x0a, + 0x09, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x73, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, + 0x73, 0x12, 0x39, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0e, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x68, 0x0a, 0x15, + 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, + 0x73, 0x12, 0x33, 0x0a, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x41, 0x6e, 0x64, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xe1, 0x01, 0x0a, 0x11, 0x45, 0x6e, 0x76, 0x69, 0x72, + 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, + 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x38, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, + 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4c, 0x6f, 0x63, 0x6b, + 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x4b, 0x65, 0x72, 0x6e, + 0x65, 0x6c, 0x4c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x55, 0x73, + 0x65, 0x4d, 0x6d, 0x61, 0x70, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x70, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0f, 0x55, 0x73, 0x65, 0x4d, 0x6d, 0x61, 0x70, 0x61, 0x62, 0x6c, 0x65, + 0x4d, 0x61, 0x70, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x55, 0x73, 0x65, 0x52, 0x69, 0x6e, 0x67, 0x42, + 0x75, 0x66, 0x66, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x55, 0x73, 0x65, + 0x52, 0x69, 0x6e, 0x67, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x16, 0x0a, 0x14, 0x44, 0x75, + 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x22, 0x3b, 0x0a, 0x15, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, + 0x64, 0x65, 0x72, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x44, + 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0xa8, 0x02, 0x0a, 0x14, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x34, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x30, + 0x0a, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x46, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, + 0x12, 0x38, 0x0a, 0x17, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x17, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, + 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x14, 0x52, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x73, 0x12, 0x3a, + 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, + 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, + 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xb3, 0x01, 0x0a, 0x12, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x44, + 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65, 0x41, 0x72, 0x67, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x74, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x33, 0x0a, 0x07, 0x53, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, - 0x12, 0x14, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x79, 0x0a, 0x15, 0x53, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, - 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x46, 0x69, 0x6c, 0x65, 0x22, 0xbe, 0x02, 0x0a, 0x13, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x48, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x6f, 0x73, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, - 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, - 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x4e, 0x53, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x44, 0x4e, 0x53, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x12, 0x33, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, - 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x22, 0x5f, 0x0a, 0x17, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x44, - 0x75, 0x6d, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x44, 0x75, 0x6d, 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x22, 0x4e, 0x0a, 0x16, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, - 0x70, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, - 0x44, 0x22, 0x2f, 0x0a, 0x17, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, - 0x70, 0x53, 0x74, 0x6f, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x22, 0x7b, 0x0a, 0x18, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2a, - 0x0a, 0x10, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, - 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, - 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x53, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, + 0x22, 0xcf, 0x03, 0x0a, 0x0f, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x67, 0x65, 0x6e, + 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x41, 0x67, 0x65, 0x6e, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x41, + 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x4b, 0x65, + 0x72, 0x6e, 0x65, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x2c, 0x0a, 0x11, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x4c, 0x69, 0x6e, + 0x75, 0x78, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x41, 0x72, + 0x63, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x74, + 0x65, 0x41, 0x72, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x44, 0x69, 0x66, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x16, + 0x0a, 0x04, 0x43, 0x6f, 0x6d, 0x6d, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x04, 0x43, 0x6f, 0x6d, 0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x18, + 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0d, + 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x22, 0x79, 0x0a, 0x15, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x43, 0x6f, + 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x46, 0x69, 0x6c, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x22, 0xbe, 0x02, + 0x0a, 0x13, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, + 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, + 0x34, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x53, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x1a, 0x0a, + 0x08, 0x44, 0x4e, 0x53, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x08, 0x44, 0x4e, 0x53, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x05, 0x53, 0x74, 0x61, + 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, + 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x18, + 0x0a, 0x16, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, + 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x5f, 0x0a, 0x17, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x44, 0x75, 0x6d, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x44, 0x75, + 0x6d, 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x4e, 0x0a, 0x16, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x22, 0x2f, 0x0a, 0x17, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7b, 0x0a, 0x18, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x46, 0x69, + 0x6c, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x07, + 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x22, 0x67, 0x0a, 0x19, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x07, 0x53, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x22, - 0x67, 0x0a, 0x19, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x41, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x22, 0x5d, 0x0a, 0x19, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x44, 0x75, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, - 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x44, 0x75, 0x6d, 0x70, 0x12, - 0x12, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, - 0x61, 0x74, 0x61, 0x22, 0x3f, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x54, 0x61, 0x67, 0x22, 0x87, 0x01, 0x0a, 0x1b, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, - 0x6d, 0x61, 0x6c, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x12, 0x2c, 0x0a, 0x11, 0x49, 0x73, 0x53, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x49, 0x73, 0x53, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x47, - 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x22, 0xec, 0x01, 0x0a, 0x18, 0x41, 0x63, 0x74, 0x69, - 0x76, 0x69, 0x74, 0x79, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, - 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x11, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x46, 0x69, 0x6c, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x4e, - 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0d, 0x44, 0x4e, 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x2a, 0x0a, 0x10, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x53, 0x6f, 0x63, 0x6b, - 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x0f, - 0x41, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, - 0x74, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x6e, 0x0a, 0x10, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, - 0x73, 0x74, 0x5f, 0x61, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x79, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, - 0x6c, 0x79, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x11, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x9b, 0x02, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x66, 0x69, 0x72, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x12, - 0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x12, 0x58, 0x0a, 0x10, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x58, 0x0a, 0x13, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa0, 0x06, 0x0a, 0x16, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, - 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x26, 0x0a, 0x0e, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, - 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x12, 0x38, 0x0a, 0x17, 0x4c, 0x6f, 0x61, 0x64, 0x65, - 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, - 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x12, 0x38, 0x0a, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, - 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x52, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6f, 0x6b, 0x69, - 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x73, 0x12, 0x4a, 0x0a, 0x0d, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x69, - 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, - 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0d, - 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x32, 0x0a, - 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x12, 0x1a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, - 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, - 0x18, 0x01, 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x08, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x52, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, - 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, - 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x33, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0c, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x69, 0x74, 0x79, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x52, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x47, - 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x5b, 0x0a, 0x10, 0x70, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x18, 0x0e, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x1a, 0x5e, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x66, 0x69, - 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3f, 0x0a, 0x19, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x49, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x22, 0x6b, 0x0a, 0x1a, 0x53, 0x65, 0x63, 0x75, - 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, - 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, - 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x19, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, - 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x12, 0x38, 0x0a, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, - 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x52, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x46, 0x0a, 0x1a, - 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, - 0x61, 0x76, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x12, 0x12, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x46, 0x69, 0x6c, 0x65, 0x32, 0x8a, 0x0a, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, - 0x79, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x3f, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x10, 0x44, 0x75, 0x6d, 0x70, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1b, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x00, 0x12, 0x3f, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x22, 0x00, 0x12, 0x30, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0b, 0x52, 0x75, 0x6e, 0x53, 0x65, 0x6c, 0x66, 0x54, - 0x65, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x65, 0x6c, - 0x66, 0x54, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x22, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x00, 0x12, 0x55, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x52, - 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x1a, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, - 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0e, 0x52, 0x65, 0x6c, 0x6f, - 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6c, 0x6f, - 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x14, 0x44, 0x75, 0x6d, - 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x0e, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, - 0x75, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, - 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x00, 0x12, 0x43, 0x0a, 0x0c, 0x44, 0x75, 0x6d, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x44, 0x75, 0x6d, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, - 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x73, 0x12, 0x1b, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x10, 0x53, 0x74, 0x6f, 0x70, - 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x12, 0x1b, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, - 0x74, 0x6f, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x12, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1e, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, - 0x12, 0x5a, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, - 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x22, 0x1a, 0x0a, 0x18, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x5d, 0x0a, 0x19, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, + 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x44, 0x75, 0x6d, + 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, + 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x52, 0x04, 0x44, 0x75, 0x6d, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x22, 0x3f, 0x0a, 0x17, 0x57, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x61, + 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x61, 0x67, 0x22, 0x87, 0x01, 0x0a, + 0x1b, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x79, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2c, 0x0a, 0x11, 0x49, 0x73, 0x53, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x11, 0x49, 0x73, 0x53, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x47, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x54, + 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x22, + 0xec, 0x01, 0x0a, 0x18, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x72, 0x65, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, + 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x4e, 0x53, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x44, 0x4e, 0x53, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x53, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x10, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, + 0x61, 0x74, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x41, + 0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x6e, + 0x0a, 0x10, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61, 0x6e, 0x6f, 0x6d, 0x61, + 0x6c, 0x79, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6c, + 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x79, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x2e, + 0x0a, 0x13, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x9b, + 0x02, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x72, 0x73, + 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x66, 0x69, + 0x72, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, + 0x73, 0x65, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, + 0x53, 0x65, 0x65, 0x6e, 0x12, 0x58, 0x0a, 0x10, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, + 0x67, 0x73, 0x1a, 0x58, 0x0a, 0x13, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa0, 0x06, 0x0a, + 0x16, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x4c, 0x6f, 0x61, 0x64, 0x65, + 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0e, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x12, + 0x38, 0x0a, 0x17, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, + 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x17, 0x4c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x49, 0x6e, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x38, 0x0a, 0x08, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, + 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x4a, 0x0a, 0x0d, 0x4c, 0x61, 0x73, + 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, 0x61, + 0x6c, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0d, 0x4c, 0x61, 0x73, 0x74, 0x41, 0x6e, 0x6f, 0x6d, + 0x61, 0x6c, 0x69, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, + 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x06, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x06, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x0b, 0x20, + 0x03, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x33, 0x0a, + 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x72, 0x65, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x53, 0x74, 0x61, + 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x47, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x5b, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, + 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x1a, + 0x5e, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0x3f, 0x0a, 0x19, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x0a, 0x0c, + 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0c, 0x49, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x22, 0x6b, 0x0a, 0x1a, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, + 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, + 0x19, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x53, 0x61, 0x76, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x38, 0x0a, 0x08, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x22, 0x46, 0x0a, 0x1a, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x32, 0x8a, 0x0a, 0x0a, + 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, + 0x3f, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x13, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, + 0x12, 0x57, 0x0a, 0x10, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x1a, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x44, 0x75, 0x6d, 0x70, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x09, 0x47, 0x65, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x30, 0x0a, 0x09, 0x47, 0x65, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x0b, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0b, + 0x52, 0x75, 0x6e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x52, 0x75, 0x6e, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x1a, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x53, 0x65, 0x6c, 0x66, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x10, 0x47, 0x65, 0x74, + 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1b, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x22, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x47, 0x65, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x53, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, + 0x12, 0x4f, 0x0a, 0x0e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, + 0x65, 0x73, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x20, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x00, 0x12, 0x5b, 0x0a, 0x14, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x49, + 0x0a, 0x0e, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, + 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, + 0x72, 0x64, 0x65, 0x72, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1a, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x44, 0x75, 0x6d, 0x70, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0c, 0x44, 0x75, 0x6d, + 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x50, + 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, + 0x6d, 0x70, 0x73, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, + 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, + 0x75, 0x6d, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, + 0x12, 0x4f, 0x0a, 0x10, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x44, 0x75, 0x6d, 0x70, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x6f, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x00, 0x12, 0x55, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x59, 0x0a, 0x14, - 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x13, 0x53, 0x61, 0x76, 0x65, 0x53, - 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x1e, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1f, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, - 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x00, 0x42, 0x18, 0x5a, 0x16, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, - 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x44, 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, + 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x44, + 0x75, 0x6d, 0x70, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x22, 0x00, 0x30, 0x01, 0x12, 0x59, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1f, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, + 0x58, 0x0a, 0x13, 0x53, 0x61, 0x76, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x42, 0x18, 0x5a, 0x16, 0x70, 0x6b, 0x67, + 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/security/proto/api/api.proto b/pkg/security/proto/api/api.proto index 223c1a9d6f903..dc3e16fecb4b2 100644 --- a/pkg/security/proto/api/api.proto +++ b/pkg/security/proto/api/api.proto @@ -15,6 +15,7 @@ message SecurityEventMessage { message DumpProcessCacheParams { bool WithArgs = 1; + string Format = 2; } message SecurityDumpProcessCacheMessage { diff --git a/pkg/security/proto/api/api_vtproto.pb.go b/pkg/security/proto/api/api_vtproto.pb.go index f823e79e6186e..462ad4782938c 100644 --- a/pkg/security/proto/api/api_vtproto.pb.go +++ b/pkg/security/proto/api/api_vtproto.pb.go @@ -144,6 +144,13 @@ func (m *DumpProcessCacheParams) MarshalToSizedBufferVT(dAtA []byte) (int, error i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } + if len(m.Format) > 0 { + i -= len(m.Format) + copy(dAtA[i:], m.Format) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Format))) + i-- + dAtA[i] = 0x12 + } if m.WithArgs { i-- if m.WithArgs { @@ -2894,6 +2901,10 @@ func (m *DumpProcessCacheParams) SizeVT() (n int) { if m.WithArgs { n += 2 } + l = len(m.Format) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } n += len(m.unknownFields) return n } @@ -4221,6 +4232,38 @@ func (m *DumpProcessCacheParams) UnmarshalVT(dAtA []byte) error { } } m.WithArgs = bool(v != 0) + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Format = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) diff --git a/pkg/security/resolvers/process/resolver_ebpf.go b/pkg/security/resolvers/process/resolver_ebpf.go index 03f416b160338..a7620ae1ef627 100644 --- a/pkg/security/resolvers/process/resolver_ebpf.go +++ b/pkg/security/resolvers/process/resolver_ebpf.go @@ -939,9 +939,9 @@ func (p *EBPFResolver) resolveFromProcfs(pid uint32, maxDepth int) *model.Proces parent := p.resolveFromProcfs(ppid, maxDepth-1) if inserted && parent != nil { if parent.Equals(entry) { - entry.SetParentOfForkChild(parent) + entry.SetForkParent(parent) } else { - entry.SetAncestor(parent) + entry.SetExecParent(parent) } } } @@ -1260,7 +1260,6 @@ func (p *EBPFResolver) syncCache(proc *process.Process, filledProc *utils.Filled } entry = p.NewProcessCacheEntry(model.PIDContext{Pid: pid, Tid: pid}) - entry.IsThread = true // update the cache entry if err := p.enrichEventFromProc(entry, proc, filledProc); err != nil { @@ -1273,9 +1272,9 @@ func (p *EBPFResolver) syncCache(proc *process.Process, filledProc *utils.Filled parent := p.entryCache[entry.PPid] if parent != nil { if parent.Equals(entry) { - entry.SetParentOfForkChild(parent) + entry.SetForkParent(parent) } else { - entry.SetAncestor(parent) + entry.SetExecParent(parent) } } @@ -1309,35 +1308,49 @@ func (p *EBPFResolver) syncCache(proc *process.Process, filledProc *utils.Filled } // ToJSON return a json version of the cache -func (p *EBPFResolver) ToJSON() ([]byte, error) { +func (p *EBPFResolver) ToJSON(raw bool) ([]byte, error) { dump := struct { Entries []json.RawMessage }{} p.Walk(func(entry *model.ProcessCacheEntry) { - e := struct { - PID uint32 - PPID uint32 - Path string - Inode uint64 - MountID uint32 - Source string - ExecInode uint64 - IsThread bool - IsParentMissing bool - }{ - PID: entry.Pid, - PPID: entry.PPid, - Path: entry.FileEvent.PathnameStr, - Inode: entry.FileEvent.Inode, - MountID: entry.FileEvent.MountID, - Source: model.ProcessSourceToString(entry.Source), - ExecInode: entry.ExecInode, - IsThread: entry.IsThread, - IsParentMissing: entry.IsParentMissing, + var ( + d []byte + err error + ) + + if raw { + d, err = json.Marshal(entry) + } else { + e := struct { + PID uint32 + PPID uint32 + Path string + Inode uint64 + MountID uint32 + Source string + ExecInode uint64 + IsExec bool + IsParentMissing bool + CGroup string + ContainerID string + }{ + PID: entry.Pid, + PPID: entry.PPid, + Path: entry.FileEvent.PathnameStr, + Inode: entry.FileEvent.Inode, + MountID: entry.FileEvent.MountID, + Source: model.ProcessSourceToString(entry.Source), + ExecInode: entry.ExecInode, + IsExec: entry.IsExec, + IsParentMissing: entry.IsParentMissing, + CGroup: string(entry.CGroup.CGroupID), + ContainerID: string(entry.ContainerID), + } + + d, err = json.Marshal(e) } - d, err := json.Marshal(e) if err == nil { dump.Entries = append(dump.Entries, d) } diff --git a/pkg/security/resolvers/process/resolver_ebpfless.go b/pkg/security/resolvers/process/resolver_ebpfless.go index 42cab69c5b5aa..474ba4dd66607 100644 --- a/pkg/security/resolvers/process/resolver_ebpfless.go +++ b/pkg/security/resolvers/process/resolver_ebpfless.go @@ -92,7 +92,6 @@ func (p *EBPFLessResolver) AddForkEntry(key CacheResolverKey, ppid uint32, ts ui entry.PIDContext.Pid = key.Pid entry.PPid = ppid entry.ForkTime = time.Unix(0, int64(ts)) - entry.IsThread = true entry.Source = model.ProcessCacheEntryFromEvent p.Lock() @@ -177,9 +176,9 @@ func (p *EBPFLessResolver) AddProcFSEntry(key CacheResolverKey, ppid uint32, fil parentKey := CacheResolverKey{NSID: key.NSID, Pid: ppid} if parent := p.entryCache[parentKey]; parent != nil { if parent.Equals(entry) { - entry.SetParentOfForkChild(parent) + entry.SetForkParent(parent) } else { - entry.SetAncestor(parent) + entry.SetExecParent(parent) } } p.insertEntry(key, entry, p.entryCache[key]) diff --git a/pkg/security/resolvers/process/resolver_test.go b/pkg/security/resolvers/process/resolver_test.go index ac4a3c15a30e9..5f9ddf59eff45 100644 --- a/pkg/security/resolvers/process/resolver_test.go +++ b/pkg/security/resolvers/process/resolver_test.go @@ -662,16 +662,16 @@ func TestIsExecExecRuntime(t *testing.T) { resolver.AddExecEntry(child3, 0) assert.False(t, parent.IsExecExec) - assert.False(t, parent.IsThread) // root node, no fork + assert.False(t, parent.IsExec) assert.False(t, child.IsExecExec) - assert.True(t, child.IsThread) + assert.False(t, child.IsExec) assert.False(t, child2.IsExecExec) - assert.False(t, child2.IsThread) + assert.True(t, child2.IsExec) assert.True(t, child3.IsExecExec) - assert.False(t, child3.IsThread) + assert.True(t, child3.IsExec) child4 := resolver.NewProcessCacheEntry(model.PIDContext{Pid: 2, Tid: 2}) child4.FileEvent.Inode = 3 @@ -679,7 +679,7 @@ func TestIsExecExecRuntime(t *testing.T) { resolver.AddExecEntry(child4, 0) assert.True(t, child3.IsExecExec) - assert.False(t, child3.IsThread) + assert.True(t, child3.IsExec) } func TestIsExecExecSnapshot(t *testing.T) { @@ -691,7 +691,6 @@ func TestIsExecExecSnapshot(t *testing.T) { parent := resolver.NewProcessCacheEntry(model.PIDContext{Pid: 1, Tid: 1}) parent.ForkTime = time.Now() parent.FileEvent.Inode = 1 - parent.IsThread = true // parent resolver.insertEntry(parent, nil, model.ProcessCacheEntryFromSnapshot) @@ -699,7 +698,6 @@ func TestIsExecExecSnapshot(t *testing.T) { child := resolver.NewProcessCacheEntry(model.PIDContext{Pid: 2, Tid: 2}) child.PPid = parent.Pid child.FileEvent.Inode = 2 - child.IsThread = true // parent // \ child @@ -708,10 +706,10 @@ func TestIsExecExecSnapshot(t *testing.T) { resolver.insertEntry(child, nil, model.ProcessCacheEntryFromSnapshot) assert.False(t, parent.IsExecExec) - assert.True(t, parent.IsThread) // root node, no fork + assert.False(t, parent.IsExec) assert.False(t, child.IsExecExec) - assert.True(t, child.IsThread) + assert.False(t, child.IsExec) // parent // \ child @@ -723,7 +721,7 @@ func TestIsExecExecSnapshot(t *testing.T) { resolver.AddExecEntry(child2, 0) assert.False(t, child2.IsExecExec) - assert.False(t, child2.IsThread) + assert.True(t, child2.IsExec) child3 := resolver.NewProcessCacheEntry(model.PIDContext{Pid: 2, Tid: 2}) child3.FileEvent.Inode = 4 @@ -731,5 +729,5 @@ func TestIsExecExecSnapshot(t *testing.T) { resolver.AddExecEntry(child3, 0) assert.True(t, child3.IsExecExec) - assert.False(t, child3.IsThread) + assert.True(t, child3.IsExec) } diff --git a/pkg/security/rules/engine.go b/pkg/security/rules/engine.go index 00ad1233946d1..fbe77c6ad462a 100644 --- a/pkg/security/rules/engine.go +++ b/pkg/security/rules/engine.go @@ -168,7 +168,6 @@ func (e *RuleEngine) Start(ctx context.Context, reloadChan <-chan struct{}, wg * if err := e.ReloadPolicies(); err != nil { seclog.Errorf("failed to reload policies: %s", err) } - e.probe.PlaySnapshot() } }() diff --git a/pkg/security/secl/compiler/ast/secl.go b/pkg/security/secl/compiler/ast/secl.go index fbe4013a8c545..946c483173b54 100644 --- a/pkg/security/secl/compiler/ast/secl.go +++ b/pkg/security/secl/compiler/ast/secl.go @@ -21,10 +21,12 @@ import ( type ParsingContext struct { ruleParser *participle.Parser macroParser *participle.Parser + + ruleCache map[string]*Rule } // NewParsingContext returns a new parsing context -func NewParsingContext() *ParsingContext { +func NewParsingContext(withRuleCache bool) *ParsingContext { seclLexer := lexer.Must(ebnf.New(` Comment = ("#" | "//") { "\u0000"…"\uffff"-"\n" } . CIDR = IP "/" digit { digit } . @@ -46,9 +48,15 @@ digit = "0"…"9" . any = "\u0000"…"\uffff" . `)) + var ruleCache map[string]*Rule + if withRuleCache { + ruleCache = make(map[string]*Rule) + } + return &ParsingContext{ ruleParser: buildParser(&Rule{}, seclLexer), macroParser: buildParser(&Macro{}, seclLexer), + ruleCache: ruleCache, } } @@ -93,6 +101,12 @@ func parseDuration(t lexer.Token) (lexer.Token, error) { // ParseRule parses a SECL rule. func (pc *ParsingContext) ParseRule(expr string) (*Rule, error) { + if pc.ruleCache != nil { + if ast, ok := pc.ruleCache[expr]; ok { + return ast, nil + } + } + rule := &Rule{} err := pc.ruleParser.Parse(bytes.NewBufferString(expr), rule) if err != nil { @@ -100,6 +114,10 @@ func (pc *ParsingContext) ParseRule(expr string) (*Rule, error) { } rule.Expr = expr + if pc.ruleCache != nil { + pc.ruleCache[expr] = rule + } + return rule, nil } diff --git a/pkg/security/secl/compiler/ast/secl_test.go b/pkg/security/secl/compiler/ast/secl_test.go index b559778270215..b59ef9d644020 100644 --- a/pkg/security/secl/compiler/ast/secl_test.go +++ b/pkg/security/secl/compiler/ast/secl_test.go @@ -12,12 +12,12 @@ import ( ) func parseRule(rule string) (*Rule, error) { - pc := NewParsingContext() + pc := NewParsingContext(false) return pc.ParseRule(rule) } func parseMacro(macro string) (*Macro, error) { - pc := NewParsingContext() + pc := NewParsingContext(false) return pc.ParseMacro(macro) } diff --git a/pkg/security/secl/compiler/eval/eval_test.go b/pkg/security/secl/compiler/eval/eval_test.go index 86dd87126133d..0674e4ef744b1 100644 --- a/pkg/security/secl/compiler/eval/eval_test.go +++ b/pkg/security/secl/compiler/eval/eval_test.go @@ -41,7 +41,7 @@ func newOptsWithParams(constants map[string]interface{}, legacyFields map[Field] func parseRule(expr string, model Model, opts *Opts) (*Rule, error) { rule := NewRule("id1", expr, opts) - pc := ast.NewParsingContext() + pc := ast.NewParsingContext(false) if err := rule.Parse(pc); err != nil { return nil, fmt.Errorf("parsing error: %v", err) @@ -608,7 +608,7 @@ func TestConstants(t *testing.T) { func TestMacroList(t *testing.T) { model := &testModel{} - pc := ast.NewParsingContext() + pc := ast.NewParsingContext(false) opts := newOptsWithParams(make(map[string]interface{}), nil) macro, err := NewMacro( @@ -638,7 +638,7 @@ func TestMacroList(t *testing.T) { func TestMacroExpression(t *testing.T) { model := &testModel{} - pc := ast.NewParsingContext() + pc := ast.NewParsingContext(false) opts := newOptsWithParams(make(map[string]interface{}), nil) macro, err := NewMacro( @@ -677,7 +677,7 @@ func TestMacroExpression(t *testing.T) { func TestMacroPartial(t *testing.T) { model := &testModel{} - pc := ast.NewParsingContext() + pc := ast.NewParsingContext(false) opts := newOptsWithParams(make(map[string]interface{}), nil) macro, err := NewMacro( @@ -738,7 +738,7 @@ func TestNestedMacros(t *testing.T) { } model := &testModel{} - pc := ast.NewParsingContext() + pc := ast.NewParsingContext(false) opts := newOptsWithParams(make(map[string]interface{}), nil) macro1, err := NewMacro( @@ -1559,7 +1559,7 @@ func BenchmarkPartial(b *testing.B) { b.Fatal(err) } - pc := ast.NewParsingContext() + pc := ast.NewParsingContext(false) if err := rule.GenEvaluator(model, pc); err != nil { b.Fatal(err) } diff --git a/pkg/security/secl/go.sum b/pkg/security/secl/go.sum index 478b6c14eec12..f060300e2a96f 100644 --- a/pkg/security/secl/go.sum +++ b/pkg/security/secl/go.sum @@ -81,6 +81,8 @@ golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= diff --git a/pkg/security/secl/model/accessors_unix.go b/pkg/security/secl/model/accessors_unix.go index 1b4a61d764a83..edbd810554799 100644 --- a/pkg/security/secl/model/accessors_unix.go +++ b/pkg/security/secl/model/accessors_unix.go @@ -27,6 +27,7 @@ func (m *Model) GetEventTypes() []eval.EventType { eval.EventType("chdir"), eval.EventType("chmod"), eval.EventType("chown"), + eval.EventType("connect"), eval.EventType("dns"), eval.EventType("exec"), eval.EventType("exit"), @@ -940,6 +941,69 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: 900 * eval.HandlerWeight, }, nil + case "connect.addr.family": + return &eval.IntEvaluator{ + EvalFnc: func(ctx *eval.Context) int { + ev := ctx.Event.(*Event) + return int(ev.Connect.AddrFamily) + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil + case "connect.addr.ip": + return &eval.CIDREvaluator{ + EvalFnc: func(ctx *eval.Context) net.IPNet { + ev := ctx.Event.(*Event) + return ev.Connect.Addr.IPNet + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil + case "connect.addr.port": + return &eval.IntEvaluator{ + EvalFnc: func(ctx *eval.Context) int { + ev := ctx.Event.(*Event) + return int(ev.Connect.Addr.Port) + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil + case "connect.retval": + return &eval.IntEvaluator{ + EvalFnc: func(ctx *eval.Context) int { + ev := ctx.Event.(*Event) + return int(ev.Connect.SyscallEvent.Retval) + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil + case "connect.server.addr.family": + return &eval.IntEvaluator{ + EvalFnc: func(ctx *eval.Context) int { + ev := ctx.Event.(*Event) + return int(ev.Connect.AddrFamily) + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil + case "connect.server.addr.ip": + return &eval.CIDREvaluator{ + EvalFnc: func(ctx *eval.Context) net.IPNet { + ev := ctx.Event.(*Event) + return ev.Connect.Addr.IPNet + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil + case "connect.server.addr.port": + return &eval.IntEvaluator{ + EvalFnc: func(ctx *eval.Context) int { + ev := ctx.Event.(*Event) + return int(ev.Connect.Addr.Port) + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "container.created_at": return &eval.IntEvaluator{ EvalFnc: func(ctx *eval.Context) int { @@ -1832,6 +1896,15 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: eval.HandlerWeight, }, nil + case "exec.is_exec": + return &eval.BoolEvaluator{ + EvalFnc: func(ctx *eval.Context) bool { + ev := ctx.Event.(*Event) + return ev.Exec.Process.IsExec + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "exec.is_kworker": return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { @@ -1845,10 +1918,10 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { ev := ctx.Event.(*Event) - return ev.Exec.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Exec.Process) }, Field: field, - Weight: eval.FunctionWeight, + Weight: eval.HandlerWeight, }, nil case "exec.pid": return &eval.IntEvaluator{ @@ -2695,6 +2768,15 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: eval.HandlerWeight, }, nil + case "exit.is_exec": + return &eval.BoolEvaluator{ + EvalFnc: func(ctx *eval.Context) bool { + ev := ctx.Event.(*Event) + return ev.Exit.Process.IsExec + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "exit.is_kworker": return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { @@ -2708,10 +2790,10 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { ev := ctx.Event.(*Event) - return ev.Exit.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Exit.Process) }, Field: field, - Weight: eval.FunctionWeight, + Weight: eval.HandlerWeight, }, nil case "exit.pid": return &eval.IntEvaluator{ @@ -4438,6 +4520,16 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: eval.HandlerWeight, }, nil + case "packet.filter": + return &eval.StringEvaluator{ + OpOverrides: PacketFilterMatching, + EvalFnc: func(ctx *eval.Context) string { + ev := ctx.Event.(*Event) + return ev.RawPacket.Filter + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "packet.l3_protocol": return &eval.IntEvaluator{ EvalFnc: func(ctx *eval.Context) int { @@ -6897,6 +6989,36 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval }, Field: field, Weight: eval.IteratorWeight, }, nil + case "process.ancestors.is_exec": + return &eval.BoolArrayEvaluator{ + EvalFnc: func(ctx *eval.Context) []bool { + if result, ok := ctx.BoolCache[field]; ok { + return result + } + var results []bool + iterator := &ProcessAncestorsIterator{} + if regID != "" { + value := iterator.At(ctx, regID, ctx.Registers[regID]) + if value == nil { + return results + } + element := value + result := element.ProcessContext.Process.IsExec + results = append(results, result) + return results + } + value := iterator.Front(ctx) + for value != nil { + element := value + result := element.ProcessContext.Process.IsExec + results = append(results, result) + value = iterator.Next() + } + ctx.BoolCache[field] = results + return results + }, Field: field, + Weight: eval.IteratorWeight, + }, nil case "process.ancestors.is_kworker": return &eval.BoolArrayEvaluator{ EvalFnc: func(ctx *eval.Context) []bool { @@ -6930,6 +7052,7 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval case "process.ancestors.is_thread": return &eval.BoolArrayEvaluator{ EvalFnc: func(ctx *eval.Context) []bool { + ev := ctx.Event.(*Event) if result, ok := ctx.BoolCache[field]; ok { return result } @@ -6941,14 +7064,14 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval return results } element := value - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) results = append(results, result) return results } value := iterator.Front(ctx) for value != nil { element := value - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) results = append(results, result) value = iterator.Next() } @@ -7976,6 +8099,15 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: eval.HandlerWeight, }, nil + case "process.is_exec": + return &eval.BoolEvaluator{ + EvalFnc: func(ctx *eval.Context) bool { + ev := ctx.Event.(*Event) + return ev.BaseEvent.ProcessContext.Process.IsExec + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "process.is_kworker": return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { @@ -7989,10 +8121,10 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { ev := ctx.Event.(*Event) - return ev.BaseEvent.ProcessContext.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.BaseEvent.ProcessContext.Process) }, Field: field, - Weight: eval.FunctionWeight, + Weight: eval.HandlerWeight, }, nil case "process.parent.args": return &eval.StringEvaluator{ @@ -8926,6 +9058,18 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: eval.HandlerWeight, }, nil + case "process.parent.is_exec": + return &eval.BoolEvaluator{ + EvalFnc: func(ctx *eval.Context) bool { + ev := ctx.Event.(*Event) + if !ev.BaseEvent.ProcessContext.HasParent() { + return false + } + return ev.BaseEvent.ProcessContext.Parent.IsExec + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "process.parent.is_kworker": return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { @@ -8945,10 +9089,10 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval if !ev.BaseEvent.ProcessContext.HasParent() { return false } - return ev.BaseEvent.ProcessContext.Parent.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.BaseEvent.ProcessContext.Parent) }, Field: field, - Weight: eval.FunctionWeight, + Weight: eval.HandlerWeight, }, nil case "process.parent.pid": return &eval.IntEvaluator{ @@ -11562,6 +11706,36 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval }, Field: field, Weight: eval.IteratorWeight, }, nil + case "ptrace.tracee.ancestors.is_exec": + return &eval.BoolArrayEvaluator{ + EvalFnc: func(ctx *eval.Context) []bool { + if result, ok := ctx.BoolCache[field]; ok { + return result + } + var results []bool + iterator := &ProcessAncestorsIterator{} + if regID != "" { + value := iterator.At(ctx, regID, ctx.Registers[regID]) + if value == nil { + return results + } + element := value + result := element.ProcessContext.Process.IsExec + results = append(results, result) + return results + } + value := iterator.Front(ctx) + for value != nil { + element := value + result := element.ProcessContext.Process.IsExec + results = append(results, result) + value = iterator.Next() + } + ctx.BoolCache[field] = results + return results + }, Field: field, + Weight: eval.IteratorWeight, + }, nil case "ptrace.tracee.ancestors.is_kworker": return &eval.BoolArrayEvaluator{ EvalFnc: func(ctx *eval.Context) []bool { @@ -11595,6 +11769,7 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval case "ptrace.tracee.ancestors.is_thread": return &eval.BoolArrayEvaluator{ EvalFnc: func(ctx *eval.Context) []bool { + ev := ctx.Event.(*Event) if result, ok := ctx.BoolCache[field]; ok { return result } @@ -11606,14 +11781,14 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval return results } element := value - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) results = append(results, result) return results } value := iterator.Front(ctx) for value != nil { element := value - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) results = append(results, result) value = iterator.Next() } @@ -12641,6 +12816,15 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: eval.HandlerWeight, }, nil + case "ptrace.tracee.is_exec": + return &eval.BoolEvaluator{ + EvalFnc: func(ctx *eval.Context) bool { + ev := ctx.Event.(*Event) + return ev.PTrace.Tracee.Process.IsExec + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "ptrace.tracee.is_kworker": return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { @@ -12654,10 +12838,10 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { ev := ctx.Event.(*Event) - return ev.PTrace.Tracee.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.PTrace.Tracee.Process) }, Field: field, - Weight: eval.FunctionWeight, + Weight: eval.HandlerWeight, }, nil case "ptrace.tracee.parent.args": return &eval.StringEvaluator{ @@ -13591,6 +13775,18 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: eval.HandlerWeight, }, nil + case "ptrace.tracee.parent.is_exec": + return &eval.BoolEvaluator{ + EvalFnc: func(ctx *eval.Context) bool { + ev := ctx.Event.(*Event) + if !ev.PTrace.Tracee.HasParent() { + return false + } + return ev.PTrace.Tracee.Parent.IsExec + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "ptrace.tracee.parent.is_kworker": return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { @@ -13610,10 +13806,10 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval if !ev.PTrace.Tracee.HasParent() { return false } - return ev.PTrace.Tracee.Parent.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.PTrace.Tracee.Parent) }, Field: field, - Weight: eval.FunctionWeight, + Weight: eval.HandlerWeight, }, nil case "ptrace.tracee.parent.pid": return &eval.IntEvaluator{ @@ -17381,6 +17577,36 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval }, Field: field, Weight: eval.IteratorWeight, }, nil + case "signal.target.ancestors.is_exec": + return &eval.BoolArrayEvaluator{ + EvalFnc: func(ctx *eval.Context) []bool { + if result, ok := ctx.BoolCache[field]; ok { + return result + } + var results []bool + iterator := &ProcessAncestorsIterator{} + if regID != "" { + value := iterator.At(ctx, regID, ctx.Registers[regID]) + if value == nil { + return results + } + element := value + result := element.ProcessContext.Process.IsExec + results = append(results, result) + return results + } + value := iterator.Front(ctx) + for value != nil { + element := value + result := element.ProcessContext.Process.IsExec + results = append(results, result) + value = iterator.Next() + } + ctx.BoolCache[field] = results + return results + }, Field: field, + Weight: eval.IteratorWeight, + }, nil case "signal.target.ancestors.is_kworker": return &eval.BoolArrayEvaluator{ EvalFnc: func(ctx *eval.Context) []bool { @@ -17414,6 +17640,7 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval case "signal.target.ancestors.is_thread": return &eval.BoolArrayEvaluator{ EvalFnc: func(ctx *eval.Context) []bool { + ev := ctx.Event.(*Event) if result, ok := ctx.BoolCache[field]; ok { return result } @@ -17425,14 +17652,14 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval return results } element := value - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) results = append(results, result) return results } value := iterator.Front(ctx) for value != nil { element := value - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) results = append(results, result) value = iterator.Next() } @@ -18460,6 +18687,15 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: eval.HandlerWeight, }, nil + case "signal.target.is_exec": + return &eval.BoolEvaluator{ + EvalFnc: func(ctx *eval.Context) bool { + ev := ctx.Event.(*Event) + return ev.Signal.Target.Process.IsExec + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "signal.target.is_kworker": return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { @@ -18473,10 +18709,10 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { ev := ctx.Event.(*Event) - return ev.Signal.Target.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.Signal.Target.Process) }, Field: field, - Weight: eval.FunctionWeight, + Weight: eval.HandlerWeight, }, nil case "signal.target.parent.args": return &eval.StringEvaluator{ @@ -19410,6 +19646,18 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval Field: field, Weight: eval.HandlerWeight, }, nil + case "signal.target.parent.is_exec": + return &eval.BoolEvaluator{ + EvalFnc: func(ctx *eval.Context) bool { + ev := ctx.Event.(*Event) + if !ev.Signal.Target.HasParent() { + return false + } + return ev.Signal.Target.Parent.IsExec + }, + Field: field, + Weight: eval.FunctionWeight, + }, nil case "signal.target.parent.is_kworker": return &eval.BoolEvaluator{ EvalFnc: func(ctx *eval.Context) bool { @@ -19429,10 +19677,10 @@ func (m *Model) GetEvaluator(field eval.Field, regID eval.RegisterID) (eval.Eval if !ev.Signal.Target.HasParent() { return false } - return ev.Signal.Target.Parent.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Signal.Target.Parent) }, Field: field, - Weight: eval.FunctionWeight, + Weight: eval.HandlerWeight, }, nil case "signal.target.parent.pid": return &eval.IntEvaluator{ @@ -20391,6 +20639,13 @@ func (ev *Event) GetFields() []eval.Field { "chown.syscall.gid", "chown.syscall.path", "chown.syscall.uid", + "connect.addr.family", + "connect.addr.ip", + "connect.addr.port", + "connect.retval", + "connect.server.addr.family", + "connect.server.addr.ip", + "connect.server.addr.port", "container.created_at", "container.id", "container.runtime", @@ -20477,6 +20732,7 @@ func (ev *Event) GetFields() []eval.Field { "exec.interpreter.file.rights", "exec.interpreter.file.uid", "exec.interpreter.file.user", + "exec.is_exec", "exec.is_kworker", "exec.is_thread", "exec.pid", @@ -20560,6 +20816,7 @@ func (ev *Event) GetFields() []eval.Field { "exit.interpreter.file.rights", "exit.interpreter.file.uid", "exit.interpreter.file.user", + "exit.is_exec", "exit.is_kworker", "exit.is_thread", "exit.pid", @@ -20751,6 +21008,7 @@ func (ev *Event) GetFields() []eval.Field { "packet.destination.ip", "packet.destination.port", "packet.device.ifname", + "packet.filter", "packet.l3_protocol", "packet.l4_protocol", "packet.size", @@ -20826,6 +21084,7 @@ func (ev *Event) GetFields() []eval.Field { "process.ancestors.interpreter.file.rights", "process.ancestors.interpreter.file.uid", "process.ancestors.interpreter.file.user", + "process.ancestors.is_exec", "process.ancestors.is_kworker", "process.ancestors.is_thread", "process.ancestors.length", @@ -20907,6 +21166,7 @@ func (ev *Event) GetFields() []eval.Field { "process.interpreter.file.rights", "process.interpreter.file.uid", "process.interpreter.file.user", + "process.is_exec", "process.is_kworker", "process.is_thread", "process.parent.args", @@ -20978,6 +21238,7 @@ func (ev *Event) GetFields() []eval.Field { "process.parent.interpreter.file.rights", "process.parent.interpreter.file.uid", "process.parent.interpreter.file.user", + "process.parent.is_exec", "process.parent.is_kworker", "process.parent.is_thread", "process.parent.pid", @@ -21069,6 +21330,7 @@ func (ev *Event) GetFields() []eval.Field { "ptrace.tracee.ancestors.interpreter.file.rights", "ptrace.tracee.ancestors.interpreter.file.uid", "ptrace.tracee.ancestors.interpreter.file.user", + "ptrace.tracee.ancestors.is_exec", "ptrace.tracee.ancestors.is_kworker", "ptrace.tracee.ancestors.is_thread", "ptrace.tracee.ancestors.length", @@ -21150,6 +21412,7 @@ func (ev *Event) GetFields() []eval.Field { "ptrace.tracee.interpreter.file.rights", "ptrace.tracee.interpreter.file.uid", "ptrace.tracee.interpreter.file.user", + "ptrace.tracee.is_exec", "ptrace.tracee.is_kworker", "ptrace.tracee.is_thread", "ptrace.tracee.parent.args", @@ -21221,6 +21484,7 @@ func (ev *Event) GetFields() []eval.Field { "ptrace.tracee.parent.interpreter.file.rights", "ptrace.tracee.parent.interpreter.file.uid", "ptrace.tracee.parent.interpreter.file.user", + "ptrace.tracee.parent.is_exec", "ptrace.tracee.parent.is_kworker", "ptrace.tracee.parent.is_thread", "ptrace.tracee.parent.pid", @@ -21438,6 +21702,7 @@ func (ev *Event) GetFields() []eval.Field { "signal.target.ancestors.interpreter.file.rights", "signal.target.ancestors.interpreter.file.uid", "signal.target.ancestors.interpreter.file.user", + "signal.target.ancestors.is_exec", "signal.target.ancestors.is_kworker", "signal.target.ancestors.is_thread", "signal.target.ancestors.length", @@ -21519,6 +21784,7 @@ func (ev *Event) GetFields() []eval.Field { "signal.target.interpreter.file.rights", "signal.target.interpreter.file.uid", "signal.target.interpreter.file.user", + "signal.target.is_exec", "signal.target.is_kworker", "signal.target.is_thread", "signal.target.parent.args", @@ -21590,6 +21856,7 @@ func (ev *Event) GetFields() []eval.Field { "signal.target.parent.interpreter.file.rights", "signal.target.parent.interpreter.file.uid", "signal.target.parent.interpreter.file.user", + "signal.target.parent.is_exec", "signal.target.parent.is_kworker", "signal.target.parent.is_thread", "signal.target.parent.pid", @@ -21879,6 +22146,20 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return ev.FieldHandlers.ResolveSyscallCtxArgsStr1(ev, &ev.Chown.SyscallContext), nil case "chown.syscall.uid": return int(ev.FieldHandlers.ResolveSyscallCtxArgsInt2(ev, &ev.Chown.SyscallContext)), nil + case "connect.addr.family": + return int(ev.Connect.AddrFamily), nil + case "connect.addr.ip": + return ev.Connect.Addr.IPNet, nil + case "connect.addr.port": + return int(ev.Connect.Addr.Port), nil + case "connect.retval": + return int(ev.Connect.SyscallEvent.Retval), nil + case "connect.server.addr.family": + return int(ev.Connect.AddrFamily), nil + case "connect.server.addr.ip": + return ev.Connect.Addr.IPNet, nil + case "connect.server.addr.port": + return int(ev.Connect.Addr.Port), nil case "container.created_at": return int(ev.FieldHandlers.ResolveContainerCreatedAt(ev, ev.BaseEvent.ContainerContext)), nil case "container.id": @@ -22159,10 +22440,12 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return "", &eval.ErrNotSupported{Field: field} } return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Exec.Process.LinuxBinprm.FileEvent.FileFields), nil + case "exec.is_exec": + return ev.Exec.Process.IsExec, nil case "exec.is_kworker": return ev.Exec.Process.PIDContext.IsKworker, nil case "exec.is_thread": - return ev.Exec.Process.IsThread, nil + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Exec.Process), nil case "exec.pid": return int(ev.Exec.Process.PIDContext.Pid), nil case "exec.ppid": @@ -22433,10 +22716,12 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return "", &eval.ErrNotSupported{Field: field} } return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Exit.Process.LinuxBinprm.FileEvent.FileFields), nil + case "exit.is_exec": + return ev.Exit.Process.IsExec, nil case "exit.is_kworker": return ev.Exit.Process.PIDContext.IsKworker, nil case "exit.is_thread": - return ev.Exit.Process.IsThread, nil + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Exit.Process), nil case "exit.pid": return int(ev.Exit.Process.PIDContext.Pid), nil case "exit.ppid": @@ -22815,6 +23100,8 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return int(ev.RawPacket.NetworkContext.Destination.Port), nil case "packet.device.ifname": return ev.FieldHandlers.ResolveNetworkDeviceIfName(ev, &ev.RawPacket.NetworkContext.Device), nil + case "packet.filter": + return ev.RawPacket.Filter, nil case "packet.l3_protocol": return int(ev.RawPacket.NetworkContext.L3Protocol), nil case "packet.l4_protocol": @@ -23615,6 +23902,18 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { ptr = iterator.Next() } return values, nil + case "process.ancestors.is_exec": + var values []bool + ctx := eval.NewContext(ev) + iterator := &ProcessAncestorsIterator{} + ptr := iterator.Front(ctx) + for ptr != nil { + element := ptr + result := element.ProcessContext.Process.IsExec + values = append(values, result) + ptr = iterator.Next() + } + return values, nil case "process.ancestors.is_kworker": var values []bool ctx := eval.NewContext(ev) @@ -23634,7 +23933,7 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { ptr := iterator.Front(ctx) for ptr != nil { element := ptr - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) values = append(values, result) ptr = iterator.Next() } @@ -23997,10 +24296,12 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return "", &eval.ErrNotSupported{Field: field} } return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.BaseEvent.ProcessContext.Process.LinuxBinprm.FileEvent.FileFields), nil + case "process.is_exec": + return ev.BaseEvent.ProcessContext.Process.IsExec, nil case "process.is_kworker": return ev.BaseEvent.ProcessContext.Process.PIDContext.IsKworker, nil case "process.is_thread": - return ev.BaseEvent.ProcessContext.Process.IsThread, nil + return ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.BaseEvent.ProcessContext.Process), nil case "process.parent.args": if !ev.BaseEvent.ProcessContext.HasParent() { return "", &eval.ErrNotSupported{Field: field} @@ -24442,6 +24743,11 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return "", &eval.ErrNotSupported{Field: field} } return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.BaseEvent.ProcessContext.Parent.LinuxBinprm.FileEvent.FileFields), nil + case "process.parent.is_exec": + if !ev.BaseEvent.ProcessContext.HasParent() { + return false, &eval.ErrNotSupported{Field: field} + } + return ev.BaseEvent.ProcessContext.Parent.IsExec, nil case "process.parent.is_kworker": if !ev.BaseEvent.ProcessContext.HasParent() { return false, &eval.ErrNotSupported{Field: field} @@ -24451,7 +24757,7 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { if !ev.BaseEvent.ProcessContext.HasParent() { return false, &eval.ErrNotSupported{Field: field} } - return ev.BaseEvent.ProcessContext.Parent.IsThread, nil + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.BaseEvent.ProcessContext.Parent), nil case "process.parent.pid": if !ev.BaseEvent.ProcessContext.HasParent() { return 0, &eval.ErrNotSupported{Field: field} @@ -25307,6 +25613,18 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { ptr = iterator.Next() } return values, nil + case "ptrace.tracee.ancestors.is_exec": + var values []bool + ctx := eval.NewContext(ev) + iterator := &ProcessAncestorsIterator{} + ptr := iterator.Front(ctx) + for ptr != nil { + element := ptr + result := element.ProcessContext.Process.IsExec + values = append(values, result) + ptr = iterator.Next() + } + return values, nil case "ptrace.tracee.ancestors.is_kworker": var values []bool ctx := eval.NewContext(ev) @@ -25326,7 +25644,7 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { ptr := iterator.Front(ctx) for ptr != nil { element := ptr - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) values = append(values, result) ptr = iterator.Next() } @@ -25689,10 +26007,12 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return "", &eval.ErrNotSupported{Field: field} } return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.PTrace.Tracee.Process.LinuxBinprm.FileEvent.FileFields), nil + case "ptrace.tracee.is_exec": + return ev.PTrace.Tracee.Process.IsExec, nil case "ptrace.tracee.is_kworker": return ev.PTrace.Tracee.Process.PIDContext.IsKworker, nil case "ptrace.tracee.is_thread": - return ev.PTrace.Tracee.Process.IsThread, nil + return ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.PTrace.Tracee.Process), nil case "ptrace.tracee.parent.args": if !ev.PTrace.Tracee.HasParent() { return "", &eval.ErrNotSupported{Field: field} @@ -26134,6 +26454,11 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return "", &eval.ErrNotSupported{Field: field} } return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.PTrace.Tracee.Parent.LinuxBinprm.FileEvent.FileFields), nil + case "ptrace.tracee.parent.is_exec": + if !ev.PTrace.Tracee.HasParent() { + return false, &eval.ErrNotSupported{Field: field} + } + return ev.PTrace.Tracee.Parent.IsExec, nil case "ptrace.tracee.parent.is_kworker": if !ev.PTrace.Tracee.HasParent() { return false, &eval.ErrNotSupported{Field: field} @@ -26143,7 +26468,7 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { if !ev.PTrace.Tracee.HasParent() { return false, &eval.ErrNotSupported{Field: field} } - return ev.PTrace.Tracee.Parent.IsThread, nil + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.PTrace.Tracee.Parent), nil case "ptrace.tracee.parent.pid": if !ev.PTrace.Tracee.HasParent() { return 0, &eval.ErrNotSupported{Field: field} @@ -27251,6 +27576,18 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { ptr = iterator.Next() } return values, nil + case "signal.target.ancestors.is_exec": + var values []bool + ctx := eval.NewContext(ev) + iterator := &ProcessAncestorsIterator{} + ptr := iterator.Front(ctx) + for ptr != nil { + element := ptr + result := element.ProcessContext.Process.IsExec + values = append(values, result) + ptr = iterator.Next() + } + return values, nil case "signal.target.ancestors.is_kworker": var values []bool ctx := eval.NewContext(ev) @@ -27270,7 +27607,7 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { ptr := iterator.Front(ctx) for ptr != nil { element := ptr - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) values = append(values, result) ptr = iterator.Next() } @@ -27633,10 +27970,12 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return "", &eval.ErrNotSupported{Field: field} } return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Signal.Target.Process.LinuxBinprm.FileEvent.FileFields), nil + case "signal.target.is_exec": + return ev.Signal.Target.Process.IsExec, nil case "signal.target.is_kworker": return ev.Signal.Target.Process.PIDContext.IsKworker, nil case "signal.target.is_thread": - return ev.Signal.Target.Process.IsThread, nil + return ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.Signal.Target.Process), nil case "signal.target.parent.args": if !ev.Signal.Target.HasParent() { return "", &eval.ErrNotSupported{Field: field} @@ -28078,6 +28417,11 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { return "", &eval.ErrNotSupported{Field: field} } return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Signal.Target.Parent.LinuxBinprm.FileEvent.FileFields), nil + case "signal.target.parent.is_exec": + if !ev.Signal.Target.HasParent() { + return false, &eval.ErrNotSupported{Field: field} + } + return ev.Signal.Target.Parent.IsExec, nil case "signal.target.parent.is_kworker": if !ev.Signal.Target.HasParent() { return false, &eval.ErrNotSupported{Field: field} @@ -28087,7 +28431,7 @@ func (ev *Event) GetFieldValue(field eval.Field) (interface{}, error) { if !ev.Signal.Target.HasParent() { return false, &eval.ErrNotSupported{Field: field} } - return ev.Signal.Target.Parent.IsThread, nil + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Signal.Target.Parent), nil case "signal.target.parent.pid": if !ev.Signal.Target.HasParent() { return 0, &eval.ErrNotSupported{Field: field} @@ -28490,6 +28834,20 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "chown", nil case "chown.syscall.uid": return "chown", nil + case "connect.addr.family": + return "connect", nil + case "connect.addr.ip": + return "connect", nil + case "connect.addr.port": + return "connect", nil + case "connect.retval": + return "connect", nil + case "connect.server.addr.family": + return "connect", nil + case "connect.server.addr.ip": + return "connect", nil + case "connect.server.addr.port": + return "connect", nil case "container.created_at": return "", nil case "container.id": @@ -28662,6 +29020,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "exec", nil case "exec.interpreter.file.user": return "exec", nil + case "exec.is_exec": + return "exec", nil case "exec.is_kworker": return "exec", nil case "exec.is_thread": @@ -28828,6 +29188,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "exit", nil case "exit.interpreter.file.user": return "exit", nil + case "exit.is_exec": + return "exit", nil case "exit.is_kworker": return "exit", nil case "exit.is_thread": @@ -29210,6 +29572,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "packet", nil case "packet.device.ifname": return "packet", nil + case "packet.filter": + return "packet", nil case "packet.l3_protocol": return "packet", nil case "packet.l4_protocol": @@ -29360,6 +29724,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "", nil case "process.ancestors.interpreter.file.user": return "", nil + case "process.ancestors.is_exec": + return "", nil case "process.ancestors.is_kworker": return "", nil case "process.ancestors.is_thread": @@ -29522,6 +29888,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "", nil case "process.interpreter.file.user": return "", nil + case "process.is_exec": + return "", nil case "process.is_kworker": return "", nil case "process.is_thread": @@ -29664,6 +30032,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "", nil case "process.parent.interpreter.file.user": return "", nil + case "process.parent.is_exec": + return "", nil case "process.parent.is_kworker": return "", nil case "process.parent.is_thread": @@ -29846,6 +30216,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "ptrace", nil case "ptrace.tracee.ancestors.interpreter.file.user": return "ptrace", nil + case "ptrace.tracee.ancestors.is_exec": + return "ptrace", nil case "ptrace.tracee.ancestors.is_kworker": return "ptrace", nil case "ptrace.tracee.ancestors.is_thread": @@ -30008,6 +30380,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "ptrace", nil case "ptrace.tracee.interpreter.file.user": return "ptrace", nil + case "ptrace.tracee.is_exec": + return "ptrace", nil case "ptrace.tracee.is_kworker": return "ptrace", nil case "ptrace.tracee.is_thread": @@ -30150,6 +30524,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "ptrace", nil case "ptrace.tracee.parent.interpreter.file.user": return "ptrace", nil + case "ptrace.tracee.parent.is_exec": + return "ptrace", nil case "ptrace.tracee.parent.is_kworker": return "ptrace", nil case "ptrace.tracee.parent.is_thread": @@ -30584,6 +30960,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "signal", nil case "signal.target.ancestors.interpreter.file.user": return "signal", nil + case "signal.target.ancestors.is_exec": + return "signal", nil case "signal.target.ancestors.is_kworker": return "signal", nil case "signal.target.ancestors.is_thread": @@ -30746,6 +31124,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "signal", nil case "signal.target.interpreter.file.user": return "signal", nil + case "signal.target.is_exec": + return "signal", nil case "signal.target.is_kworker": return "signal", nil case "signal.target.is_thread": @@ -30888,6 +31268,8 @@ func (ev *Event) GetFieldEventType(field eval.Field) (eval.EventType, error) { return "signal", nil case "signal.target.parent.interpreter.file.user": return "signal", nil + case "signal.target.parent.is_exec": + return "signal", nil case "signal.target.parent.is_kworker": return "signal", nil case "signal.target.parent.is_thread": @@ -31267,6 +31649,20 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.String, nil case "chown.syscall.uid": return reflect.Int, nil + case "connect.addr.family": + return reflect.Int, nil + case "connect.addr.ip": + return reflect.Struct, nil + case "connect.addr.port": + return reflect.Int, nil + case "connect.retval": + return reflect.Int, nil + case "connect.server.addr.family": + return reflect.Int, nil + case "connect.server.addr.ip": + return reflect.Struct, nil + case "connect.server.addr.port": + return reflect.Int, nil case "container.created_at": return reflect.Int, nil case "container.id": @@ -31439,6 +31835,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "exec.interpreter.file.user": return reflect.String, nil + case "exec.is_exec": + return reflect.Bool, nil case "exec.is_kworker": return reflect.Bool, nil case "exec.is_thread": @@ -31605,6 +32003,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "exit.interpreter.file.user": return reflect.String, nil + case "exit.is_exec": + return reflect.Bool, nil case "exit.is_kworker": return reflect.Bool, nil case "exit.is_thread": @@ -31987,6 +32387,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "packet.device.ifname": return reflect.String, nil + case "packet.filter": + return reflect.String, nil case "packet.l3_protocol": return reflect.Int, nil case "packet.l4_protocol": @@ -32137,6 +32539,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "process.ancestors.interpreter.file.user": return reflect.String, nil + case "process.ancestors.is_exec": + return reflect.Bool, nil case "process.ancestors.is_kworker": return reflect.Bool, nil case "process.ancestors.is_thread": @@ -32299,6 +32703,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "process.interpreter.file.user": return reflect.String, nil + case "process.is_exec": + return reflect.Bool, nil case "process.is_kworker": return reflect.Bool, nil case "process.is_thread": @@ -32441,6 +32847,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "process.parent.interpreter.file.user": return reflect.String, nil + case "process.parent.is_exec": + return reflect.Bool, nil case "process.parent.is_kworker": return reflect.Bool, nil case "process.parent.is_thread": @@ -32623,6 +33031,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "ptrace.tracee.ancestors.interpreter.file.user": return reflect.String, nil + case "ptrace.tracee.ancestors.is_exec": + return reflect.Bool, nil case "ptrace.tracee.ancestors.is_kworker": return reflect.Bool, nil case "ptrace.tracee.ancestors.is_thread": @@ -32785,6 +33195,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "ptrace.tracee.interpreter.file.user": return reflect.String, nil + case "ptrace.tracee.is_exec": + return reflect.Bool, nil case "ptrace.tracee.is_kworker": return reflect.Bool, nil case "ptrace.tracee.is_thread": @@ -32927,6 +33339,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "ptrace.tracee.parent.interpreter.file.user": return reflect.String, nil + case "ptrace.tracee.parent.is_exec": + return reflect.Bool, nil case "ptrace.tracee.parent.is_kworker": return reflect.Bool, nil case "ptrace.tracee.parent.is_thread": @@ -33361,6 +33775,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "signal.target.ancestors.interpreter.file.user": return reflect.String, nil + case "signal.target.ancestors.is_exec": + return reflect.Bool, nil case "signal.target.ancestors.is_kworker": return reflect.Bool, nil case "signal.target.ancestors.is_thread": @@ -33523,6 +33939,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "signal.target.interpreter.file.user": return reflect.String, nil + case "signal.target.is_exec": + return reflect.Bool, nil case "signal.target.is_kworker": return reflect.Bool, nil case "signal.target.is_thread": @@ -33665,6 +34083,8 @@ func (ev *Event) GetFieldType(field eval.Field) (reflect.Kind, error) { return reflect.Int, nil case "signal.target.parent.interpreter.file.user": return reflect.String, nil + case "signal.target.parent.is_exec": + return reflect.Bool, nil case "signal.target.parent.is_kworker": return reflect.Bool, nil case "signal.target.parent.is_thread": @@ -34522,6 +34942,67 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.Chown.SyscallContext.IntArg2 = int64(rv) return nil + case "connect.addr.family": + rv, ok := value.(int) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Connect.AddrFamily"} + } + if rv < 0 || rv > math.MaxUint16 { + return &eval.ErrValueOutOfRange{Field: "Connect.AddrFamily"} + } + ev.Connect.AddrFamily = uint16(rv) + return nil + case "connect.addr.ip": + rv, ok := value.(net.IPNet) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Connect.Addr.IPNet"} + } + ev.Connect.Addr.IPNet = rv + return nil + case "connect.addr.port": + rv, ok := value.(int) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Connect.Addr.Port"} + } + if rv < 0 || rv > math.MaxUint16 { + return &eval.ErrValueOutOfRange{Field: "Connect.Addr.Port"} + } + ev.Connect.Addr.Port = uint16(rv) + return nil + case "connect.retval": + rv, ok := value.(int) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Connect.SyscallEvent.Retval"} + } + ev.Connect.SyscallEvent.Retval = int64(rv) + return nil + case "connect.server.addr.family": + rv, ok := value.(int) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Connect.AddrFamily"} + } + if rv < 0 || rv > math.MaxUint16 { + return &eval.ErrValueOutOfRange{Field: "Connect.AddrFamily"} + } + ev.Connect.AddrFamily = uint16(rv) + return nil + case "connect.server.addr.ip": + rv, ok := value.(net.IPNet) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Connect.Addr.IPNet"} + } + ev.Connect.Addr.IPNet = rv + return nil + case "connect.server.addr.port": + rv, ok := value.(int) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Connect.Addr.Port"} + } + if rv < 0 || rv > math.MaxUint16 { + return &eval.ErrValueOutOfRange{Field: "Connect.Addr.Port"} + } + ev.Connect.Addr.Port = uint16(rv) + return nil case "container.created_at": if ev.BaseEvent.ContainerContext == nil { ev.BaseEvent.ContainerContext = &ContainerContext{} @@ -35369,6 +35850,16 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.Exec.Process.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "exec.is_exec": + if ev.Exec.Process == nil { + ev.Exec.Process = &Process{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Exec.Process.IsExec"} + } + ev.Exec.Process.IsExec = rv + return nil case "exec.is_kworker": if ev.Exec.Process == nil { ev.Exec.Process = &Process{} @@ -36206,6 +36697,16 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.Exit.Process.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "exit.is_exec": + if ev.Exit.Process == nil { + ev.Exit.Process = &Process{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Exit.Process.IsExec"} + } + ev.Exit.Process.IsExec = rv + return nil case "exit.is_kworker": if ev.Exit.Process == nil { ev.Exit.Process = &Process{} @@ -37591,6 +38092,13 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.RawPacket.NetworkContext.Device.IfName = rv return nil + case "packet.filter": + rv, ok := value.(string) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "RawPacket.Filter"} + } + ev.RawPacket.Filter = rv + return nil case "packet.l3_protocol": rv, ok := value.(int) if !ok { @@ -38555,6 +39063,19 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.BaseEvent.ProcessContext.Ancestor.ProcessContext.Process.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "process.ancestors.is_exec": + if ev.BaseEvent.ProcessContext == nil { + ev.BaseEvent.ProcessContext = &ProcessContext{} + } + if ev.BaseEvent.ProcessContext.Ancestor == nil { + ev.BaseEvent.ProcessContext.Ancestor = &ProcessCacheEntry{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "BaseEvent.ProcessContext.Ancestor.ProcessContext.Process.IsExec"} + } + ev.BaseEvent.ProcessContext.Ancestor.ProcessContext.Process.IsExec = rv + return nil case "process.ancestors.is_kworker": if ev.BaseEvent.ProcessContext == nil { ev.BaseEvent.ProcessContext = &ProcessContext{} @@ -39412,6 +39933,16 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.BaseEvent.ProcessContext.Process.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "process.is_exec": + if ev.BaseEvent.ProcessContext == nil { + ev.BaseEvent.ProcessContext = &ProcessContext{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "BaseEvent.ProcessContext.Process.IsExec"} + } + ev.BaseEvent.ProcessContext.Process.IsExec = rv + return nil case "process.is_kworker": if ev.BaseEvent.ProcessContext == nil { ev.BaseEvent.ProcessContext = &ProcessContext{} @@ -40342,6 +40873,19 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.BaseEvent.ProcessContext.Parent.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "process.parent.is_exec": + if ev.BaseEvent.ProcessContext == nil { + ev.BaseEvent.ProcessContext = &ProcessContext{} + } + if ev.BaseEvent.ProcessContext.Parent == nil { + ev.BaseEvent.ProcessContext.Parent = &Process{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "BaseEvent.ProcessContext.Parent.IsExec"} + } + ev.BaseEvent.ProcessContext.Parent.IsExec = rv + return nil case "process.parent.is_kworker": if ev.BaseEvent.ProcessContext == nil { ev.BaseEvent.ProcessContext = &ProcessContext{} @@ -41505,6 +42049,19 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.PTrace.Tracee.Ancestor.ProcessContext.Process.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "ptrace.tracee.ancestors.is_exec": + if ev.PTrace.Tracee == nil { + ev.PTrace.Tracee = &ProcessContext{} + } + if ev.PTrace.Tracee.Ancestor == nil { + ev.PTrace.Tracee.Ancestor = &ProcessCacheEntry{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "PTrace.Tracee.Ancestor.ProcessContext.Process.IsExec"} + } + ev.PTrace.Tracee.Ancestor.ProcessContext.Process.IsExec = rv + return nil case "ptrace.tracee.ancestors.is_kworker": if ev.PTrace.Tracee == nil { ev.PTrace.Tracee = &ProcessContext{} @@ -42362,6 +42919,16 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.PTrace.Tracee.Process.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "ptrace.tracee.is_exec": + if ev.PTrace.Tracee == nil { + ev.PTrace.Tracee = &ProcessContext{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "PTrace.Tracee.Process.IsExec"} + } + ev.PTrace.Tracee.Process.IsExec = rv + return nil case "ptrace.tracee.is_kworker": if ev.PTrace.Tracee == nil { ev.PTrace.Tracee = &ProcessContext{} @@ -43292,6 +43859,19 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.PTrace.Tracee.Parent.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "ptrace.tracee.parent.is_exec": + if ev.PTrace.Tracee == nil { + ev.PTrace.Tracee = &ProcessContext{} + } + if ev.PTrace.Tracee.Parent == nil { + ev.PTrace.Tracee.Parent = &Process{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "PTrace.Tracee.Parent.IsExec"} + } + ev.PTrace.Tracee.Parent.IsExec = rv + return nil case "ptrace.tracee.parent.is_kworker": if ev.PTrace.Tracee == nil { ev.PTrace.Tracee = &ProcessContext{} @@ -45332,6 +45912,19 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.Signal.Target.Ancestor.ProcessContext.Process.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "signal.target.ancestors.is_exec": + if ev.Signal.Target == nil { + ev.Signal.Target = &ProcessContext{} + } + if ev.Signal.Target.Ancestor == nil { + ev.Signal.Target.Ancestor = &ProcessCacheEntry{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Signal.Target.Ancestor.ProcessContext.Process.IsExec"} + } + ev.Signal.Target.Ancestor.ProcessContext.Process.IsExec = rv + return nil case "signal.target.ancestors.is_kworker": if ev.Signal.Target == nil { ev.Signal.Target = &ProcessContext{} @@ -46189,6 +46782,16 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.Signal.Target.Process.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "signal.target.is_exec": + if ev.Signal.Target == nil { + ev.Signal.Target = &ProcessContext{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Signal.Target.Process.IsExec"} + } + ev.Signal.Target.Process.IsExec = rv + return nil case "signal.target.is_kworker": if ev.Signal.Target == nil { ev.Signal.Target = &ProcessContext{} @@ -47119,6 +47722,19 @@ func (ev *Event) SetFieldValue(field eval.Field, value interface{}) error { } ev.Signal.Target.Parent.LinuxBinprm.FileEvent.FileFields.User = rv return nil + case "signal.target.parent.is_exec": + if ev.Signal.Target == nil { + ev.Signal.Target = &ProcessContext{} + } + if ev.Signal.Target.Parent == nil { + ev.Signal.Target.Parent = &Process{} + } + rv, ok := value.(bool) + if !ok { + return &eval.ErrValueTypeMismatch{Field: "Signal.Target.Parent.IsExec"} + } + ev.Signal.Target.Parent.IsExec = rv + return nil case "signal.target.parent.is_kworker": if ev.Signal.Target == nil { ev.Signal.Target = &ProcessContext{} diff --git a/pkg/security/secl/model/category.go b/pkg/security/secl/model/category.go index f7a934b09ead9..f03a79ffeb7b9 100644 --- a/pkg/security/secl/model/category.go +++ b/pkg/security/secl/model/category.go @@ -57,7 +57,8 @@ func GetEventTypeCategory(eventType eval.EventType) EventCategory { MProtectEventType.String(), PTraceEventType.String(), UnloadModuleEventType.String(), - BindEventType.String(): + BindEventType.String(), + ConnectEventType.String(): return KernelCategory // Network diff --git a/pkg/security/secl/model/events.go b/pkg/security/secl/model/events.go index 8e44b9aa1e97c..a0fb2b8a149d6 100644 --- a/pkg/security/secl/model/events.go +++ b/pkg/security/secl/model/events.go @@ -85,6 +85,8 @@ const ( VethPairEventType // BindEventType Bind event BindEventType + // ConnectEventType Connect event + ConnectEventType // UnshareMountNsEventType is sent when a new mount is created from a mount namespace copy UnshareMountNsEventType // SyscallsEventType Syscalls event @@ -229,6 +231,8 @@ func (t EventType) String() string { return "veth_pair" case BindEventType: return "bind" + case ConnectEventType: + return "connect" case UnshareMountNsEventType: return "unshare_mntns" case SyscallsEventType: diff --git a/pkg/security/secl/model/field_accessors_unix.go b/pkg/security/secl/model/field_accessors_unix.go index 71e1fbaab29bc..9df3c15cb4cb9 100644 --- a/pkg/security/secl/model/field_accessors_unix.go +++ b/pkg/security/secl/model/field_accessors_unix.go @@ -898,6 +898,62 @@ func (ev *Event) GetChownSyscallUid() int { return ev.FieldHandlers.ResolveSyscallCtxArgsInt2(ev, &ev.Chown.SyscallContext) } +// GetConnectAddrFamily returns the value of the field, resolving if necessary +func (ev *Event) GetConnectAddrFamily() uint16 { + if ev.GetEventType().String() != "connect" { + return uint16(0) + } + return ev.Connect.AddrFamily +} + +// GetConnectAddrIp returns the value of the field, resolving if necessary +func (ev *Event) GetConnectAddrIp() net.IPNet { + if ev.GetEventType().String() != "connect" { + return net.IPNet{} + } + return ev.Connect.Addr.IPNet +} + +// GetConnectAddrPort returns the value of the field, resolving if necessary +func (ev *Event) GetConnectAddrPort() uint16 { + if ev.GetEventType().String() != "connect" { + return uint16(0) + } + return ev.Connect.Addr.Port +} + +// GetConnectRetval returns the value of the field, resolving if necessary +func (ev *Event) GetConnectRetval() int64 { + if ev.GetEventType().String() != "connect" { + return int64(0) + } + return ev.Connect.SyscallEvent.Retval +} + +// GetConnectServerAddrFamily returns the value of the field, resolving if necessary +func (ev *Event) GetConnectServerAddrFamily() uint16 { + if ev.GetEventType().String() != "connect" { + return uint16(0) + } + return ev.Connect.AddrFamily +} + +// GetConnectServerAddrIp returns the value of the field, resolving if necessary +func (ev *Event) GetConnectServerAddrIp() net.IPNet { + if ev.GetEventType().String() != "connect" { + return net.IPNet{} + } + return ev.Connect.Addr.IPNet +} + +// GetConnectServerAddrPort returns the value of the field, resolving if necessary +func (ev *Event) GetConnectServerAddrPort() uint16 { + if ev.GetEventType().String() != "connect" { + return uint16(0) + } + return ev.Connect.Addr.Port +} + // GetContainerCreatedAt returns the value of the field, resolving if necessary func (ev *Event) GetContainerCreatedAt() int { if ev.BaseEvent.ContainerContext == nil { @@ -1949,6 +2005,17 @@ func (ev *Event) GetExecInterpreterFileUser() string { return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Exec.Process.LinuxBinprm.FileEvent.FileFields) } +// GetExecIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetExecIsExec() bool { + if ev.GetEventType().String() != "exec" { + return false + } + if ev.Exec.Process == nil { + return false + } + return ev.Exec.Process.IsExec +} + // GetExecIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetExecIsKworker() bool { if ev.GetEventType().String() != "exec" { @@ -1968,7 +2035,7 @@ func (ev *Event) GetExecIsThread() bool { if ev.Exec.Process == nil { return false } - return ev.Exec.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Exec.Process) } // GetExecPid returns the value of the field, resolving if necessary @@ -3075,6 +3142,17 @@ func (ev *Event) GetExitInterpreterFileUser() string { return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Exit.Process.LinuxBinprm.FileEvent.FileFields) } +// GetExitIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetExitIsExec() bool { + if ev.GetEventType().String() != "exit" { + return false + } + if ev.Exit.Process == nil { + return false + } + return ev.Exit.Process.IsExec +} + // GetExitIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetExitIsKworker() bool { if ev.GetEventType().String() != "exit" { @@ -3094,7 +3172,7 @@ func (ev *Event) GetExitIsThread() bool { if ev.Exit.Process == nil { return false } - return ev.Exit.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Exit.Process) } // GetExitPid returns the value of the field, resolving if necessary @@ -4756,6 +4834,14 @@ func (ev *Event) GetPacketDeviceIfname() string { return ev.FieldHandlers.ResolveNetworkDeviceIfName(ev, &ev.RawPacket.NetworkContext.Device) } +// GetPacketFilter returns the value of the field, resolving if necessary +func (ev *Event) GetPacketFilter() string { + if ev.GetEventType().String() != "packet" { + return "" + } + return ev.RawPacket.Filter +} + // GetPacketL3Protocol returns the value of the field, resolving if necessary func (ev *Event) GetPacketL3Protocol() uint16 { if ev.GetEventType().String() != "packet" { @@ -6316,6 +6402,27 @@ func (ev *Event) GetProcessAncestorsInterpreterFileUser() []string { return values } +// GetProcessAncestorsIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetProcessAncestorsIsExec() []bool { + if ev.BaseEvent.ProcessContext == nil { + return []bool{} + } + if ev.BaseEvent.ProcessContext.Ancestor == nil { + return []bool{} + } + var values []bool + ctx := eval.NewContext(ev) + iterator := &ProcessAncestorsIterator{} + ptr := iterator.Front(ctx) + for ptr != nil { + element := (*ProcessCacheEntry)(ptr) + result := element.ProcessContext.Process.IsExec + values = append(values, result) + ptr = iterator.Next() + } + return values +} + // GetProcessAncestorsIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetProcessAncestorsIsKworker() []bool { if ev.BaseEvent.ProcessContext == nil { @@ -6351,7 +6458,7 @@ func (ev *Event) GetProcessAncestorsIsThread() []bool { ptr := iterator.Front(ctx) for ptr != nil { element := (*ProcessCacheEntry)(ptr) - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) values = append(values, result) ptr = iterator.Next() } @@ -7268,6 +7375,14 @@ func (ev *Event) GetProcessInterpreterFileUser() string { return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.BaseEvent.ProcessContext.Process.LinuxBinprm.FileEvent.FileFields) } +// GetProcessIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetProcessIsExec() bool { + if ev.BaseEvent.ProcessContext == nil { + return false + } + return ev.BaseEvent.ProcessContext.Process.IsExec +} + // GetProcessIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetProcessIsKworker() bool { if ev.BaseEvent.ProcessContext == nil { @@ -7281,7 +7396,7 @@ func (ev *Event) GetProcessIsThread() bool { if ev.BaseEvent.ProcessContext == nil { return false } - return ev.BaseEvent.ProcessContext.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.BaseEvent.ProcessContext.Process) } // GetProcessParentArgs returns the value of the field, resolving if necessary @@ -8388,6 +8503,20 @@ func (ev *Event) GetProcessParentInterpreterFileUser() string { return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.BaseEvent.ProcessContext.Parent.LinuxBinprm.FileEvent.FileFields) } +// GetProcessParentIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetProcessParentIsExec() bool { + if ev.BaseEvent.ProcessContext == nil { + return false + } + if ev.BaseEvent.ProcessContext.Parent == nil { + return false + } + if !ev.BaseEvent.ProcessContext.HasParent() { + return false + } + return ev.BaseEvent.ProcessContext.Parent.IsExec +} + // GetProcessParentIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetProcessParentIsKworker() bool { if ev.BaseEvent.ProcessContext == nil { @@ -8413,7 +8542,7 @@ func (ev *Event) GetProcessParentIsThread() bool { if !ev.BaseEvent.ProcessContext.HasParent() { return false } - return ev.BaseEvent.ProcessContext.Parent.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.BaseEvent.ProcessContext.Parent) } // GetProcessParentPid returns the value of the field, resolving if necessary @@ -10358,6 +10487,30 @@ func (ev *Event) GetPtraceTraceeAncestorsInterpreterFileUser() []string { return values } +// GetPtraceTraceeAncestorsIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetPtraceTraceeAncestorsIsExec() []bool { + if ev.GetEventType().String() != "ptrace" { + return []bool{} + } + if ev.PTrace.Tracee == nil { + return []bool{} + } + if ev.PTrace.Tracee.Ancestor == nil { + return []bool{} + } + var values []bool + ctx := eval.NewContext(ev) + iterator := &ProcessAncestorsIterator{} + ptr := iterator.Front(ctx) + for ptr != nil { + element := (*ProcessCacheEntry)(ptr) + result := element.ProcessContext.Process.IsExec + values = append(values, result) + ptr = iterator.Next() + } + return values +} + // GetPtraceTraceeAncestorsIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetPtraceTraceeAncestorsIsKworker() []bool { if ev.GetEventType().String() != "ptrace" { @@ -10399,7 +10552,7 @@ func (ev *Event) GetPtraceTraceeAncestorsIsThread() []bool { ptr := iterator.Front(ctx) for ptr != nil { element := (*ProcessCacheEntry)(ptr) - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) values = append(values, result) ptr = iterator.Next() } @@ -11571,6 +11724,17 @@ func (ev *Event) GetPtraceTraceeInterpreterFileUser() string { return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.PTrace.Tracee.Process.LinuxBinprm.FileEvent.FileFields) } +// GetPtraceTraceeIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetPtraceTraceeIsExec() bool { + if ev.GetEventType().String() != "ptrace" { + return false + } + if ev.PTrace.Tracee == nil { + return false + } + return ev.PTrace.Tracee.Process.IsExec +} + // GetPtraceTraceeIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetPtraceTraceeIsKworker() bool { if ev.GetEventType().String() != "ptrace" { @@ -11590,7 +11754,7 @@ func (ev *Event) GetPtraceTraceeIsThread() bool { if ev.PTrace.Tracee == nil { return false } - return ev.PTrace.Tracee.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.PTrace.Tracee.Process) } // GetPtraceTraceeParentArgs returns the value of the field, resolving if necessary @@ -12913,6 +13077,23 @@ func (ev *Event) GetPtraceTraceeParentInterpreterFileUser() string { return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.PTrace.Tracee.Parent.LinuxBinprm.FileEvent.FileFields) } +// GetPtraceTraceeParentIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetPtraceTraceeParentIsExec() bool { + if ev.GetEventType().String() != "ptrace" { + return false + } + if ev.PTrace.Tracee == nil { + return false + } + if ev.PTrace.Tracee.Parent == nil { + return false + } + if !ev.PTrace.Tracee.HasParent() { + return false + } + return ev.PTrace.Tracee.Parent.IsExec +} + // GetPtraceTraceeParentIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetPtraceTraceeParentIsKworker() bool { if ev.GetEventType().String() != "ptrace" { @@ -12944,7 +13125,7 @@ func (ev *Event) GetPtraceTraceeParentIsThread() bool { if !ev.PTrace.Tracee.HasParent() { return false } - return ev.PTrace.Tracee.Parent.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.PTrace.Tracee.Parent) } // GetPtraceTraceeParentPid returns the value of the field, resolving if necessary @@ -15999,6 +16180,30 @@ func (ev *Event) GetSignalTargetAncestorsInterpreterFileUser() []string { return values } +// GetSignalTargetAncestorsIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetSignalTargetAncestorsIsExec() []bool { + if ev.GetEventType().String() != "signal" { + return []bool{} + } + if ev.Signal.Target == nil { + return []bool{} + } + if ev.Signal.Target.Ancestor == nil { + return []bool{} + } + var values []bool + ctx := eval.NewContext(ev) + iterator := &ProcessAncestorsIterator{} + ptr := iterator.Front(ctx) + for ptr != nil { + element := (*ProcessCacheEntry)(ptr) + result := element.ProcessContext.Process.IsExec + values = append(values, result) + ptr = iterator.Next() + } + return values +} + // GetSignalTargetAncestorsIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetSignalTargetAncestorsIsKworker() []bool { if ev.GetEventType().String() != "signal" { @@ -16040,7 +16245,7 @@ func (ev *Event) GetSignalTargetAncestorsIsThread() []bool { ptr := iterator.Front(ctx) for ptr != nil { element := (*ProcessCacheEntry)(ptr) - result := element.ProcessContext.Process.IsThread + result := ev.FieldHandlers.ResolveProcessIsThread(ev, &element.ProcessContext.Process) values = append(values, result) ptr = iterator.Next() } @@ -17212,6 +17417,17 @@ func (ev *Event) GetSignalTargetInterpreterFileUser() string { return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Signal.Target.Process.LinuxBinprm.FileEvent.FileFields) } +// GetSignalTargetIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetSignalTargetIsExec() bool { + if ev.GetEventType().String() != "signal" { + return false + } + if ev.Signal.Target == nil { + return false + } + return ev.Signal.Target.Process.IsExec +} + // GetSignalTargetIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetSignalTargetIsKworker() bool { if ev.GetEventType().String() != "signal" { @@ -17231,7 +17447,7 @@ func (ev *Event) GetSignalTargetIsThread() bool { if ev.Signal.Target == nil { return false } - return ev.Signal.Target.Process.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.Signal.Target.Process) } // GetSignalTargetParentArgs returns the value of the field, resolving if necessary @@ -18554,6 +18770,23 @@ func (ev *Event) GetSignalTargetParentInterpreterFileUser() string { return ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Signal.Target.Parent.LinuxBinprm.FileEvent.FileFields) } +// GetSignalTargetParentIsExec returns the value of the field, resolving if necessary +func (ev *Event) GetSignalTargetParentIsExec() bool { + if ev.GetEventType().String() != "signal" { + return false + } + if ev.Signal.Target == nil { + return false + } + if ev.Signal.Target.Parent == nil { + return false + } + if !ev.Signal.Target.HasParent() { + return false + } + return ev.Signal.Target.Parent.IsExec +} + // GetSignalTargetParentIsKworker returns the value of the field, resolving if necessary func (ev *Event) GetSignalTargetParentIsKworker() bool { if ev.GetEventType().String() != "signal" { @@ -18585,7 +18818,7 @@ func (ev *Event) GetSignalTargetParentIsThread() bool { if !ev.Signal.Target.HasParent() { return false } - return ev.Signal.Target.Parent.IsThread + return ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Signal.Target.Parent) } // GetSignalTargetParentPid returns the value of the field, resolving if necessary diff --git a/pkg/security/secl/model/field_handlers_unix.go b/pkg/security/secl/model/field_handlers_unix.go index 0a8676ccbbcc1..bf89665d41f89 100644 --- a/pkg/security/secl/model/field_handlers_unix.go +++ b/pkg/security/secl/model/field_handlers_unix.go @@ -113,6 +113,7 @@ func (ev *Event) resolveFields(forADs bool) { if ev.BaseEvent.ProcessContext.Process.HasInterpreter() { _ = ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.BaseEvent.ProcessContext.Process.LinuxBinprm.FileEvent.FileFields) } + _ = ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.BaseEvent.ProcessContext.Process) if ev.BaseEvent.ProcessContext.HasParent() { if !forADs { _ = ev.FieldHandlers.ResolveProcessArgs(ev, ev.BaseEvent.ProcessContext.Parent) @@ -212,6 +213,9 @@ func (ev *Event) resolveFields(forADs bool) { if ev.BaseEvent.ProcessContext.HasParent() && ev.BaseEvent.ProcessContext.Parent.HasInterpreter() { _ = ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.BaseEvent.ProcessContext.Parent.LinuxBinprm.FileEvent.FileFields) } + if ev.BaseEvent.ProcessContext.HasParent() { + _ = ev.FieldHandlers.ResolveProcessIsThread(ev, ev.BaseEvent.ProcessContext.Parent) + } if ev.BaseEvent.ProcessContext.HasParent() { _ = ev.FieldHandlers.ResolveK8SGroups(ev, &ev.BaseEvent.ProcessContext.Parent.UserSession) } @@ -288,6 +292,7 @@ func (ev *Event) resolveFields(forADs bool) { if !forADs { _ = ev.FieldHandlers.ResolveSyscallCtxArgsInt3(ev, &ev.Chown.SyscallContext) } + case "connect": case "dns": case "exec": if ev.Exec.Process.IsNotKworker() { @@ -370,6 +375,7 @@ func (ev *Event) resolveFields(forADs bool) { _ = ev.FieldHandlers.ResolveProcessEnvs(ev, ev.Exec.Process) _ = ev.FieldHandlers.ResolveProcessEnvp(ev, ev.Exec.Process) _ = ev.FieldHandlers.ResolveProcessEnvsTruncated(ev, ev.Exec.Process) + _ = ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Exec.Process) if !forADs { _ = ev.FieldHandlers.ResolveSyscallCtxArgsStr1(ev, &ev.Exec.SyscallContext) } @@ -454,6 +460,7 @@ func (ev *Event) resolveFields(forADs bool) { _ = ev.FieldHandlers.ResolveProcessEnvs(ev, ev.Exit.Process) _ = ev.FieldHandlers.ResolveProcessEnvp(ev, ev.Exit.Process) _ = ev.FieldHandlers.ResolveProcessEnvsTruncated(ev, ev.Exit.Process) + _ = ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Exit.Process) case "imds": case "link": _ = ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Link.Source.FileFields) @@ -656,6 +663,7 @@ func (ev *Event) resolveFields(forADs bool) { _ = ev.FieldHandlers.ResolveProcessEnvs(ev, &ev.PTrace.Tracee.Process) _ = ev.FieldHandlers.ResolveProcessEnvp(ev, &ev.PTrace.Tracee.Process) _ = ev.FieldHandlers.ResolveProcessEnvsTruncated(ev, &ev.PTrace.Tracee.Process) + _ = ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.PTrace.Tracee.Process) if ev.PTrace.Tracee.HasParent() && ev.PTrace.Tracee.Parent.IsNotKworker() { _ = ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.PTrace.Tracee.Parent.FileEvent.FileFields) } @@ -764,6 +772,9 @@ func (ev *Event) resolveFields(forADs bool) { if ev.PTrace.Tracee.HasParent() { _ = ev.FieldHandlers.ResolveProcessEnvsTruncated(ev, ev.PTrace.Tracee.Parent) } + if ev.PTrace.Tracee.HasParent() { + _ = ev.FieldHandlers.ResolveProcessIsThread(ev, ev.PTrace.Tracee.Parent) + } case "removexattr": _ = ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.RemoveXAttr.File.FileFields) _ = ev.FieldHandlers.ResolveFileFieldsGroup(ev, &ev.RemoveXAttr.File.FileFields) @@ -929,6 +940,7 @@ func (ev *Event) resolveFields(forADs bool) { _ = ev.FieldHandlers.ResolveProcessEnvs(ev, &ev.Signal.Target.Process) _ = ev.FieldHandlers.ResolveProcessEnvp(ev, &ev.Signal.Target.Process) _ = ev.FieldHandlers.ResolveProcessEnvsTruncated(ev, &ev.Signal.Target.Process) + _ = ev.FieldHandlers.ResolveProcessIsThread(ev, &ev.Signal.Target.Process) if ev.Signal.Target.HasParent() && ev.Signal.Target.Parent.IsNotKworker() { _ = ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Signal.Target.Parent.FileEvent.FileFields) } @@ -1037,6 +1049,9 @@ func (ev *Event) resolveFields(forADs bool) { if ev.Signal.Target.HasParent() { _ = ev.FieldHandlers.ResolveProcessEnvsTruncated(ev, ev.Signal.Target.Parent) } + if ev.Signal.Target.HasParent() { + _ = ev.FieldHandlers.ResolveProcessIsThread(ev, ev.Signal.Target.Parent) + } case "splice": _ = ev.FieldHandlers.ResolveFileFieldsUser(ev, &ev.Splice.File.FileFields) _ = ev.FieldHandlers.ResolveFileFieldsGroup(ev, &ev.Splice.File.FileFields) @@ -1147,6 +1162,7 @@ type FieldHandlers interface { ResolveProcessEnvp(ev *Event, e *Process) []string ResolveProcessEnvs(ev *Event, e *Process) []string ResolveProcessEnvsTruncated(ev *Event, e *Process) bool + ResolveProcessIsThread(ev *Event, e *Process) bool ResolveRights(ev *Event, e *FileFields) int ResolveSELinuxBoolName(ev *Event, e *SELinuxEvent) string ResolveService(ev *Event, e *BaseEvent) string @@ -1325,6 +1341,9 @@ func (dfh *FakeFieldHandlers) ResolveProcessEnvs(ev *Event, e *Process) []string func (dfh *FakeFieldHandlers) ResolveProcessEnvsTruncated(ev *Event, e *Process) bool { return bool(e.EnvsTruncated) } +func (dfh *FakeFieldHandlers) ResolveProcessIsThread(ev *Event, e *Process) bool { + return bool(e.IsThread) +} func (dfh *FakeFieldHandlers) ResolveRights(ev *Event, e *FileFields) int { return int(e.Mode) } func (dfh *FakeFieldHandlers) ResolveSELinuxBoolName(ev *Event, e *SELinuxEvent) string { return string(e.BoolName) diff --git a/pkg/security/secl/model/model.go b/pkg/security/secl/model/model.go index 63e91a77107e5..27e25b561d715 100644 --- a/pkg/security/secl/model/model.go +++ b/pkg/security/secl/model/model.go @@ -14,10 +14,11 @@ import ( "runtime" "time" + "modernc.org/mathutil" + "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" "github.com/DataDog/datadog-agent/pkg/security/secl/containerutils" "github.com/DataDog/datadog-agent/pkg/security/secl/model/usersession" - "modernc.org/mathutil" ) // Model describes the data model for the runtime security agent events @@ -629,10 +630,3 @@ func (dfh *FakeFieldHandlers) ResolveContainerContext(_ *Event) (*ContainerConte type TLSContext struct { Version uint16 `field:"version"` // SECLDoc[version] Definition:`TLS version` } - -// RawPacketEvent represents a packet event -type RawPacketEvent struct { - NetworkContext - - TLSContext TLSContext `field:"tls"` // SECLDoc[tls] Definition:`TLS context` -} diff --git a/pkg/security/secl/model/model_unix.go b/pkg/security/secl/model/model_unix.go index 16fb174894fd7..9f20419c54447 100644 --- a/pkg/security/secl/model/model_unix.go +++ b/pkg/security/secl/model/model_unix.go @@ -15,6 +15,8 @@ import ( "modernc.org/mathutil" + "github.com/google/gopacket" + "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" "github.com/DataDog/datadog-agent/pkg/security/secl/containerutils" ) @@ -59,7 +61,8 @@ type Event struct { LoginUIDWrite LoginUIDWriteEvent `field:"-"` // network syscalls - Bind BindEvent `field:"bind" event:"bind"` // [7.37] [Network] A bind was executed + Bind BindEvent `field:"bind" event:"bind"` // [7.37] [Network] A bind was executed + Connect ConnectEvent `field:"connect" event:"connect"` // [7.60] [Network] A connect was executed // kernel events SELinux SELinuxEvent `field:"selinux" event:"selinux"` // [7.30] [Kernel] An SELinux operation was run @@ -260,9 +263,11 @@ type Process struct { ScrubbedArgvResolved bool `field:"-"` Variables eval.Variables `field:"-"` - IsThread bool `field:"is_thread"` // SECLDoc[is_thread] Definition:`Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program)` - IsExecExec bool `field:"-"` // Indicates whether the process is an exec following another exec - IsParentMissing bool `field:"-"` // Indicates the direct parent is missing + // IsThread is the negation of IsExec and should be manipulated directly + IsThread bool `field:"is_thread,handler:ResolveProcessIsThread"` // SECLDoc[is_thread] Definition:`Indicates whether the process is considered a thread (that is, a child process that hasn't executed another program)` + IsExec bool `field:"is_exec"` // SECLDoc[is_exec] Definition:`Indicates whether the process entry is from a new binary execution` + IsExecExec bool `field:"-"` // Indicates whether the process is an exec following another exec + IsParentMissing bool `field:"-"` // Indicates the direct parent is missing Source uint64 `field:"-"` @@ -637,6 +642,13 @@ type BindEvent struct { AddrFamily uint16 `field:"addr.family"` // SECLDoc[addr.family] Definition:`Address family` } +// ConnectEvent represents a connect event +type ConnectEvent struct { + SyscallEvent + Addr IPPortContext `field:"addr;server.addr"` // Connection address + AddrFamily uint16 `field:"addr.family;server.addr.family"` // SECLDoc[addr.family] Definition:`Address family` SECLDoc[server.addr.family] Definition:`Server address family` +} + // NetDevice represents a network device type NetDevice struct { Name string @@ -693,3 +705,12 @@ type OnDemandEvent struct { type LoginUIDWriteEvent struct { AUID uint32 `field:"-"` } + +// RawPacketEvent represents a packet event +type RawPacketEvent struct { + NetworkContext + TLSContext TLSContext `field:"tls"` // SECLDoc[tls] Definition:`TLS context` + Filter string `field:"filter" op_override:"PacketFilterMatching"` // SECLDoc[filter] Definition:`pcap filter expression` + CaptureInfo gopacket.CaptureInfo `field:"-"` + Data []byte `field:"-"` +} diff --git a/pkg/security/secl/model/packet_filter_unix.go b/pkg/security/secl/model/packet_filter_unix.go new file mode 100644 index 0000000000000..af1329d84040f --- /dev/null +++ b/pkg/security/secl/model/packet_filter_unix.go @@ -0,0 +1,73 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build unix && pcap && cgo + +// Package model holds model related files +package model + +import ( + "errors" + "fmt" + + "github.com/google/gopacket/layers" + "github.com/google/gopacket/pcap" + + "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" +) + +var errNonStaticPacketFilterField = errors.New("packet filter fields only support matching a single static") + +func errorNonStaticPacketFilterField(a eval.Evaluator, b eval.Evaluator) error { + var field string + if a.IsStatic() { + field = b.GetField() + } else if b.IsStatic() { + field = a.GetField() + } else { + return errNonStaticPacketFilterField + } + return fmt.Errorf("field `%s` only supports matching a single static value", field) +} + +func newPacketFilterEvaluator(field string, value string) (*eval.BoolEvaluator, error) { + switch field { + case "packet.filter": + captureLength := 256 // sizeof(struct raw_packet_t.data) + filter, err := pcap.NewBPF(layers.LinkTypeEthernet, captureLength, value) + if err != nil { + return nil, fmt.Errorf("failed to compile packet filter `%s` on field `%s`: %v", value, field, err) + } + return &eval.BoolEvaluator{ + EvalFnc: func(ctx *eval.Context) bool { + ev := ctx.Event.(*Event) + ev.RawPacket.CaptureInfo.Timestamp = ev.ResolveEventTime() + return filter.Matches(ev.RawPacket.CaptureInfo, ev.RawPacket.Data) + }, + }, nil + } + return nil, fmt.Errorf("field `%s` doesn't support packet filter evaluation", field) +} + +// PacketFilterMatching is a set of overrides for packet filter fields, it only supports matching a single static value +var PacketFilterMatching = &eval.OpOverrides{ + StringEquals: func(a *eval.StringEvaluator, b *eval.StringEvaluator, _ *eval.State) (*eval.BoolEvaluator, error) { + if a.IsStatic() { + return newPacketFilterEvaluator(b.GetField(), a.Value) + } else if b.IsStatic() { + return newPacketFilterEvaluator(a.GetField(), b.Value) + } + return nil, errorNonStaticPacketFilterField(a, b) + }, + StringValuesContains: func(a *eval.StringEvaluator, b *eval.StringValuesEvaluator, _ *eval.State) (*eval.BoolEvaluator, error) { + return nil, errorNonStaticPacketFilterField(a, b) + }, + StringArrayContains: func(a *eval.StringEvaluator, b *eval.StringArrayEvaluator, _ *eval.State) (*eval.BoolEvaluator, error) { + return nil, errorNonStaticPacketFilterField(a, b) + }, + StringArrayMatches: func(a *eval.StringArrayEvaluator, b *eval.StringValuesEvaluator, _ *eval.State) (*eval.BoolEvaluator, error) { + return nil, errorNonStaticPacketFilterField(a, b) + }, +} diff --git a/pkg/security/secl/model/packet_filter_unsupported.go b/pkg/security/secl/model/packet_filter_unsupported.go new file mode 100644 index 0000000000000..2dd5cdf74bc7b --- /dev/null +++ b/pkg/security/secl/model/packet_filter_unsupported.go @@ -0,0 +1,33 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build !(unix && pcap && cgo) + +// Package model holds model related files +package model + +import ( + "errors" + + "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" +) + +var errUnsupportedPacketFilter = errors.New("packet filter fields are not supported") + +// PacketFilterMatching is a set of overrides for packet filter fields, it only supports matching a single static value +var PacketFilterMatching = &eval.OpOverrides{ + StringEquals: func(_ *eval.StringEvaluator, _ *eval.StringEvaluator, _ *eval.State) (*eval.BoolEvaluator, error) { + return nil, errUnsupportedPacketFilter + }, + StringValuesContains: func(_ *eval.StringEvaluator, _ *eval.StringValuesEvaluator, _ *eval.State) (*eval.BoolEvaluator, error) { + return nil, errUnsupportedPacketFilter + }, + StringArrayContains: func(_ *eval.StringEvaluator, _ *eval.StringArrayEvaluator, _ *eval.State) (*eval.BoolEvaluator, error) { + return nil, errUnsupportedPacketFilter + }, + StringArrayMatches: func(_ *eval.StringArrayEvaluator, _ *eval.StringValuesEvaluator, _ *eval.State) (*eval.BoolEvaluator, error) { + return nil, errUnsupportedPacketFilter + }, +} diff --git a/pkg/security/secl/model/process_cache_entry_unix.go b/pkg/security/secl/model/process_cache_entry_unix.go index 55fb265984c79..c99de2e92dc8e 100644 --- a/pkg/security/secl/model/process_cache_entry_unix.go +++ b/pkg/security/secl/model/process_cache_entry_unix.go @@ -93,13 +93,19 @@ func (pc *ProcessCacheEntry) ApplyExecTimeOf(entry *ProcessCacheEntry) { pc.ExecTime = entry.ExecTime } +// SetExecParent set the parent of the exec entry +func (pc *ProcessCacheEntry) SetExecParent(parent *ProcessCacheEntry) { + pc.SetAncestor(parent) + pc.IsExec = true + pc.IsExecExec = pc.Parent != nil && pc.Parent.IsExec +} + // Exec replace a process func (pc *ProcessCacheEntry) Exec(entry *ProcessCacheEntry) { - entry.SetAncestor(pc) + entry.SetExecParent(pc) // use exec time as exit time pc.Exit(entry.ExecTime) - entry.Process.IsExecExec = !pc.IsThread // keep some context copyProcessContext(pc, entry) @@ -125,14 +131,13 @@ func (pc *ProcessCacheEntry) GetContainerPIDs() ([]uint32, []string) { return pids, paths } -// SetParentOfForkChild set the parent of a fork child -func (pc *ProcessCacheEntry) SetParentOfForkChild(parent *ProcessCacheEntry) { +// SetForkParent set the parent of the fork entry +func (pc *ProcessCacheEntry) SetForkParent(parent *ProcessCacheEntry) { pc.SetAncestor(parent) if parent != nil { pc.ArgsEntry = parent.ArgsEntry pc.EnvsEntry = parent.EnvsEntry } - pc.IsThread = true } // Fork returns a copy of the current ProcessCacheEntry @@ -148,7 +153,7 @@ func (pc *ProcessCacheEntry) Fork(childEntry *ProcessCacheEntry) { childEntry.LinuxBinprm = pc.LinuxBinprm childEntry.Cookie = pc.Cookie - childEntry.SetParentOfForkChild(pc) + childEntry.SetForkParent(pc) } // Equals returns whether process cache entries share the same values for file and args/envs diff --git a/pkg/security/secl/model/unmarshallers_linux.go b/pkg/security/secl/model/unmarshallers_linux.go index ab0955abc6195..cf7ebad99eaaf 100644 --- a/pkg/security/secl/model/unmarshallers_linux.go +++ b/pkg/security/secl/model/unmarshallers_linux.go @@ -19,11 +19,12 @@ import ( "strings" "time" - "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" - "github.com/DataDog/datadog-agent/pkg/security/secl/containerutils" "github.com/google/gopacket" "github.com/google/gopacket/layers" "golang.org/x/sys/unix" + + "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" + "github.com/DataDog/datadog-agent/pkg/security/secl/containerutils" ) func validateReadSize(size, read int) (int, error) { @@ -1274,6 +1275,33 @@ func (e *BindEvent) UnmarshalBinary(data []byte) (int, error) { return read + 20, nil } +// UnmarshalBinary unmarshalls a binary representation of itself +func (e *ConnectEvent) UnmarshalBinary(data []byte) (int, error) { + read, err := UnmarshalBinary(data, &e.SyscallEvent) + if err != nil { + return 0, err + } + + if len(data)-read < 20 { + return 0, ErrNotEnoughData + } + + var ipRaw [16]byte + SliceToArray(data[read:read+16], ipRaw[:]) + e.AddrFamily = binary.NativeEndian.Uint16(data[read+16 : read+18]) + e.Addr.Port = binary.BigEndian.Uint16(data[read+18 : read+20]) + + // readjust IP size depending on the protocol + switch e.AddrFamily { + case 0x2: // unix.AF_INET + e.Addr.IPNet = *eval.IPNetFromIP(ipRaw[0:4]) + case 0xa: // unix.AF_INET6 + e.Addr.IPNet = *eval.IPNetFromIP(ipRaw[:]) + } + + return read + 20, nil +} + // UnmarshalBinary unmarshalls a binary representation of itself func (e *SyscallsEvent) UnmarshalBinary(data []byte) (int, error) { if len(data) < 72 { @@ -1314,6 +1342,10 @@ func (e *RawPacketEvent) UnmarshalBinary(data []byte) (int, error) { e.Size = binary.NativeEndian.Uint32(data) data = data[4:] + e.Data = data + e.CaptureInfo.InterfaceIndex = int(e.NetworkContext.Device.IfIndex) + e.CaptureInfo.Length = int(e.NetworkContext.Size) + e.CaptureInfo.CaptureLength = len(data) packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.DecodeOptions{NoCopy: true, Lazy: true, DecodeStreamsAsDatagrams: true}) if layer := packet.Layer(layers.LayerTypeIPv4); layer != nil { diff --git a/pkg/security/secl/rules/policy.go b/pkg/security/secl/rules/policy.go index 240fb77ad984c..6b8dea65a6c35 100644 --- a/pkg/security/secl/rules/policy.go +++ b/pkg/security/secl/rules/policy.go @@ -90,7 +90,7 @@ func (r *PolicyRule) MergeWith(r2 *PolicyRule) error { case OverridePolicy: applyOverride(r, r2) default: - if !r2.Def.Disabled { + if r.Def.Disabled == r2.Def.Disabled { return &ErrRuleLoad{Rule: r2, Err: ErrDefinitionIDConflict} } } diff --git a/pkg/security/secl/rules/policy_test.go b/pkg/security/secl/rules/policy_test.go index 286b0fc1036da..fefbd3320551a 100644 --- a/pkg/security/secl/rules/policy_test.go +++ b/pkg/security/secl/rules/policy_test.go @@ -104,18 +104,40 @@ func TestMacroMerge(t *testing.T) { func TestRuleMerge(t *testing.T) { testPolicy := &PolicyDef{ - Rules: []*RuleDefinition{{ - ID: "test_rule", - Expression: `open.file.path == "/tmp/test"`, - }}, + Rules: []*RuleDefinition{ + { + ID: "test_rule", + Expression: `open.file.path == "/tmp/test"`, + }, + { + ID: "test_rule_foo", + Expression: `exec.file.name == "foo"`, + }, + { + ID: "test_rule_bar", + Expression: `exec.file.name == "bar"`, + Disabled: true, + }, + }, } testPolicy2 := &PolicyDef{ - Rules: []*RuleDefinition{{ - ID: "test_rule", - Expression: `open.file.path == "/tmp/test"`, - Combine: OverridePolicy, - }}, + Rules: []*RuleDefinition{ + { + ID: "test_rule", + Expression: `open.file.path == "/tmp/test"`, + Combine: OverridePolicy, + }, + { + ID: "test_rule_foo", + Expression: `exec.file.name == "foo"`, + Disabled: true, + }, + { + ID: "test_rule_bar", + Expression: `exec.file.name == "bar"`, + }, + }, } tmpDir := t.TempDir() @@ -139,20 +161,36 @@ func TestRuleMerge(t *testing.T) { t.Error(err) } - rule := rs.GetRules()["test_rule"] - if rule == nil { - t.Fatal("failed to find test_rule in ruleset") - } + t.Run("override", func(t *testing.T) { + rule := rs.GetRules()["test_rule"] + if rule == nil { + t.Fatal("failed to find test_rule in ruleset") + } - testPolicy2.Rules[0].Combine = "" + testPolicy2.Rules[0].Combine = "" - if err := savePolicy(filepath.Join(tmpDir, "test2.policy"), testPolicy2); err != nil { - t.Fatal(err) - } + if err := savePolicy(filepath.Join(tmpDir, "test2.policy"), testPolicy2); err != nil { + t.Fatal(err) + } - if err := rs.LoadPolicies(loader, PolicyLoaderOpts{}); err == nil { - t.Error("expected rule ID conflict") - } + if err := rs.LoadPolicies(loader, PolicyLoaderOpts{}); err == nil { + t.Error("expected rule ID conflict") + } + }) + + t.Run("enabled-disabled", func(t *testing.T) { + rule := rs.GetRules()["test_rule_foo"] + if rule != nil { + t.Fatal("expected test_rule_foo to not be loaded") + } + }) + + t.Run("disabled-enabled", func(t *testing.T) { + rule := rs.GetRules()["test_rule_bar"] + if rule == nil { + t.Fatal("expected test_rule_bar to be loaded") + } + }) } func TestActionSetVariable(t *testing.T) { diff --git a/pkg/security/secl/rules/rule_filters.go b/pkg/security/secl/rules/rule_filters.go index 8f116d4d175f5..e6fbb0024bea7 100644 --- a/pkg/security/secl/rules/rule_filters.go +++ b/pkg/security/secl/rules/rule_filters.go @@ -89,7 +89,7 @@ type SECLRuleFilter struct { func NewSECLRuleFilter(model eval.Model) *SECLRuleFilter { return &SECLRuleFilter{ model: model, - parsingContext: ast.NewParsingContext(), + parsingContext: ast.NewParsingContext(false), } } diff --git a/pkg/security/secl/rules/ruleset.go b/pkg/security/secl/rules/ruleset.go index 061e9d230c5a5..2e34abf5d0aa3 100644 --- a/pkg/security/secl/rules/ruleset.go +++ b/pkg/security/secl/rules/ruleset.go @@ -743,7 +743,7 @@ func (rs *RuleSet) LoadPolicies(loader *PolicyLoader, opts PolicyLoaderOpts) *mu rulesIndex = make(map[string]*PolicyRule) ) - parsingContext := ast.NewParsingContext() + parsingContext := ast.NewParsingContext(false) policies, err := loader.LoadPolicies(opts) if err != nil { diff --git a/pkg/security/secl/rules/ruleset_test.go b/pkg/security/secl/rules/ruleset_test.go index 8221163152fd4..f7b56bdc5cd93 100644 --- a/pkg/security/secl/rules/ruleset_test.go +++ b/pkg/security/secl/rules/ruleset_test.go @@ -1067,7 +1067,7 @@ func TestGetRuleEventType(t *testing.T) { t.Run("ok", func(t *testing.T) { rule := eval.NewRule("aaa", `open.file.name == "test"`, &eval.Opts{}) - pc := ast.NewParsingContext() + pc := ast.NewParsingContext(false) if err := rule.GenEvaluator(&model.Model{}, pc); err != nil { t.Fatal(err) @@ -1092,7 +1092,7 @@ func TestGetRuleEventType(t *testing.T) { t.Run("ko", func(t *testing.T) { rule := eval.NewRule("aaa", `open.file.name == "test" && unlink.file.name == "123"`, &eval.Opts{}) - pc := ast.NewParsingContext() + pc := ast.NewParsingContext(false) if err := rule.GenEvaluator(&model.Model{}, pc); err == nil { t.Fatalf("shouldn't get an evaluator, multiple event types: %s", err) diff --git a/pkg/security/secl/rules/testutil.go b/pkg/security/secl/rules/testutil.go index 53d06c1ec32a0..2631662e7b2fe 100644 --- a/pkg/security/secl/rules/testutil.go +++ b/pkg/security/secl/rules/testutil.go @@ -30,7 +30,7 @@ func AddTestRuleExpr(t testing.TB, rs *RuleSet, exprs ...string) { rules = append(rules, rule) } - pc := ast.NewParsingContext() + pc := ast.NewParsingContext(false) if err := rs.AddRules(pc, rules); err != nil { t.Fatal(err) diff --git a/pkg/security/secl/validators/rule_structure.go b/pkg/security/secl/validators/rule_structure.go index d8c2740bbeb17..e2665dd41658d 100644 --- a/pkg/security/secl/validators/rule_structure.go +++ b/pkg/security/secl/validators/rule_structure.go @@ -14,7 +14,7 @@ import ( // HasBareWildcardInField checks whether a rule has a bare wildcard func HasBareWildcardInField(rule *eval.Rule) (bool, error) { - parsingContext := ast.NewParsingContext() + parsingContext := ast.NewParsingContext(false) localModel := &model.Model{} if err := rule.GenEvaluator(localModel, parsingContext); err != nil { return false, err diff --git a/pkg/security/seclwin/model/events.go b/pkg/security/seclwin/model/events.go index 8e44b9aa1e97c..a0fb2b8a149d6 100644 --- a/pkg/security/seclwin/model/events.go +++ b/pkg/security/seclwin/model/events.go @@ -85,6 +85,8 @@ const ( VethPairEventType // BindEventType Bind event BindEventType + // ConnectEventType Connect event + ConnectEventType // UnshareMountNsEventType is sent when a new mount is created from a mount namespace copy UnshareMountNsEventType // SyscallsEventType Syscalls event @@ -229,6 +231,8 @@ func (t EventType) String() string { return "veth_pair" case BindEventType: return "bind" + case ConnectEventType: + return "connect" case UnshareMountNsEventType: return "unshare_mntns" case SyscallsEventType: diff --git a/pkg/security/seclwin/model/model.go b/pkg/security/seclwin/model/model.go index 63e91a77107e5..27e25b561d715 100644 --- a/pkg/security/seclwin/model/model.go +++ b/pkg/security/seclwin/model/model.go @@ -14,10 +14,11 @@ import ( "runtime" "time" + "modernc.org/mathutil" + "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" "github.com/DataDog/datadog-agent/pkg/security/secl/containerutils" "github.com/DataDog/datadog-agent/pkg/security/secl/model/usersession" - "modernc.org/mathutil" ) // Model describes the data model for the runtime security agent events @@ -629,10 +630,3 @@ func (dfh *FakeFieldHandlers) ResolveContainerContext(_ *Event) (*ContainerConte type TLSContext struct { Version uint16 `field:"version"` // SECLDoc[version] Definition:`TLS version` } - -// RawPacketEvent represents a packet event -type RawPacketEvent struct { - NetworkContext - - TLSContext TLSContext `field:"tls"` // SECLDoc[tls] Definition:`TLS context` -} diff --git a/pkg/security/serializers/serializers_linux.go b/pkg/security/serializers/serializers_linux.go index 0d238edd68221..958ecb9c25634 100644 --- a/pkg/security/serializers/serializers_linux.go +++ b/pkg/security/serializers/serializers_linux.go @@ -430,6 +430,12 @@ type BindEventSerializer struct { Addr IPPortFamilySerializer `json:"addr"` } +// ConnectEventSerializer serializes a connect event to JSON +// easyjson:json +type ConnectEventSerializer struct { + Addr IPPortFamilySerializer `json:"addr"` +} + // MountEventSerializer serializes a mount event to JSON // easyjson:json type MountEventSerializer struct { @@ -626,6 +632,7 @@ type EventSerializer struct { *DNSEventSerializer `json:"dns,omitempty"` *IMDSEventSerializer `json:"imds,omitempty"` *BindEventSerializer `json:"bind,omitempty"` + *ConnectEventSerializer `json:"connect,omitempty"` *MountEventSerializer `json:"mount,omitempty"` *SyscallsEventSerializer `json:"syscalls,omitempty"` *UserContextSerializer `json:"usr,omitempty"` @@ -934,6 +941,14 @@ func newBindEventSerializer(e *model.Event) *BindEventSerializer { return bes } +func newConnectEventSerializer(e *model.Event) *ConnectEventSerializer { + ces := &ConnectEventSerializer{ + Addr: newIPPortFamilySerializer(&e.Connect.Addr, + model.AddressFamily(e.Connect.AddrFamily).String()), + } + return ces +} + func newMountEventSerializer(e *model.Event) *MountEventSerializer { fh := e.FieldHandlers @@ -1385,6 +1400,9 @@ func NewEventSerializer(event *model.Event, opts *eval.Opts) *EventSerializer { case model.BindEventType: s.EventContextSerializer.Outcome = serializeOutcome(event.Bind.Retval) s.BindEventSerializer = newBindEventSerializer(event) + case model.ConnectEventType: + s.EventContextSerializer.Outcome = serializeOutcome(event.Connect.Retval) + s.ConnectEventSerializer = newConnectEventSerializer(event) case model.SyscallsEventType: s.SyscallsEventSerializer = newSyscallsEventSerializer(&event.Syscalls) case model.DNSEventType: diff --git a/pkg/security/serializers/serializers_linux_easyjson.go b/pkg/security/serializers/serializers_linux_easyjson.go index 5af0f52a63883..d843ad8f04869 100644 --- a/pkg/security/serializers/serializers_linux_easyjson.go +++ b/pkg/security/serializers/serializers_linux_easyjson.go @@ -3606,6 +3606,7 @@ func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers24( out.DNSEventSerializer = new(DNSEventSerializer) out.IMDSEventSerializer = new(IMDSEventSerializer) out.BindEventSerializer = new(BindEventSerializer) + out.ConnectEventSerializer = new(ConnectEventSerializer) out.MountEventSerializer = new(MountEventSerializer) out.SyscallsEventSerializer = new(SyscallsEventSerializer) out.UserContextSerializer = new(UserContextSerializer) @@ -3761,6 +3762,16 @@ func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers24( } (*out.BindEventSerializer).UnmarshalEasyJSON(in) } + case "connect": + if in.IsNull() { + in.Skip() + out.ConnectEventSerializer = nil + } else { + if out.ConnectEventSerializer == nil { + out.ConnectEventSerializer = new(ConnectEventSerializer) + } + (*out.ConnectEventSerializer).UnmarshalEasyJSON(in) + } case "mount": if in.IsNull() { in.Skip() @@ -4038,6 +4049,16 @@ func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers24( } (*in.BindEventSerializer).MarshalEasyJSON(out) } + if in.ConnectEventSerializer != nil { + const prefix string = ",\"connect\":" + if first { + first = false + out.RawString(prefix[1:]) + } else { + out.RawString(prefix) + } + (*in.ConnectEventSerializer).MarshalEasyJSON(out) + } if in.MountEventSerializer != nil { const prefix string = ",\"mount\":" if first { @@ -4460,7 +4481,59 @@ func (v CredentialsSerializer) MarshalEasyJSON(w *jwriter.Writer) { func (v *CredentialsSerializer) UnmarshalEasyJSON(l *jlexer.Lexer) { easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers26(l, v) } -func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers27(in *jlexer.Lexer, out *CapsetSerializer) { +func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers27(in *jlexer.Lexer, out *ConnectEventSerializer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "addr": + (out.Addr).UnmarshalEasyJSON(in) + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers27(out *jwriter.Writer, in ConnectEventSerializer) { + out.RawByte('{') + first := true + _ = first + { + const prefix string = ",\"addr\":" + out.RawString(prefix[1:]) + (in.Addr).MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v ConnectEventSerializer) MarshalEasyJSON(w *jwriter.Writer) { + easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers27(w, v) +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *ConnectEventSerializer) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers27(l, v) +} +func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers28(in *jlexer.Lexer, out *CapsetSerializer) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4535,7 +4608,7 @@ func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers27( in.Consumed() } } -func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers27(out *jwriter.Writer, in CapsetSerializer) { +func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers28(out *jwriter.Writer, in CapsetSerializer) { out.RawByte('{') first := true _ = first @@ -4576,14 +4649,14 @@ func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers27( // MarshalEasyJSON supports easyjson.Marshaler interface func (v CapsetSerializer) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers27(w, v) + easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers28(w, v) } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *CapsetSerializer) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers27(l, v) + easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers28(l, v) } -func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers28(in *jlexer.Lexer, out *BindEventSerializer) { +func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers29(in *jlexer.Lexer, out *BindEventSerializer) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4614,7 +4687,7 @@ func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers28( in.Consumed() } } -func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers28(out *jwriter.Writer, in BindEventSerializer) { +func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers29(out *jwriter.Writer, in BindEventSerializer) { out.RawByte('{') first := true _ = first @@ -4628,14 +4701,14 @@ func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers28( // MarshalEasyJSON supports easyjson.Marshaler interface func (v BindEventSerializer) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers28(w, v) + easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers29(w, v) } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *BindEventSerializer) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers28(l, v) + easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers29(l, v) } -func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers29(in *jlexer.Lexer, out *BPFProgramSerializer) { +func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers30(in *jlexer.Lexer, out *BPFProgramSerializer) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4695,7 +4768,7 @@ func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers29( in.Consumed() } } -func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers29(out *jwriter.Writer, in BPFProgramSerializer) { +func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers30(out *jwriter.Writer, in BPFProgramSerializer) { out.RawByte('{') first := true _ = first @@ -4759,14 +4832,14 @@ func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers29( // MarshalEasyJSON supports easyjson.Marshaler interface func (v BPFProgramSerializer) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers29(w, v) + easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers30(w, v) } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *BPFProgramSerializer) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers29(l, v) + easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers30(l, v) } -func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers30(in *jlexer.Lexer, out *BPFMapSerializer) { +func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers31(in *jlexer.Lexer, out *BPFMapSerializer) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4799,7 +4872,7 @@ func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers30( in.Consumed() } } -func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers30(out *jwriter.Writer, in BPFMapSerializer) { +func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers31(out *jwriter.Writer, in BPFMapSerializer) { out.RawByte('{') first := true _ = first @@ -4824,14 +4897,14 @@ func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers30( // MarshalEasyJSON supports easyjson.Marshaler interface func (v BPFMapSerializer) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers30(w, v) + easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers31(w, v) } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *BPFMapSerializer) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers30(l, v) + easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers31(l, v) } -func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers31(in *jlexer.Lexer, out *BPFEventSerializer) { +func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers32(in *jlexer.Lexer, out *BPFEventSerializer) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4882,7 +4955,7 @@ func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers31( in.Consumed() } } -func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers31(out *jwriter.Writer, in BPFEventSerializer) { +func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers32(out *jwriter.Writer, in BPFEventSerializer) { out.RawByte('{') first := true _ = first @@ -4906,14 +4979,14 @@ func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers31( // MarshalEasyJSON supports easyjson.Marshaler interface func (v BPFEventSerializer) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers31(w, v) + easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers32(w, v) } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *BPFEventSerializer) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers31(l, v) + easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers32(l, v) } -func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers32(in *jlexer.Lexer, out *AnomalyDetectionSyscallEventSerializer) { +func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers33(in *jlexer.Lexer, out *AnomalyDetectionSyscallEventSerializer) { isTopLevel := in.IsStart() if in.IsNull() { if isTopLevel { @@ -4944,7 +5017,7 @@ func easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers32( in.Consumed() } } -func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers32(out *jwriter.Writer, in AnomalyDetectionSyscallEventSerializer) { +func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers33(out *jwriter.Writer, in AnomalyDetectionSyscallEventSerializer) { out.RawByte('{') first := true _ = first @@ -4958,10 +5031,10 @@ func easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers32( // MarshalEasyJSON supports easyjson.Marshaler interface func (v AnomalyDetectionSyscallEventSerializer) MarshalEasyJSON(w *jwriter.Writer) { - easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers32(w, v) + easyjsonDdc0fdbeEncodeGithubComDataDogDatadogAgentPkgSecuritySerializers33(w, v) } // UnmarshalEasyJSON supports easyjson.Unmarshaler interface func (v *AnomalyDetectionSyscallEventSerializer) UnmarshalEasyJSON(l *jlexer.Lexer) { - easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers32(l, v) + easyjsonDdc0fdbeDecodeGithubComDataDogDatadogAgentPkgSecuritySerializers33(l, v) } diff --git a/pkg/security/telemetry/telemetry.go b/pkg/security/telemetry/telemetry.go index 71985fb7b4b97..2a5a2ae9e3368 100644 --- a/pkg/security/telemetry/telemetry.go +++ b/pkg/security/telemetry/telemetry.go @@ -10,6 +10,7 @@ import ( "strings" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" + "github.com/DataDog/datadog-agent/comp/dogstatsd/constants" "github.com/DataDog/datadog-agent/pkg/util/log" "github.com/DataDog/datadog-go/v5/statsd" ) @@ -47,7 +48,7 @@ func (c *ContainersTelemetry) ReportContainers(metricName string) { continue } - c.TelemetrySender.Gauge(metricName, 1.0, []string{"container_id:" + container.ID}) + c.TelemetrySender.Gauge(metricName, 1.0, []string{"container_id:" + container.ID, constants.CardinalityTagPrefix + "orch"}) } c.TelemetrySender.Commit() } diff --git a/pkg/security/tests/activity_dumps_test.go b/pkg/security/tests/activity_dumps_test.go index 7c957aa7e2e3f..c64e05a3b76ca 100644 --- a/pkg/security/tests/activity_dumps_test.go +++ b/pkg/security/tests/activity_dumps_test.go @@ -16,14 +16,13 @@ import ( "testing" "time" - imdsutils "github.com/DataDog/datadog-agent/pkg/security/tests/imds_utils" - "github.com/DataDog/datadog-agent/pkg/security/ebpf/kernel" "github.com/DataDog/datadog-agent/pkg/security/secl/containerutils" "github.com/DataDog/datadog-agent/pkg/security/secl/model" "github.com/DataDog/datadog-agent/pkg/security/secl/rules" activity_tree "github.com/DataDog/datadog-agent/pkg/security/security_profile/activity_tree" activitydump "github.com/DataDog/datadog-agent/pkg/security/security_profile/dump" + "github.com/DataDog/datadog-agent/pkg/security/tests/testutils" "github.com/stretchr/testify/assert" ) @@ -108,10 +107,10 @@ func TestActivityDumps(t *testing.T) { var requestFound, responseFound bool for _, node := range nodes { for evt := range node.IMDSEvents { - if evt.Type == "request" && evt.URL == imdsutils.IMDSSecurityCredentialsURL { + if evt.Type == "request" && evt.URL == testutils.IMDSSecurityCredentialsURL { requestFound = true } - if evt.Type == "response" && evt.AWS.SecurityCredentials.AccessKeyID == imdsutils.AWSSecurityCredentialsAccessKeyIDTestValue { + if evt.Type == "response" && evt.AWS.SecurityCredentials.AccessKeyID == testutils.AWSSecurityCredentialsAccessKeyIDTestValue { responseFound = true } } diff --git a/pkg/security/tests/connect_test.go b/pkg/security/tests/connect_test.go new file mode 100644 index 0000000000000..76940c6769780 --- /dev/null +++ b/pkg/security/tests/connect_test.go @@ -0,0 +1,176 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build linux && functionaltests + +// Package tests holds tests related files +package tests + +import ( + "context" + "fmt" + "net" + "testing" + + "golang.org/x/sys/unix" + + "github.com/stretchr/testify/assert" + + "github.com/DataDog/datadog-agent/pkg/security/secl/model" + "github.com/DataDog/datadog-agent/pkg/security/secl/rules" +) + +func TestConnectEvent(t *testing.T) { + SkipIfNotAvailable(t) + + ruleDefs := []*rules.RuleDefinition{ + { + ID: "test_connect_af_inet", + Expression: `connect.server.addr.family == AF_INET && process.file.name == "syscall_tester"`, + }, + { + ID: "test_connect_af_inet6", + Expression: `connect.server.addr.family == AF_INET6 && process.file.name == "syscall_tester"`, + }, + } + + test, err := newTestModule(t, nil, ruleDefs) + if err != nil { + t.Fatal(err) + } + defer test.Close() + + syscallTester, err := loadSyscallTester(t, test, "syscall_tester") + if err != nil { + t.Fatal(err) + } + + t.Run("connect-af-inet-any-tcp-success", func(t *testing.T) { + done := make(chan struct{}) + defer close(done) + go func() { + err := bindAndAcceptConnection("tcp", ":4242", done) + if err != nil { + t.Fatal(err) + } + }() + + test.WaitSignal(t, func() error { + return runSyscallTesterFunc(context.Background(), t, syscallTester, "connect", "AF_INET", "any", "tcp") + }, func(event *model.Event, r *rules.Rule) { + assert.Equal(t, "connect", event.GetType(), "wrong event type") + assert.Equal(t, uint16(unix.AF_INET), event.Connect.AddrFamily, "wrong address family") + assert.Equal(t, uint16(4242), event.Connect.Addr.Port, "wrong address port") + assert.Equal(t, string("0.0.0.0/32"), event.Connect.Addr.IPNet.String(), "wrong address") + assert.Equal(t, int64(0), event.Connect.Retval, "wrong retval") + test.validateConnectSchema(t, event) + }) + }) + + t.Run("connect-af-inet-any-udp-success", func(t *testing.T) { + done := make(chan struct{}) + defer close(done) + go func() { + err := bindAndAcceptConnection("udp", ":4242", done) + if err != nil { + t.Fatal(err) + } + }() + + test.WaitSignal(t, func() error { + return runSyscallTesterFunc(context.Background(), t, syscallTester, "connect", "AF_INET", "any", "udp") + }, func(event *model.Event, r *rules.Rule) { + assert.Equal(t, "connect", event.GetType(), "wrong event type") + assert.Equal(t, uint16(unix.AF_INET), event.Connect.AddrFamily, "wrong address family") + assert.Equal(t, uint16(4242), event.Connect.Addr.Port, "wrong address port") + assert.Equal(t, string("0.0.0.0/32"), event.Connect.Addr.IPNet.String(), "wrong address") + assert.Equal(t, int64(0), event.Connect.Retval, "wrong retval") + test.validateConnectSchema(t, event) + }) + }) + + t.Run("connect-af-inet6-any-tcp-success", func(t *testing.T) { + done := make(chan struct{}) + defer close(done) + go func() { + err := bindAndAcceptConnection("tcp", ":4242", done) + if err != nil { + t.Fatal(err) + } + }() + + test.WaitSignal(t, func() error { + return runSyscallTesterFunc(context.Background(), t, syscallTester, "connect", "AF_INET6", "any", "tcp") + }, func(event *model.Event, r *rules.Rule) { + assert.Equal(t, "connect", event.GetType(), "wrong event type") + assert.Equal(t, uint16(unix.AF_INET6), event.Connect.AddrFamily, "wrong address family") + assert.Equal(t, uint16(4242), event.Connect.Addr.Port, "wrong address port") + assert.Equal(t, string("::/128"), event.Connect.Addr.IPNet.String(), "wrong address") + assert.Equal(t, int64(0), event.Connect.Retval, "wrong retval") + test.validateConnectSchema(t, event) + }) + }) + + t.Run("connect-af-inet6-any-udp-success", func(t *testing.T) { + done := make(chan struct{}) + defer close(done) + go func() { + err := bindAndAcceptConnection("udp", ":4242", done) + if err != nil { + t.Fatal(err) + } + }() + + test.WaitSignal(t, func() error { + return runSyscallTesterFunc(context.Background(), t, syscallTester, "connect", "AF_INET6", "any", "udp") + }, func(event *model.Event, r *rules.Rule) { + assert.Equal(t, "connect", event.GetType(), "wrong event type") + assert.Equal(t, uint16(unix.AF_INET6), event.Connect.AddrFamily, "wrong address family") + assert.Equal(t, uint16(4242), event.Connect.Addr.Port, "wrong address port") + assert.Equal(t, string("::/128"), event.Connect.Addr.IPNet.String(), "wrong address") + assert.Equal(t, int64(0), event.Connect.Retval, "wrong retval") + test.validateConnectSchema(t, event) + }) + }) + +} + +func bindAndAcceptConnection(proto, address string, done chan struct{}) error { + switch proto { + case "tcp": + listener, err := net.Listen(proto, address) + if err != nil { + return fmt.Errorf("failed to bind to %s:%s: %w", proto, address, err) + } + defer listener.Close() + + // Start a goroutine to accept connections continuously + go func() { + for { + c, err := listener.Accept() + if err != nil { + fmt.Printf("accept error: %v\n", err) + return + } + fmt.Println("Connection accepted") + defer c.Close() + } + }() + + case "udp", "unixgram": + conn, err := net.ListenPacket(proto, address) + if err != nil { + return fmt.Errorf("failed to bind to %s:%s: %w", proto, address, err) + } + defer conn.Close() + + default: + return fmt.Errorf("unsupported protocol: %s", proto) + } + + // Wait for the test to complete before returning + <-done + return nil +} diff --git a/pkg/security/tests/event_test.go b/pkg/security/tests/event_test.go index e1f9280d204da..621cc585ba762 100644 --- a/pkg/security/tests/event_test.go +++ b/pkg/security/tests/event_test.go @@ -237,7 +237,7 @@ func TestEventIteratorRegister(t *testing.T) { }, { ID: "test_register_2", - Expression: fmt.Sprintf(`open.file.path == "{{.Root}}/test-register" && process.ancestors[A].file.path == "%s" && process.ancestors[A].pid == 1`, pid1Path), + Expression: fmt.Sprintf(`open.file.path == "{{.Root}}/test-register-2" && process.ancestors[A].file.path == "%s" && process.ancestors[A].pid == 1`, pid1Path), }, } @@ -253,6 +253,12 @@ func TestEventIteratorRegister(t *testing.T) { } defer os.Remove(testFile) + testFile2, _, err := test.Path("test-register-2") + if err != nil { + t.Fatal(err) + } + defer os.Remove(testFile2) + syscallTester, err := loadSyscallTester(t, test, "syscall_tester") if err != nil { t.Fatal(err) @@ -268,7 +274,7 @@ func TestEventIteratorRegister(t *testing.T) { t.Run("pid1", func(t *testing.T) { test.WaitSignal(t, func() error { - f, err := os.Create(testFile) + f, err := os.Create(testFile2) if err != nil { return err } diff --git a/pkg/security/tests/imds_test.go b/pkg/security/tests/imds_test.go index 31d100c15c8c0..6f08b62d3a2bb 100644 --- a/pkg/security/tests/imds_test.go +++ b/pkg/security/tests/imds_test.go @@ -16,12 +16,13 @@ import ( "syscall" "testing" + "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/pkg/config/env" "github.com/DataDog/datadog-agent/pkg/security/ebpf/kernel" "github.com/DataDog/datadog-agent/pkg/security/secl/model" "github.com/DataDog/datadog-agent/pkg/security/secl/rules" - "github.com/DataDog/datadog-agent/pkg/security/tests/imds_utils" - "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/pkg/security/tests/testutils" ) func TestAWSIMDSv1Request(t *testing.T) { @@ -51,21 +52,21 @@ func TestAWSIMDSv1Request(t *testing.T) { } // create dummy interface - dummy, err := imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) if err != nil { t.Fatal(err) } defer func() { - if err = imdsutils.RemoveDummyInterface(dummy); err != nil { + if err = testutils.RemoveDummyInterface(dummy); err != nil { t.Fatal(err) } }() // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err = imdsutils.StopIMDSserver(imdsServer); err != nil { + if err = testutils.StopIMDSserver(imdsServer); err != nil { t.Fatal(err) } }() @@ -78,7 +79,7 @@ func TestAWSIMDSv1Request(t *testing.T) { t.Run("aws_imds_v1_request", func(t *testing.T) { test.WaitSignal(t, func() error { - response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL)) + response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL)) if err != nil { return fmt.Errorf("failed to query IMDS server: %v", err) } @@ -89,7 +90,7 @@ func TestAWSIMDSv1Request(t *testing.T) { assertTriggeredRule(t, rule, "test_rule_aws_imds_v1_request") assert.Equal(t, "request", event.IMDS.Type, "wrong IMDS request type") assert.Equal(t, imdsServerAddr, event.IMDS.Host, "wrong IMDS request Host") - assert.Equal(t, imdsutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") + assert.Equal(t, testutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") assert.Equal(t, "Go-http-client/1.1", event.IMDS.UserAgent, "wrong IMDS request user agent") test.validateIMDSSchema(t, event) @@ -129,21 +130,21 @@ func TestAWSIMDSv1Response(t *testing.T) { } // create dummy interface - dummy, err := imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) if err != nil { t.Fatal(err) } defer func() { - if err = imdsutils.RemoveDummyInterface(dummy); err != nil { + if err = testutils.RemoveDummyInterface(dummy); err != nil { t.Fatal(err) } }() // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err = imdsutils.StopIMDSserver(imdsServer); err != nil { + if err = testutils.StopIMDSserver(imdsServer); err != nil { t.Fatal(err) } }() @@ -156,7 +157,7 @@ func TestAWSIMDSv1Response(t *testing.T) { t.Run("aws_imds_v1_response", func(t *testing.T) { test.WaitSignal(t, func() error { - response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL)) + response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL)) if err != nil { return fmt.Errorf("failed to query IMDS server: %v", err) } @@ -166,12 +167,12 @@ func TestAWSIMDSv1Response(t *testing.T) { }, func(event *model.Event, rule *rules.Rule) { assertTriggeredRule(t, rule, "test_rule_aws_imds_v1_response") assert.Equal(t, "response", event.IMDS.Type, "wrong IMDS request Type") - assert.Equal(t, imdsutils.AWSIMDSServerTestValue, event.IMDS.Server, "wrong IMDS request Server") - assert.Equal(t, imdsutils.AWSSecurityCredentialsTypeTestValue, event.IMDS.AWS.SecurityCredentials.Type, "wrong IMDS request AWS Security Credentials Type") - assert.Equal(t, imdsutils.AWSSecurityCredentialsExpirationTestValue, event.IMDS.AWS.SecurityCredentials.ExpirationRaw, "wrong IMDS request AWS Security Credentials ExpirationRaw") - assert.Equal(t, imdsutils.AWSSecurityCredentialsAccessKeyIDTestValue, event.IMDS.AWS.SecurityCredentials.AccessKeyID, "wrong IMDS request AWS Security Credentials AccessKeyID") - assert.Equal(t, imdsutils.AWSSecurityCredentialsCodeTestValue, event.IMDS.AWS.SecurityCredentials.Code, "wrong IMDS request AWS Security Credentials Code") - assert.Equal(t, imdsutils.AWSSecurityCredentialsLastUpdatedTestValue, event.IMDS.AWS.SecurityCredentials.LastUpdated, "wrong IMDS request AWS Security Credentials LastUpdated") + assert.Equal(t, testutils.AWSIMDSServerTestValue, event.IMDS.Server, "wrong IMDS request Server") + assert.Equal(t, testutils.AWSSecurityCredentialsTypeTestValue, event.IMDS.AWS.SecurityCredentials.Type, "wrong IMDS request AWS Security Credentials Type") + assert.Equal(t, testutils.AWSSecurityCredentialsExpirationTestValue, event.IMDS.AWS.SecurityCredentials.ExpirationRaw, "wrong IMDS request AWS Security Credentials ExpirationRaw") + assert.Equal(t, testutils.AWSSecurityCredentialsAccessKeyIDTestValue, event.IMDS.AWS.SecurityCredentials.AccessKeyID, "wrong IMDS request AWS Security Credentials AccessKeyID") + assert.Equal(t, testutils.AWSSecurityCredentialsCodeTestValue, event.IMDS.AWS.SecurityCredentials.Code, "wrong IMDS request AWS Security Credentials Code") + assert.Equal(t, testutils.AWSSecurityCredentialsLastUpdatedTestValue, event.IMDS.AWS.SecurityCredentials.LastUpdated, "wrong IMDS request AWS Security Credentials LastUpdated") test.validateIMDSSchema(t, event) }) @@ -205,21 +206,21 @@ func TestNoAWSIMDSv1Response(t *testing.T) { } // create dummy interface - dummy, err := imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) if err != nil { t.Fatal(err) } defer func() { - if err = imdsutils.RemoveDummyInterface(dummy); err != nil { + if err = testutils.RemoveDummyInterface(dummy); err != nil { t.Fatal(err) } }() // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err = imdsutils.StopIMDSserver(imdsServer); err != nil { + if err = testutils.StopIMDSserver(imdsServer); err != nil { t.Fatal(err) } }() @@ -232,7 +233,7 @@ func TestNoAWSIMDSv1Response(t *testing.T) { t.Run("no_aws_imds_v1_response", func(t *testing.T) { if err := waitForIMDSResponseProbeEvent(test, func() error { - response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL)) + response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL)) if err != nil { return fmt.Errorf("failed to query IMDS server: %v", err) } @@ -277,21 +278,21 @@ func TestAWSIMDSv2Request(t *testing.T) { } // create dummy interface - dummy, err := imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) if err != nil { t.Fatal(err) } defer func() { - if err = imdsutils.RemoveDummyInterface(dummy); err != nil { + if err = testutils.RemoveDummyInterface(dummy); err != nil { t.Fatal(err) } }() // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err = imdsutils.StopIMDSserver(imdsServer); err != nil { + if err = testutils.StopIMDSserver(imdsServer); err != nil { t.Fatal(err) } }() @@ -304,7 +305,7 @@ func TestAWSIMDSv2Request(t *testing.T) { t.Run("aws_imds_v2_request", func(t *testing.T) { test.WaitSignal(t, func() error { - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL), nil) if err != nil { return fmt.Errorf("failed to instantiate request: %v", err) } @@ -320,7 +321,7 @@ func TestAWSIMDSv2Request(t *testing.T) { assertTriggeredRule(t, rule, "test_rule_aws_imds_v2_request") assert.Equal(t, "request", event.IMDS.Type, "wrong IMDS request type") assert.Equal(t, imdsServerAddr, event.IMDS.Host, "wrong IMDS request Host") - assert.Equal(t, imdsutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") + assert.Equal(t, testutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") assert.Equal(t, "Go-http-client/1.1", event.IMDS.UserAgent, "wrong IMDS request user agent") test.validateIMDSSchema(t, event) @@ -355,21 +356,21 @@ func TestGCPIMDS(t *testing.T) { } // create dummy interface - dummy, err := imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) if err != nil { t.Fatal(err) } defer func() { - if err = imdsutils.RemoveDummyInterface(dummy); err != nil { + if err = testutils.RemoveDummyInterface(dummy); err != nil { t.Fatal(err) } }() // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err = imdsutils.StopIMDSserver(imdsServer); err != nil { + if err = testutils.StopIMDSserver(imdsServer); err != nil { t.Fatal(err) } }() @@ -382,7 +383,7 @@ func TestGCPIMDS(t *testing.T) { t.Run("gcp_imds_request", func(t *testing.T) { test.WaitSignal(t, func() error { - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL), nil) if err != nil { return fmt.Errorf("failed to instantiate request: %v", err) } @@ -398,7 +399,7 @@ func TestGCPIMDS(t *testing.T) { assertTriggeredRule(t, rule, "test_rule_gcp_imds_request") assert.Equal(t, "request", event.IMDS.Type, "wrong IMDS request type") assert.Equal(t, imdsServerAddr, event.IMDS.Host, "wrong IMDS request Host") - assert.Equal(t, imdsutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") + assert.Equal(t, testutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") assert.Equal(t, "Go-http-client/1.1", event.IMDS.UserAgent, "wrong IMDS request user agent") test.validateIMDSSchema(t, event) @@ -433,21 +434,21 @@ func TestAzureIMDS(t *testing.T) { } // create dummy interface - dummy, err := imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) if err != nil { t.Fatal(err) } defer func() { - if err = imdsutils.RemoveDummyInterface(dummy); err != nil { + if err = testutils.RemoveDummyInterface(dummy); err != nil { t.Fatal(err) } }() // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err = imdsutils.StopIMDSserver(imdsServer); err != nil { + if err = testutils.StopIMDSserver(imdsServer); err != nil { t.Fatal(err) } }() @@ -460,7 +461,7 @@ func TestAzureIMDS(t *testing.T) { t.Run("azure_imds_request", func(t *testing.T) { test.WaitSignal(t, func() error { - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL), nil) if err != nil { return fmt.Errorf("failed to instantiate request: %v", err) } @@ -476,7 +477,7 @@ func TestAzureIMDS(t *testing.T) { assertTriggeredRule(t, rule, "test_rule_azure_imds_request") assert.Equal(t, "request", event.IMDS.Type, "wrong IMDS request type") assert.Equal(t, imdsServerAddr, event.IMDS.Host, "wrong IMDS request Host") - assert.Equal(t, imdsutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") + assert.Equal(t, testutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") assert.Equal(t, "Go-http-client/1.1", event.IMDS.UserAgent, "wrong IMDS request user agent") test.validateIMDSSchema(t, event) @@ -511,21 +512,21 @@ func TestIBMIMDS(t *testing.T) { } // create dummy interface - dummy, err := imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) if err != nil { t.Fatal(err) } defer func() { - if err = imdsutils.RemoveDummyInterface(dummy); err != nil { + if err = testutils.RemoveDummyInterface(dummy); err != nil { t.Fatal(err) } }() // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err = imdsutils.StopIMDSserver(imdsServer); err != nil { + if err = testutils.StopIMDSserver(imdsServer); err != nil { t.Fatal(err) } }() @@ -538,7 +539,7 @@ func TestIBMIMDS(t *testing.T) { t.Run("ibm_imds_request", func(t *testing.T) { test.WaitSignal(t, func() error { - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL), nil) if err != nil { return fmt.Errorf("failed to instantiate request: %v", err) } @@ -554,7 +555,7 @@ func TestIBMIMDS(t *testing.T) { assertTriggeredRule(t, rule, "test_rule_idbm_imds_request") assert.Equal(t, "request", event.IMDS.Type, "wrong IMDS request type") assert.Equal(t, imdsServerAddr, event.IMDS.Host, "wrong IMDS request Host") - assert.Equal(t, imdsutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") + assert.Equal(t, testutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") assert.Equal(t, "Go-http-client/1.1", event.IMDS.UserAgent, "wrong IMDS request user agent") test.validateIMDSSchema(t, event) @@ -589,21 +590,21 @@ func TestOracleIMDS(t *testing.T) { } // create dummy interface - dummy, err := imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) if err != nil { t.Fatal(err) } defer func() { - if err = imdsutils.RemoveDummyInterface(dummy); err != nil { + if err = testutils.RemoveDummyInterface(dummy); err != nil { t.Fatal(err) } }() // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err = imdsutils.StopIMDSserver(imdsServer); err != nil { + if err = testutils.StopIMDSserver(imdsServer); err != nil { t.Fatal(err) } }() @@ -616,7 +617,7 @@ func TestOracleIMDS(t *testing.T) { t.Run("oracle_imds_request", func(t *testing.T) { test.WaitSignal(t, func() error { - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL), nil) + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL), nil) if err != nil { return fmt.Errorf("failed to instantiate request: %v", err) } @@ -632,7 +633,7 @@ func TestOracleIMDS(t *testing.T) { assertTriggeredRule(t, rule, "test_rule_oracle_imds_request") assert.Equal(t, "request", event.IMDS.Type, "wrong IMDS request type") assert.Equal(t, imdsServerAddr, event.IMDS.Host, "wrong IMDS request Host") - assert.Equal(t, imdsutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") + assert.Equal(t, testutils.IMDSSecurityCredentialsURL, event.IMDS.URL, "wrong IMDS request URL") assert.Equal(t, "Go-http-client/1.1", event.IMDS.UserAgent, "wrong IMDS request user agent") test.validateIMDSSchema(t, event) @@ -672,21 +673,21 @@ func TestIMDSProcessContext(t *testing.T) { } // create dummy interface - dummy, err := imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) if err != nil { t.Fatal(err) } defer func() { - if err = imdsutils.RemoveDummyInterface(dummy); err != nil { + if err = testutils.RemoveDummyInterface(dummy); err != nil { t.Fatal(err) } }() // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err = imdsutils.StopIMDSserver(imdsServer); err != nil { + if err = testutils.StopIMDSserver(imdsServer); err != nil { t.Fatal(err) } }() @@ -707,7 +708,7 @@ func TestIMDSProcessContext(t *testing.T) { test.WaitSignal(t, func() error { // make request first to populate process cache - response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL)) + response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL)) if err != nil { return fmt.Errorf("failed to query IMDS server: %v", err) } @@ -725,11 +726,11 @@ func TestIMDSProcessContext(t *testing.T) { assert.NotNil(t, event.ProcessCacheEntry.Process.AWSSecurityCredentials, "empty IMDS context") if len(event.ProcessCacheEntry.Process.AWSSecurityCredentials) > 0 { creds := event.ProcessCacheEntry.Process.AWSSecurityCredentials[0] - assert.Equal(t, imdsutils.AWSSecurityCredentialsTypeTestValue, creds.Type, "wrong IMDS context AWS Security Credentials Type") - assert.Equal(t, imdsutils.AWSSecurityCredentialsExpirationTestValue, creds.ExpirationRaw, "wrong IMDS context AWS Security Credentials ExpirationRaw") - assert.Equal(t, imdsutils.AWSSecurityCredentialsAccessKeyIDTestValue, creds.AccessKeyID, "wrong IMDS context AWS Security Credentials AccessKeyID") - assert.Equal(t, imdsutils.AWSSecurityCredentialsCodeTestValue, creds.Code, "wrong IMDS context AWS Security Credentials Code") - assert.Equal(t, imdsutils.AWSSecurityCredentialsLastUpdatedTestValue, creds.LastUpdated, "wrong IMDS context AWS Security Credentials LastUpdated") + assert.Equal(t, testutils.AWSSecurityCredentialsTypeTestValue, creds.Type, "wrong IMDS context AWS Security Credentials Type") + assert.Equal(t, testutils.AWSSecurityCredentialsExpirationTestValue, creds.ExpirationRaw, "wrong IMDS context AWS Security Credentials ExpirationRaw") + assert.Equal(t, testutils.AWSSecurityCredentialsAccessKeyIDTestValue, creds.AccessKeyID, "wrong IMDS context AWS Security Credentials AccessKeyID") + assert.Equal(t, testutils.AWSSecurityCredentialsCodeTestValue, creds.Code, "wrong IMDS context AWS Security Credentials Code") + assert.Equal(t, testutils.AWSSecurityCredentialsLastUpdatedTestValue, creds.LastUpdated, "wrong IMDS context AWS Security Credentials LastUpdated") } test.validateOpenSchema(t, event) diff --git a/pkg/security/tests/module_tester.go b/pkg/security/tests/module_tester.go index 1b4b9f85399b4..62f9a99fac628 100644 --- a/pkg/security/tests/module_tester.go +++ b/pkg/security/tests/module_tester.go @@ -773,6 +773,7 @@ func genTestConfigs(cfgDir string, opts testOpts) (*emconfig.Config, *secconfig. "EBPFLessEnabled": ebpfLessEnabled, "FIMEnabled": opts.enableFIM, // should only be enabled/disabled on windows "NetworkIngressEnabled": opts.networkIngressEnabled, + "NetworkRawPacketEnabled": opts.networkRawPacketEnabled, "OnDemandRateLimiterEnabled": !opts.disableOnDemandRateLimiter, "EnforcementExcludeBinary": opts.enforcementExcludeBinary, "EnforcementDisarmerContainerEnabled": opts.enforcementDisarmerContainerEnabled, diff --git a/pkg/security/tests/module_tester_linux.go b/pkg/security/tests/module_tester_linux.go index 9402de02605df..86939f3db10cc 100644 --- a/pkg/security/tests/module_tester_linux.go +++ b/pkg/security/tests/module_tester_linux.go @@ -78,6 +78,8 @@ event_monitoring_config: enabled: true ingress: enabled: {{ .NetworkIngressEnabled }} + raw_packet: + enabled: {{ .NetworkRawPacketEnabled}} flush_discarder_window: 0 {{if .DisableFilters}} enable_kernel_filters: false @@ -808,7 +810,9 @@ func newTestModuleWithOnDemandProbes(t testing.TB, onDemandHooks []rules.OnDeman testMod.RegisterRuleEventHandler(func(e *model.Event, r *rules.Rule) { opts.staticOpts.snapshotRuleMatchHandler(testMod, e, r) }) - defer testMod.RegisterRuleEventHandler(nil) + t.Cleanup(func() { + testMod.RegisterRuleEventHandler(nil) + }) } if err := testMod.eventMonitor.Start(); err != nil { @@ -816,7 +820,7 @@ func newTestModuleWithOnDemandProbes(t testing.TB, onDemandHooks []rules.OnDeman } if ruleSetloadedErr.ErrorOrNil() != nil { - defer testMod.Close() + testMod.Close() return nil, ruleSetloadedErr.ErrorOrNil() } diff --git a/pkg/security/tests/network_test.go b/pkg/security/tests/network_test.go index 61e88603851f6..6fde6aa80657f 100644 --- a/pkg/security/tests/network_test.go +++ b/pkg/security/tests/network_test.go @@ -12,6 +12,8 @@ import ( "fmt" "net" "net/netip" + "os" + "path/filepath" "strings" "testing" @@ -23,6 +25,7 @@ import ( "github.com/DataDog/datadog-agent/pkg/security/ebpf/kernel" "github.com/DataDog/datadog-agent/pkg/security/secl/model" "github.com/DataDog/datadog-agent/pkg/security/secl/rules" + "github.com/DataDog/datadog-agent/pkg/security/tests/testutils" ) func TestNetworkCIDR(t *testing.T) { @@ -72,3 +75,77 @@ func TestNetworkCIDR(t *testing.T) { }) }) } + +func TestRawPacket(t *testing.T) { + SkipIfNotAvailable(t) + + checkKernelCompatibility(t, "RHEL, SLES, SUSE and Oracle kernels", func(kv *kernel.Version) bool { + // TODO: Oracle because we are missing offsets + // OpenSUSE distributions are missing the dummy kernel module + return kv.IsRH7Kernel() || kv.IsOracleUEKKernel() || kv.IsSLESKernel() || kv.IsOpenSUSELeapKernel() + }) + + if testEnvironment != DockerEnvironment && !env.IsContainerized() { + if out, err := loadModule("veth"); err != nil { + t.Fatalf("couldn't load 'veth' module: %s, %v", string(out), err) + } + } + + executable, err := os.Executable() + if err != nil { + t.Fatal(err) + } + + testDestIP := "192.168.172.171" + testUDPDestPort := uint16(12345) + + // create dummy interface + dummy, err := testutils.CreateDummyInterface(testutils.CSMDummyInterface, testDestIP+"/32") + if err != nil { + t.Fatal(err) + } + defer func() { + if err = testutils.RemoveDummyInterface(dummy); err != nil { + t.Fatal(err) + } + }() + + rule := &rules.RuleDefinition{ + ID: "test_rule_raw_packet_udp4", + Expression: fmt.Sprintf(`packet.filter == "ip dst %s and udp dst port %d" && process.file.name == "%s"`, testDestIP, testUDPDestPort, filepath.Base(executable)), + } + + test, err := newTestModule(t, nil, []*rules.RuleDefinition{rule}, withStaticOpts(testOpts{networkRawPacketEnabled: true})) + if err != nil { + t.Fatal(err) + } + defer test.Close() + + t.Run("udp4", func(t *testing.T) { + test.WaitSignal(t, func() error { + conn, err := net.Dial("udp4", fmt.Sprintf("%s:%d", testDestIP, testUDPDestPort)) + if err != nil { + return err + } + defer conn.Close() + + _, err = conn.Write([]byte("hello")) + if err != nil { + return err + } + + return nil + }, func(event *model.Event, rule *rules.Rule) { + assert.Equal(t, "packet", event.GetType(), "wrong event type") + assertTriggeredRule(t, rule, "test_rule_raw_packet_udp4") + assertFieldEqual(t, event, "packet.l3_protocol", int(model.EthPIP)) + _, expectedIPNet, err := net.ParseCIDR(testDestIP + "/32") + if err != nil { + t.Fatal(err) + } + assertFieldEqual(t, event, "packet.destination.ip", *expectedIPNet) + assertFieldEqual(t, event, "packet.l4_protocol", int(model.IPProtoUDP)) + assertFieldEqual(t, event, "packet.destination.port", int(testUDPDestPort)) + }) + }) +} diff --git a/pkg/security/tests/process_test.go b/pkg/security/tests/process_test.go index 405db99859fc0..2cd713feb871a 100644 --- a/pkg/security/tests/process_test.go +++ b/pkg/security/tests/process_test.go @@ -1727,7 +1727,7 @@ func TestProcessIsThread(t *testing.T) { t.Fatal(err) } - t.Run("fork-isthread", func(t *testing.T) { + t.Run("fork-is-not-exec", func(t *testing.T) { test.WaitSignal(t, func() error { args := []string{"fork"} cmd := exec.Command(syscallTester, args...) @@ -1738,11 +1738,11 @@ func TestProcessIsThread(t *testing.T) { assert.Equal(t, "syscall_tester", event.ProcessContext.FileEvent.BasenameStr, "wrong process file basename") assert.Equal(t, "syscall_tester", event.ProcessContext.Ancestor.ProcessContext.FileEvent.BasenameStr, "wrong parent process file basename") assert.Equal(t, "syscall_tester", event.ProcessContext.Parent.FileEvent.BasenameStr, "wrong parent process file basename") - assert.True(t, event.ProcessContext.IsThread, "process should be marked as being a thread") + assert.False(t, event.ProcessContext.IsExec, "process shouldn't be marked as being an exec") }) }) - t.Run("exec-isnotthread", func(t *testing.T) { + t.Run("exec-is-exec", func(t *testing.T) { test.WaitSignal(t, func() error { args := []string{"fork", "exec"} cmd := exec.Command(syscallTester, args...) @@ -1752,7 +1752,7 @@ func TestProcessIsThread(t *testing.T) { assertTriggeredRule(t, rule, "test_process_exec_is_not_thread") assert.Equal(t, "syscall_tester", event.ProcessContext.Ancestor.ProcessContext.FileEvent.BasenameStr, "wrong parent process file basename") assert.Equal(t, "syscall_tester", event.ProcessContext.Parent.FileEvent.BasenameStr, "wrong parent process file basename") - assert.False(t, event.ProcessContext.IsThread, "process should be marked as not being a thread") + assert.True(t, event.ProcessContext.IsExec, "process should be marked as being an exec") }) }) } diff --git a/pkg/security/tests/schemas.go b/pkg/security/tests/schemas.go index cb63a6af1de6a..bfaae44321d15 100644 --- a/pkg/security/tests/schemas.go +++ b/pkg/security/tests/schemas.go @@ -306,6 +306,12 @@ func (tm *testModule) validateBindSchema(t *testing.T, event *model.Event) bool return tm.validateEventSchema(t, event, "file:///schemas/bind.schema.json") } +//nolint:deadcode,unused +func (tm *testModule) validateConnectSchema(t *testing.T, event *model.Event) bool { + t.Helper() + return tm.validateEventSchema(t, event, "file:///schemas/connect.schema.json") +} + //nolint:deadcode,unused func (tm *testModule) validateMountSchema(t *testing.T, event *model.Event) bool { if ebpfLessEnabled { diff --git a/pkg/security/tests/schemas/connect.schema.json b/pkg/security/tests/schemas/connect.schema.json new file mode 100644 index 0000000000000..6f94bc0852e89 --- /dev/null +++ b/pkg/security/tests/schemas/connect.schema.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "connect.json", + "type": "object", + "allOf": [ + { + "$ref": "/schemas/event.json" + }, + { + "$ref": "/schemas/usr.json" + }, + { + "$ref": "/schemas/process_context.json" + }, + { + "date": { + "$ref": "/schemas/datetime.json" + } + }, + { + "properties": { + "connect": { + "type": "object", + "required": [ + "addr" + ], + "properties": { + "addr": { + "type": "object", + "required": [ + "family", + "ip", + "port" + ], + "properties": { + "family": { + "type": "string" + }, + "ip": { + "type": "string" + }, + "port": { + "type": "integer" + } + } + } + } + } + } + } + ] +} \ No newline at end of file diff --git a/pkg/security/tests/snapshot_replay_test.go b/pkg/security/tests/snapshot_replay_test.go index 3fcff7e97c13c..35af42551c8dc 100644 --- a/pkg/security/tests/snapshot_replay_test.go +++ b/pkg/security/tests/snapshot_replay_test.go @@ -8,9 +8,12 @@ package tests import ( + "os/exec" "testing" + "time" "github.com/stretchr/testify/assert" + "go.uber.org/atomic" "github.com/DataDog/datadog-agent/pkg/security/secl/model" "github.com/DataDog/datadog-agent/pkg/security/secl/rules" @@ -24,13 +27,13 @@ func TestSnapshotReplay(t *testing.T) { Expression: "exec.comm in [\"testsuite\"]", } - var gotEvent bool + gotEvent := atomic.NewBool(false) test, err := newTestModule(t, nil, []*rules.RuleDefinition{ruleDef}, withStaticOpts(testOpts{ snapshotRuleMatchHandler: func(testMod *testModule, e *model.Event, r *rules.Rule) { assertTriggeredRule(t, r, "test_rule_snapshot_replay") testMod.validateExecSchema(t, e) - gotEvent = true + gotEvent.Store(true) }, })) @@ -39,5 +42,9 @@ func TestSnapshotReplay(t *testing.T) { } defer test.Close() - assert.True(t, gotEvent, "didn't get the event from snapshot") + if _, err := exec.Command("echo", "hello", "world").CombinedOutput(); err != nil { + t.Fatal(err) + } + + assert.Eventually(t, func() bool { return gotEvent.Load() }, 10*time.Second, 100*time.Millisecond, "didn't get the event from snapshot") } diff --git a/pkg/security/tests/syscall_tester/c/syscall_tester.c b/pkg/security/tests/syscall_tester/c/syscall_tester.c index 1a1cc06e800dc..85fb9d18a6695 100644 --- a/pkg/security/tests/syscall_tester/c/syscall_tester.c +++ b/pkg/security/tests/syscall_tester/c/syscall_tester.c @@ -492,6 +492,120 @@ int test_bind(int argc, char** argv) { return EXIT_FAILURE; } +int test_connect_af_inet(int argc, char** argv) { + + if (argc != 3) { + fprintf(stderr, "%s: please specify a valid command:\n", __FUNCTION__); + fprintf(stderr, "Arg1: an option for the addr in the list: any, custom_ip\n"); + fprintf(stderr, "Arg2: an option for the protocol in the list: tcp, udp\n"); + return EXIT_FAILURE; + } + + char* proto = argv[2]; + int s; + + if (!strcmp(proto, "udp")) + s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + else + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (s < 0) { + perror("socket"); + return EXIT_FAILURE; + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + + char* ip = argv[1]; + if (!strcmp(ip, "any")) { + addr.sin_addr.s_addr = htonl(INADDR_ANY); + } else if (!strcmp(ip, "custom_ip")) { + int ip32 = 0; + if (inet_pton(AF_INET, "127.0.0.1", &ip32) != 1) { + perror("inet_pton"); + return EXIT_FAILURE; + } + addr.sin_addr.s_addr = htonl(ip32); + } else { + fprintf(stderr, "Please specify an option in the list: any, broadcast, custom_ip\n"); + return EXIT_FAILURE; + } + + addr.sin_port = htons(4242); + + if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("Failed to connect to port"); + return EXIT_FAILURE; + } + + close (s); + return EXIT_SUCCESS; +} + +int test_connect_af_inet6(int argc, char** argv) { + + if (argc != 3) { + fprintf(stderr, "%s: please specify a valid command:\n", __FUNCTION__); + fprintf(stderr, "Arg1: an option for the addr in the list: any, custom_ip\n"); + fprintf(stderr, "Arg2: an option for the protocol in the list: tcp, udp\n"); + return EXIT_FAILURE; + } + + char* proto = argv[2]; + int s; + + if (!strcmp(proto, "udp")) + s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + else + s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + + if (s < 0) { + perror("socket"); + return EXIT_FAILURE; + } + + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + + char* ip = argv[1]; + if (!strcmp(ip, "any")) { + inet_pton(AF_INET6, "::", &addr.sin6_addr); + } else if (!strcmp(ip, "custom_ip")) { + inet_pton(AF_INET6, "1234:5678:90ab:cdef:0000:0000:1a1a:1337", &addr.sin6_addr); + } else { + fprintf(stderr, "Please specify an option in the list: any, broadcast, custom_ip\n"); + return EXIT_FAILURE; + } + + addr.sin6_port = htons(4242); + if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("Failed to connect to port"); + return EXIT_FAILURE; + } + + close(s); + return EXIT_SUCCESS; +} + +int test_connect(int argc, char** argv) { + if (argc <= 1) { + fprintf(stderr, "Please specify an addr_type\n"); + return EXIT_FAILURE; + } + + char* addr_family = argv[1]; + if (!strcmp(addr_family, "AF_INET")) { + return test_connect_af_inet(argc - 1, argv + 1); + } else if (!strcmp(addr_family, "AF_INET6")) { + return test_connect_af_inet6(argc - 1, argv + 1); + } + fprintf(stderr, "Specified %s addr_type is not a valid one, try: AF_INET or AF_INET6 \n", addr_family); + return EXIT_FAILURE; +} + int test_forkexec(int argc, char **argv) { if (argc == 2) { char *subcmd = argv[1]; @@ -787,6 +901,8 @@ int main(int argc, char **argv) { exit_code = self_exec(sub_argc, sub_argv); } else if (strcmp(cmd, "bind") == 0) { exit_code = test_bind(sub_argc, sub_argv); + } else if (strcmp(cmd, "connect") == 0) { + exit_code = test_connect(sub_argc, sub_argv); } else if (strcmp(cmd, "fork") == 0) { return test_forkexec(sub_argc, sub_argv); } else if (strcmp(cmd, "set-signal-handler") == 0) { diff --git a/pkg/security/tests/syscall_tester/go/syscall_go_tester.go b/pkg/security/tests/syscall_tester/go/syscall_go_tester.go index ef5833f48e406..ba61cc7f81627 100644 --- a/pkg/security/tests/syscall_tester/go/syscall_go_tester.go +++ b/pkg/security/tests/syscall_tester/go/syscall_go_tester.go @@ -27,7 +27,7 @@ import ( "github.com/DataDog/datadog-agent/cmd/cws-instrumentation/subcommands/injectcmd" "github.com/DataDog/datadog-agent/pkg/security/resolvers/usersessions" - imdsutils "github.com/DataDog/datadog-agent/pkg/security/tests/imds_utils" + "github.com/DataDog/datadog-agent/pkg/security/tests/testutils" ) var ( @@ -164,10 +164,10 @@ func SetupAndRunIMDSTest() error { func RunIMDSTest() error { // create fake IMDS server - imdsServerAddr := fmt.Sprintf("%s:%v", imdsutils.IMDSTestServerIP, imdsutils.IMDSTestServerPort) - imdsServer := imdsutils.CreateIMDSServer(imdsServerAddr) + imdsServerAddr := fmt.Sprintf("%s:%v", testutils.IMDSTestServerIP, testutils.IMDSTestServerPort) + imdsServer := testutils.CreateIMDSServer(imdsServerAddr) defer func() { - if err := imdsutils.StopIMDSserver(imdsServer); err != nil { + if err := testutils.StopIMDSserver(imdsServer); err != nil { panic(err) } }() @@ -176,7 +176,7 @@ func RunIMDSTest() error { time.Sleep(5 * time.Second) // make IMDS request - response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, imdsutils.IMDSSecurityCredentialsURL)) + response, err := http.Get(fmt.Sprintf("http://%s%s", imdsServerAddr, testutils.IMDSSecurityCredentialsURL)) if err != nil { return fmt.Errorf("failed to query IMDS server: %v", err) } @@ -185,11 +185,11 @@ func RunIMDSTest() error { func SetupIMDSTest() (*netlink.Dummy, error) { // create dummy interface - return imdsutils.CreateDummyInterface(imdsutils.IMDSTestServerIP, imdsutils.CSMDummyInterface) + return testutils.CreateDummyInterface(testutils.CSMDummyInterface, testutils.IMDSTestServerCIDR) } func CleanupIMDSTest(dummy *netlink.Dummy) error { - return imdsutils.RemoveDummyInterface(dummy) + return testutils.RemoveDummyInterface(dummy) } func RunSyscallDriftTest() error { @@ -320,7 +320,7 @@ func main() { if cleanupIMDSTest { if err := CleanupIMDSTest(&netlink.Dummy{ LinkAttrs: netlink.LinkAttrs{ - Name: imdsutils.CSMDummyInterface, + Name: testutils.CSMDummyInterface, }, }); err != nil { panic(err) diff --git a/pkg/security/tests/testopts.go b/pkg/security/tests/testopts.go index bf86b8ea89e9c..7b6b34d1a5b80 100644 --- a/pkg/security/tests/testopts.go +++ b/pkg/security/tests/testopts.go @@ -61,6 +61,7 @@ type testOpts struct { snapshotRuleMatchHandler func(*testModule, *model.Event, *rules.Rule) enableFIM bool // only valid on windows networkIngressEnabled bool + networkRawPacketEnabled bool disableOnDemandRateLimiter bool ebpfLessEnabled bool dontWaitEBPFLessClient bool @@ -147,6 +148,7 @@ func (to testOpts) Equal(opts testOpts) bool { to.snapshotRuleMatchHandler == nil && opts.snapshotRuleMatchHandler == nil && to.preStartCallback == nil && opts.preStartCallback == nil && to.networkIngressEnabled == opts.networkIngressEnabled && + to.networkRawPacketEnabled == opts.networkRawPacketEnabled && to.disableOnDemandRateLimiter == opts.disableOnDemandRateLimiter && to.ebpfLessEnabled == opts.ebpfLessEnabled && to.enforcementExcludeBinary == opts.enforcementExcludeBinary && diff --git a/pkg/security/tests/imds_utils/imds_utils.go b/pkg/security/tests/testutils/imds.go similarity index 72% rename from pkg/security/tests/imds_utils/imds_utils.go rename to pkg/security/tests/testutils/imds.go index f52b740da4208..c105709fcb450 100644 --- a/pkg/security/tests/imds_utils/imds_utils.go +++ b/pkg/security/tests/testutils/imds.go @@ -3,19 +3,16 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. -// Package imdsutils holds utils related to the IMDS tests -package imdsutils +// Package testutils holds test utility functions +package testutils import ( "context" "encoding/json" "errors" "fmt" - "net" "net/http" "time" - - "github.com/vishvananda/netlink" ) const ( @@ -33,55 +30,14 @@ const ( AWSSecurityCredentialsExpirationTestValue = "2324-05-01T12:00:00Z" // AWSIMDSServerTestValue is the IMDS Server used by the IMDS tests AWSIMDSServerTestValue = "EC2ws" - // CSMDummyInterface is the Dummy interface name used by the IMDS tests - CSMDummyInterface = "dummy_csm" // IMDSTestServerIP is the IMDS server IP used by the IMDS tests IMDSTestServerIP = "169.254.169.254" + // IMDSTestServerCIDR is the IMDS server CIDR used by the IMDS tests + IMDSTestServerCIDR = IMDSTestServerIP + "/32" // IMDSTestServerPort is the IMDS server port used by the IMDS tests IMDSTestServerPort = 8080 ) -// CreateDummyInterface creates a dummy interface and attaches it to the provided IP -func CreateDummyInterface(ip string, name string) (*netlink.Dummy, error) { - dummy := &netlink.Dummy{ - LinkAttrs: netlink.LinkAttrs{ - Name: name, - }, - } - - // delete existing dummy interface - _ = netlink.LinkDel(dummy) - - // Add the dummy interface - if err := netlink.LinkAdd(dummy); err != nil { - return nil, fmt.Errorf("failed to create dummy interface %s: %v", name, err) - } - - // attach the IMDS IP to the dummy interface - addr := &netlink.Addr{IPNet: &net.IPNet{ - IP: net.ParseIP(ip), - Mask: net.CIDRMask(24, 32), - }} - if err := netlink.AddrAdd(dummy, addr); err != nil { - return nil, fmt.Errorf("failed to attach IMDS IP to %s: %v", name, err) - } - - // set dummy interface up - if err := netlink.LinkSetUp(dummy); err != nil { - return nil, fmt.Errorf("failed to set %s up: %v", name, err) - } - - return dummy, nil -} - -// RemoveDummyInterface removes the provided dummy interface -func RemoveDummyInterface(link *netlink.Dummy) error { - if err := netlink.LinkDel(link); err != nil { - return fmt.Errorf("failed to delete %s: %v", link.Name, err) - } - return nil -} - // CreateIMDSServer creates a fake IMDS server func CreateIMDSServer(addr string) *http.Server { mux := http.NewServeMux() diff --git a/pkg/security/tests/testutils/network.go b/pkg/security/tests/testutils/network.go new file mode 100644 index 0000000000000..bcb85cbec22b4 --- /dev/null +++ b/pkg/security/tests/testutils/network.go @@ -0,0 +1,62 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +// Package testutils holds test utility functions +package testutils + +import ( + "fmt" + "net" + + "github.com/vishvananda/netlink" +) + +const ( + // CSMDummyInterface is the Dummy interface name used by the IMDS tests + CSMDummyInterface = "dummy_csm" +) + +// CreateDummyInterface creates a dummy interface and attaches it to the provided IP +func CreateDummyInterface(name string, cidr string) (*netlink.Dummy, error) { + dummy := &netlink.Dummy{ + LinkAttrs: netlink.LinkAttrs{ + Name: name, + }, + } + + // delete existing dummy interface + _ = netlink.LinkDel(dummy) + + // Add the dummy interface + if err := netlink.LinkAdd(dummy); err != nil { + return nil, fmt.Errorf("failed to create dummy interface %s: %v", name, err) + } + + _, ipNet, err := net.ParseCIDR(cidr) + if err != nil { + return nil, fmt.Errorf("failed to parse CIDR %s: %v", cidr, err) + } + + // attach the IMDS IP to the dummy interface + addr := &netlink.Addr{IPNet: ipNet} + if err := netlink.AddrAdd(dummy, addr); err != nil { + return nil, fmt.Errorf("failed to attach IMDS IP to %s: %v", name, err) + } + + // set dummy interface up + if err := netlink.LinkSetUp(dummy); err != nil { + return nil, fmt.Errorf("failed to set %s up: %v", name, err) + } + + return dummy, nil +} + +// RemoveDummyInterface removes the provided dummy interface +func RemoveDummyInterface(link *netlink.Dummy) error { + if err := netlink.LinkDel(link); err != nil { + return fmt.Errorf("failed to delete %s: %v", link.Name, err) + } + return nil +} diff --git a/pkg/security/utils/proc_linux.go b/pkg/security/utils/proc_linux.go index 6746091231e65..241aae6f91b3f 100644 --- a/pkg/security/utils/proc_linux.go +++ b/pkg/security/utils/proc_linux.go @@ -120,6 +120,14 @@ func ProcRootPath(pid uint32) string { // ProcRootFilePath returns the path to the input file after prepending the proc root path of the given pid func ProcRootFilePath(pid uint32, file string) string { + // if file starts with /, the result of filepath.Join will look, before cleaning, like + // /proc/$PID/root//file + // and this will require a re-allocation in filepath.Clean + // to prevent this, we remove the leading / from the file if it's there. In most cases + // it will be enough + if file != "" && file[0] == os.PathSeparator { + file = file[1:] + } return procPidPath2(pid, "root", file) } diff --git a/pkg/serializer/go.mod b/pkg/serializer/go.mod index dd628a0dd43c2..22ad7cff9f9a3 100644 --- a/pkg/serializer/go.mod +++ b/pkg/serializer/go.mod @@ -17,6 +17,7 @@ replace ( github.com/DataDog/datadog-agent/comp/forwarder/orchestrator/orchestratorinterface => ../../comp/forwarder/orchestrator/orchestratorinterface github.com/DataDog/datadog-agent/comp/serializer/compression => ../../comp/serializer/compression github.com/DataDog/datadog-agent/pkg/aggregator/ckey => ../aggregator/ckey + github.com/DataDog/datadog-agent/pkg/api => ../api github.com/DataDog/datadog-agent/pkg/collector/check/defaults => ../collector/check/defaults github.com/DataDog/datadog-agent/pkg/config/env => ../config/env github.com/DataDog/datadog-agent/pkg/config/logs => ../config/logs/ @@ -63,7 +64,7 @@ replace ( require ( github.com/DataDog/agent-payload/v5 v5.0.114 - github.com/DataDog/datadog-agent/comp/core/config v0.56.0-rc.3 + github.com/DataDog/datadog-agent/comp/core/config v0.57.1 github.com/DataDog/datadog-agent/comp/forwarder/defaultforwarder v0.56.0-rc.3 github.com/DataDog/datadog-agent/comp/forwarder/orchestrator/orchestratorinterface v0.56.0-rc.3 github.com/DataDog/datadog-agent/comp/serializer/compression v0.56.0-rc.3 @@ -77,7 +78,7 @@ require ( github.com/DataDog/datadog-agent/pkg/telemetry v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/util/json v0.56.0-rc.3 github.com/DataDog/datadog-agent/pkg/util/log v0.57.1 - github.com/DataDog/datadog-agent/pkg/version v0.56.0-rc.3 + github.com/DataDog/datadog-agent/pkg/version v0.57.1 github.com/DataDog/opentelemetry-mapping-go/pkg/quantile v0.20.0 github.com/gogo/protobuf v1.3.2 github.com/json-iterator/go v1.1.12 @@ -88,20 +89,21 @@ require ( ) require ( - github.com/DataDog/datadog-agent/comp/core/flare/builder v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/types v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/builder v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/types v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/log/def v0.0.0-00010101000000-000000000000 // indirect github.com/DataDog/datadog-agent/comp/core/secrets v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/status v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/comp/core/telemetry v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/def v0.57.1 // indirect + github.com/DataDog/datadog-agent/pkg/api v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/collector/check/defaults v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/env v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/nodetreemodel v0.60.0-devel // indirect github.com/DataDog/datadog-agent/pkg/config/setup v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/structure v0.0.0-00010101000000-000000000000 // indirect github.com/DataDog/datadog-agent/pkg/config/teeconfig v0.60.0-devel // indirect - github.com/DataDog/datadog-agent/pkg/config/utils v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/config/utils v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/orchestrator/model v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/status/health v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/util/backoff v0.56.0-rc.3 // indirect diff --git a/pkg/serializer/internal/metrics/iterable_series.go b/pkg/serializer/internal/metrics/iterable_series.go index d6aae8dc9ed4b..3abd43eb7a93e 100644 --- a/pkg/serializer/internal/metrics/iterable_series.go +++ b/pkg/serializer/internal/metrics/iterable_series.go @@ -138,60 +138,58 @@ func (series *IterableSeries) MarshalSplitCompress(bufferContext *marshaler.Buff return pb.payloads, nil } -// MarshalSplitCompressMultiple uses the stream compressor to marshal and compress one series into two sets of payloads. -// One set of payloads contains all metrics, and the other contains only those that pass the provided filter function. +// MarshalSplitCompressMultiple uses the stream compressor to marshal and compress one series into three sets of payloads. +// One set of payloads contains all metrics, +// The seond contains only those that pass the provided MRF filter function. +// The third contains only those that pass the provided autoscaling local failover filter function. // This function exists because we need a way to build both payloads in a single pass over the input data, which cannot be iterated over twice. -func (series *IterableSeries) MarshalSplitCompressMultiple(config config.Component, strategy compression.Component, filterFunc func(s *metrics.Serie) bool) (transaction.BytesPayloads, transaction.BytesPayloads, error) { - bufferContext := marshaler.NewBufferContext() - pb, err := series.NewPayloadsBuilder(bufferContext, config, strategy) - if err != nil { - return nil, nil, err - } - - bufferContext2 := marshaler.NewBufferContext() - pb2, err := series.NewPayloadsBuilder(bufferContext2, config, strategy) - if err != nil { - return nil, nil, err - } - - err = pb.startPayload() - if err != nil { - return nil, nil, err - } +func (series *IterableSeries) MarshalSplitCompressMultiple(config config.Component, strategy compression.Component, filterFuncForMRF func(s *metrics.Serie) bool, filterFuncForAutoscaling func(s *metrics.Serie) bool) (transaction.BytesPayloads, transaction.BytesPayloads, transaction.BytesPayloads, error) { + pbs := make([]*PayloadsBuilder, 3) // 0: all, 1: MRF, 2: autoscaling + for i := range pbs { + bufferContext := marshaler.NewBufferContext() + pb, err := series.NewPayloadsBuilder(bufferContext, config, strategy) + if err != nil { + return nil, nil, nil, err + } + pbs[i] = &pb - err = pb2.startPayload() - if err != nil { - return nil, nil, err + err = pbs[i].startPayload() + if err != nil { + return nil, nil, nil, err + } } - // Use series.source.MoveNext() instead of series.MoveNext() because this function supports // the serie.NoIndex field. for series.source.MoveNext() { - err = pb.writeSerie(series.source.Current()) + err := pbs[0].writeSerie(series.source.Current()) if err != nil { - return nil, nil, err + return nil, nil, nil, err } - if filterFunc(series.source.Current()) { - err = pb2.writeSerie(series.source.Current()) + if filterFuncForMRF(series.source.Current()) { + err = pbs[1].writeSerie(series.source.Current()) if err != nil { - return nil, nil, err + return nil, nil, nil, err } } - } - // if the last payload has any data, flush it - err = pb.finishPayload() - if err != nil { - return nil, nil, err + if filterFuncForAutoscaling(series.source.Current()) { + err = pbs[2].writeSerie(series.source.Current()) + if err != nil { + return nil, nil, nil, err + } + } } - err = pb2.finishPayload() - if err != nil { - return nil, nil, err + // if the last payload has any data, flush it + for i := range pbs { + err := pbs[i].finishPayload() + if err != nil { + return nil, nil, nil, err + } } - return pb.payloads, pb2.payloads, nil + return pbs[0].payloads, pbs[1].payloads, pbs[2].payloads, nil } // NewPayloadsBuilder initializes a new PayloadsBuilder to be used for serializing series into a set of output payloads. diff --git a/pkg/serializer/internal/metrics/series_test.go b/pkg/serializer/internal/metrics/series_test.go index 4abb2db20bac8..0eaf9cc1d8944 100644 --- a/pkg/serializer/internal/metrics/series_test.go +++ b/pkg/serializer/internal/metrics/series_test.go @@ -462,13 +462,19 @@ func TestMarshalSplitCompressMultiplePointsLimit(t *testing.T) { } series := CreateIterableSeries(CreateSerieSource(rawSeries)) - payloads, filteredPayloads, err := series.MarshalSplitCompressMultiple(mockConfig, compressionimpl.NewCompressor(mockConfig), func(s *metrics.Serie) bool { - return s.Name == "test.metrics42" - }) + payloads, filteredPayloads, autoscalingFailoverPayloads, err := series.MarshalSplitCompressMultiple(mockConfig, compressionimpl.NewCompressor(mockConfig), + func(s *metrics.Serie) bool { + return s.Name == "test.metrics42" + }, + func(s *metrics.Serie) bool { + return s.Name == "test.metrics99" || s.Name == "test.metrics98" + }, + ) require.NoError(t, err) require.Equal(t, 5, len(payloads)) // only one serie should be present in the filtered payload, so 5 total points, which fits in one payload require.Equal(t, 1, len(filteredPayloads)) + require.Equal(t, 1, len(autoscalingFailoverPayloads)) }) } } diff --git a/pkg/serializer/serializer.go b/pkg/serializer/serializer.go index 94a0b50eadbf4..801fcc659cc22 100644 --- a/pkg/serializer/serializer.go +++ b/pkg/serializer/serializer.go @@ -350,21 +350,33 @@ func (s *Serializer) SendIterableSeries(serieSource metrics.SerieSource) error { } else if useV1API && !s.enableJSONStream { seriesBytesPayloads, extraHeaders, err = s.serializePayloadJSON(seriesSerializer, true) } else { - failoverActive, allowlist := s.getFailoverAllowlist() - - if failoverActive && len(allowlist) > 0 { + failoverActiveForMRF, allowlistForMRF := s.getFailoverAllowlist() + failoverActiveForAutoscaling, allowlistForAutoscaling := s.getAutoscalingFailoverMetrics() + failoverActive := (failoverActiveForMRF && len(allowlistForMRF) > 0) || (failoverActiveForAutoscaling && len(allowlistForAutoscaling) > 0) + if failoverActive { var filtered transaction.BytesPayloads - seriesBytesPayloads, filtered, err = seriesSerializer.MarshalSplitCompressMultiple(s.config, s.Strategy, func(s *metrics.Serie) bool { - _, allowed := allowlist[s.Name] - return allowed - }) + var localAutoscalingFaioverPayloads transaction.BytesPayloads + seriesBytesPayloads, filtered, localAutoscalingFaioverPayloads, err = seriesSerializer.MarshalSplitCompressMultiple(s.config, s.Strategy, + func(s *metrics.Serie) bool { // Filter for MRF + _, allowed := allowlistForMRF[s.Name] + return allowed + }, + func(s *metrics.Serie) bool { // Filter for Autoscaling + _, allowed := allowlistForAutoscaling[s.Name] + return allowed + }) + for _, seriesBytesPayload := range seriesBytesPayloads { seriesBytesPayload.Destination = transaction.PrimaryOnly } for _, seriesBytesPayload := range filtered { seriesBytesPayload.Destination = transaction.SecondaryOnly } + for _, seriesBytesPayload := range localAutoscalingFaioverPayloads { + seriesBytesPayload.Destination = transaction.LocalOnly + } seriesBytesPayloads = append(seriesBytesPayloads, filtered...) + seriesBytesPayloads = append(seriesBytesPayloads, localAutoscalingFaioverPayloads...) } else { seriesBytesPayloads, err = seriesSerializer.MarshalSplitCompress(marshaler.NewBufferContext(), s.config, s.Strategy) for _, seriesBytesPayload := range seriesBytesPayloads { @@ -397,6 +409,19 @@ func (s *Serializer) getFailoverAllowlist() (bool, map[string]struct{}) { return failoverActive, allowlist } +func (s *Serializer) getAutoscalingFailoverMetrics() (bool, map[string]struct{}) { + autoscalingFailoverEnabled := s.config.GetBool("autoscaling.failover.enabled") && s.config.GetBool("cluster_agent.enabled") + var allowlist map[string]struct{} + if autoscalingFailoverEnabled && s.config.IsSet("autoscaling.failover.metrics") { + rawList := s.config.GetStringSlice("autoscaling.failover.metrics") + allowlist = make(map[string]struct{}, len(rawList)) + for _, allowed := range rawList { + allowlist[allowed] = struct{}{} + } + } + return autoscalingFailoverEnabled, allowlist +} + // AreSketchesEnabled returns whether sketches are enabled for serialization func (s *Serializer) AreSketchesEnabled() bool { return s.enableSketches @@ -411,7 +436,6 @@ func (s *Serializer) SendSketch(sketches metrics.SketchesSource) error { sketchesSerializer := metricsserializer.SketchSeriesList{SketchesSource: sketches} if s.enableSketchProtobufStream { failoverActive, allowlist := s.getFailoverAllowlist() - if failoverActive && len(allowlist) > 0 { payloads, filteredPayloads, err := sketchesSerializer.MarshalSplitCompressMultiple(s.config, s.Strategy, func(ss *metrics.SketchSeries) bool { _, allowed := allowlist[ss.Name] diff --git a/pkg/serverless/daemon/routes_test.go b/pkg/serverless/daemon/routes_test.go index 3a8470bec1e21..0937104e5b0f7 100644 --- a/pkg/serverless/daemon/routes_test.go +++ b/pkg/serverless/daemon/routes_test.go @@ -20,6 +20,7 @@ import ( "github.com/cihub/seelog" "github.com/stretchr/testify/assert" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" pb "github.com/DataDog/datadog-agent/pkg/proto/pbgo/trace" "github.com/DataDog/datadog-agent/pkg/serverless/invocationlifecycle" "github.com/DataDog/datadog-agent/pkg/serverless/metrics" @@ -445,6 +446,7 @@ func startAgents() *Daemon { ma := &metrics.ServerlessMetricAgent{ SketchesBucketOffset: time.Second * 10, + Tagger: nooptagger.NewTaggerClient(), } ma.Start(FlushTimeout, &metrics.MetricConfig{}, &metrics.MetricDogStatsD{}) d.SetStatsdServer(ma) diff --git a/pkg/serverless/metrics/metric.go b/pkg/serverless/metrics/metric.go index 9732db4e76c8f..a3f3456a94ef7 100644 --- a/pkg/serverless/metrics/metric.go +++ b/pkg/serverless/metrics/metric.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/DataDog/datadog-agent/comp/core/tagger" dogstatsdServer "github.com/DataDog/datadog-agent/comp/dogstatsd/server" "github.com/DataDog/datadog-agent/pkg/aggregator" "github.com/DataDog/datadog-agent/pkg/config/model" @@ -22,6 +23,7 @@ import ( type ServerlessMetricAgent struct { dogStatsDServer dogstatsdServer.ServerlessDogstatsd tags []string + Tagger tagger.Component Demux aggregator.Demultiplexer SketchesBucketOffset time.Duration @@ -76,7 +78,7 @@ func (c *ServerlessMetricAgent) Start(forwarderTimeout time.Duration, multipleEn } else { pkgconfigsetup.Datadog().Set(statsDMetricBlocklistKey, buildMetricBlocklist(customerList), model.SourceAgentRuntime) } - demux := buildDemultiplexer(multipleEndpointConfig, forwarderTimeout) + demux := buildDemultiplexer(multipleEndpointConfig, forwarderTimeout, c.Tagger) if demux != nil { statsd, err := dogstatFactory.NewServer(demux) @@ -121,14 +123,14 @@ func (c *ServerlessMetricAgent) GetExtraTags() []string { return c.tags } -func buildDemultiplexer(multipleEndpointConfig MultipleEndpointConfig, forwarderTimeout time.Duration) aggregator.Demultiplexer { +func buildDemultiplexer(multipleEndpointConfig MultipleEndpointConfig, forwarderTimeout time.Duration, tagger tagger.Component) aggregator.Demultiplexer { log.Debugf("Using a SyncForwarder with a %v timeout", forwarderTimeout) keysPerDomain, err := multipleEndpointConfig.GetMultipleEndpoints() if err != nil { log.Errorf("Misconfiguration of agent endpoints: %s", err) return nil } - return aggregator.InitAndStartServerlessDemultiplexer(keysPerDomain, forwarderTimeout) + return aggregator.InitAndStartServerlessDemultiplexer(keysPerDomain, forwarderTimeout, tagger) } func buildMetricBlocklist(userProvidedList []string) []string { diff --git a/pkg/serverless/metrics/metric_test.go b/pkg/serverless/metrics/metric_test.go index 9f7abdc5d8b75..ba31842f93590 100644 --- a/pkg/serverless/metrics/metric_test.go +++ b/pkg/serverless/metrics/metric_test.go @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + nooptagger "github.com/DataDog/datadog-agent/comp/core/tagger/noopimpl" dogstatsdServer "github.com/DataDog/datadog-agent/comp/dogstatsd/server" "github.com/DataDog/datadog-agent/pkg/aggregator" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" @@ -42,6 +43,7 @@ func TestStartDoesNotBlock(t *testing.T) { pkgconfigsetup.LoadWithoutSecret(pkgconfigsetup.Datadog(), nil) metricAgent := &ServerlessMetricAgent{ SketchesBucketOffset: time.Second * 10, + Tagger: nooptagger.NewTaggerClient(), } defer metricAgent.Stop() metricAgent.Start(10*time.Second, &MetricConfig{}, &MetricDogStatsD{}) @@ -64,6 +66,7 @@ func (m *InvalidMetricConfigMocked) GetMultipleEndpoints() (map[string][]string, func TestStartInvalidConfig(t *testing.T) { metricAgent := &ServerlessMetricAgent{ SketchesBucketOffset: time.Second * 10, + Tagger: nooptagger.NewTaggerClient(), } defer metricAgent.Stop() metricAgent.Start(1*time.Second, &InvalidMetricConfigMocked{}, &MetricDogStatsD{}) @@ -81,6 +84,7 @@ func (m *MetricDogStatsDMocked) NewServer(_ aggregator.Demultiplexer) (dogstatsd func TestStartInvalidDogStatsD(t *testing.T) { metricAgent := &ServerlessMetricAgent{ SketchesBucketOffset: time.Second * 10, + Tagger: nooptagger.NewTaggerClient(), } defer metricAgent.Stop() metricAgent.Start(1*time.Second, &MetricConfig{}, &MetricDogStatsDMocked{}) @@ -97,6 +101,7 @@ func TestStartWithProxy(t *testing.T) { metricAgent := &ServerlessMetricAgent{ SketchesBucketOffset: time.Second * 10, + Tagger: nooptagger.NewTaggerClient(), } defer metricAgent.Stop() metricAgent.Start(10*time.Second, &MetricConfig{}, &MetricDogStatsD{}) @@ -116,6 +121,7 @@ func TestRaceFlushVersusAddSample(t *testing.T) { } metricAgent := &ServerlessMetricAgent{ SketchesBucketOffset: time.Second * 10, + Tagger: nooptagger.NewTaggerClient(), } defer metricAgent.Stop() metricAgent.Start(10*time.Second, &ValidMetricConfigMocked{}, &MetricDogStatsD{}) @@ -210,7 +216,7 @@ func TestRaceFlushVersusParsePacket(t *testing.T) { require.NoError(t, err) pkgconfigsetup.Datadog().SetDefault("dogstatsd_port", port) - demux := aggregator.InitAndStartServerlessDemultiplexer(nil, time.Second*1000) + demux := aggregator.InitAndStartServerlessDemultiplexer(nil, time.Second*1000, nooptagger.NewTaggerClient()) s, err := dogstatsdServer.NewServerlessServer(demux) require.NoError(t, err, "cannot start DSD") diff --git a/pkg/serverless/trace/trace.go b/pkg/serverless/trace/trace.go index c941f113069a3..1b1b8e5d9d0d1 100644 --- a/pkg/serverless/trace/trace.go +++ b/pkg/serverless/trace/trace.go @@ -15,6 +15,7 @@ import ( "github.com/DataDog/datadog-agent/cmd/serverless-init/cloudservice" compcorecfg "github.com/DataDog/datadog-agent/comp/core/config" + "github.com/DataDog/datadog-agent/comp/core/tagger" zstd "github.com/DataDog/datadog-agent/comp/trace/compression/impl-zstd" comptracecfg "github.com/DataDog/datadog-agent/comp/trace/config" "github.com/DataDog/datadog-agent/pkg/config/model" @@ -45,7 +46,8 @@ type Load interface { // LoadConfig is implementing Load to retrieve the config type LoadConfig struct { - Path string + Path string + Tagger tagger.Component } // httpURLMetaKey is the key of the span meta containing the HTTP URL @@ -86,7 +88,7 @@ func (l *LoadConfig) Load() (*config.AgentConfig, error) { if err != nil { return nil, err } - return comptracecfg.LoadConfigFile(l.Path, c) + return comptracecfg.LoadConfigFile(l.Path, c, l.Tagger) } // Start starts the agent diff --git a/pkg/snmp/snmp_test.go b/pkg/snmp/snmp_test.go index bffe8bef122b6..bd19561783a3f 100644 --- a/pkg/snmp/snmp_test.go +++ b/pkg/snmp/snmp_test.go @@ -6,11 +6,11 @@ package snmp import ( - "strings" "testing" "github.com/DataDog/datadog-agent/pkg/snmp/snmpintegration" + configmock "github.com/DataDog/datadog-agent/pkg/config/mock" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/gosnmp/gosnmp" @@ -89,10 +89,7 @@ func TestBuildSNMPParams(t *testing.T) { } func TestNewListenerConfig(t *testing.T) { - pkgconfigsetup.Datadog().SetConfigType("yaml") - - // default collect_device_metadata should be true - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` snmp_listener: configs: - network: 127.0.0.1/30 @@ -100,8 +97,7 @@ snmp_listener: collect_device_metadata: true - network: 127.0.0.3/30 collect_device_metadata: false -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) @@ -114,7 +110,7 @@ snmp_listener: assert.Equal(t, false, conf.Configs[2].CollectDeviceMetadata) // collect_device_metadata: false - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` snmp_listener: collect_device_metadata: false configs: @@ -123,8 +119,7 @@ snmp_listener: collect_device_metadata: true - network: 127.0.0.3/30 collect_device_metadata: false -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.NoError(t, err) @@ -137,7 +132,7 @@ snmp_listener: assert.Equal(t, false, conf.Configs[2].CollectDeviceMetadata) // collect_device_metadata: true - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` snmp_listener: collect_device_metadata: true configs: @@ -146,8 +141,7 @@ snmp_listener: collect_device_metadata: true - network: 127.0.0.3/30 collect_device_metadata: false -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.NoError(t, err) @@ -164,7 +158,7 @@ func TestNewNetworkDevicesListenerConfig(t *testing.T) { pkgconfigsetup.Datadog().SetConfigType("yaml") // default collect_device_metadata should be true - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: configs: @@ -173,8 +167,7 @@ network_devices: collect_device_metadata: true - network: 127.0.0.3/30 collect_device_metadata: false -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) @@ -187,7 +180,7 @@ network_devices: assert.Equal(t, false, conf.Configs[2].CollectDeviceMetadata) // collect_device_metadata: false - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: collect_device_metadata: false @@ -197,8 +190,7 @@ network_devices: collect_device_metadata: true - network: 127.0.0.3/30 collect_device_metadata: false -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.NoError(t, err) @@ -211,7 +203,7 @@ network_devices: assert.Equal(t, false, conf.Configs[2].CollectDeviceMetadata) // collect_device_metadata: true - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: collect_device_metadata: true @@ -221,8 +213,7 @@ network_devices: collect_device_metadata: true - network: 127.0.0.3/30 collect_device_metadata: false -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.NoError(t, err) @@ -239,7 +230,7 @@ func TestBothListenersConfig(t *testing.T) { pkgconfigsetup.Datadog().SetConfigType("yaml") // check that network_devices config override the snmp_listener config - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` snmp_listener: collect_device_metadata: true configs: @@ -257,8 +248,7 @@ network_devices: collect_device_metadata: false - network: 127.0.0.6/30 collect_device_metadata: true -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) @@ -272,7 +262,7 @@ network_devices: assert.Equal(t, true, conf.Configs[2].CollectDeviceMetadata) // incorrect snmp_listener config and correct network_devices config - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` snmp_listener: configs: - foo: bar @@ -285,8 +275,7 @@ network_devices: collect_device_metadata: false - network: 127.0.0.6/30 collect_device_metadata: true -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.NoError(t, err) @@ -299,7 +288,7 @@ network_devices: assert.Equal(t, true, conf.Configs[2].CollectDeviceMetadata) // incorrect snmp_listener config and correct network_devices config - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` snmp_listener: configs: - network: 127.0.0.4/30 @@ -310,16 +299,14 @@ snmp_listener: network_devices: autodiscovery: - foo: bar -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.Error(t, err) } func Test_LoaderConfig(t *testing.T) { - pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: configs: @@ -328,8 +315,7 @@ network_devices: loader: core - network: 127.3.0.0/30 loader: python -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) @@ -338,7 +324,7 @@ network_devices: assert.Equal(t, "core", conf.Configs[1].Loader) assert.Equal(t, "python", conf.Configs[2].Loader) - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: loader: core @@ -348,8 +334,7 @@ network_devices: loader: core - network: 127.3.0.0/30 loader: python -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.NoError(t, err) @@ -361,8 +346,7 @@ network_devices: } func Test_MinCollectionInterval(t *testing.T) { - pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: min_collection_interval: 60 @@ -370,8 +354,7 @@ network_devices: - network: 127.1.0.0/30 min_collection_interval: 30 - network: 127.2.0.0/30 -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) @@ -381,8 +364,7 @@ network_devices: } func Test_Configs(t *testing.T) { - pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: workers: 10 @@ -404,8 +386,7 @@ network_devices: match_value: "eth0" in_speed: 50 out_speed: 25 -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) @@ -438,7 +419,7 @@ network_devices: ///////////////// // legacy configs ///////////////// - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: allowed_failures: 15 @@ -450,8 +431,7 @@ network_devices: community: legacyCommunityString version: legacySnmpVersion network: 127.2.0.0/30 -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.NoError(t, err) legacyConfig := conf.Configs[0] @@ -468,39 +448,34 @@ network_devices: func Test_NamespaceConfig(t *testing.T) { // Default Namespace - pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: configs: - community_string: someCommunityString network_address: 127.1.0.0/30 -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) networkConf := conf.Configs[0] assert.Equal(t, "default", networkConf.Namespace) // Custom Namespace in network_devices - pkgconfigsetup.Datadog().SetConfigType("yaml") - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: namespace: ponyo autodiscovery: configs: - community_string: someCommunityString network_address: 127.1.0.0/30 -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.NoError(t, err) networkConf = conf.Configs[0] assert.Equal(t, "ponyo", networkConf.Namespace) // Custom Namespace in snmp_listener - pkgconfigsetup.Datadog().SetConfigType("yaml") - err = pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: namespace: totoro @@ -510,8 +485,7 @@ network_devices: - community_string: someCommunityString network_address: 127.2.0.0/30 namespace: mononoke -`)) - assert.NoError(t, err) +`) conf, err = NewListenerConfig() assert.NoError(t, err) assert.Equal(t, "totoro", conf.Configs[0].Namespace) @@ -528,8 +502,7 @@ func TestFirstNonEmpty(t *testing.T) { } func Test_UseDeviceIDAsHostname(t *testing.T) { - pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: use_device_id_as_hostname: true @@ -537,8 +510,7 @@ network_devices: - network: 127.1.0.0/30 use_device_id_as_hostname: false - network: 127.2.0.0/30 -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) @@ -548,8 +520,7 @@ network_devices: } func Test_CollectTopology_withRootCollectTopologyFalse(t *testing.T) { - pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: collect_topology: false @@ -559,8 +530,7 @@ network_devices: - network: 127.2.0.0/30 collect_topology: false - network: 127.3.0.0/30 -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) @@ -571,8 +541,7 @@ network_devices: } func Test_CollectTopology_withRootCollectTopologyTrue(t *testing.T) { - pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: collect_topology: true @@ -582,8 +551,7 @@ network_devices: - network: 127.2.0.0/30 collect_topology: false - network: 127.3.0.0/30 -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) @@ -594,8 +562,7 @@ network_devices: } func Test_CollectTopology_withRootCollectTopologyUnset(t *testing.T) { - pkgconfigsetup.Datadog().SetConfigType("yaml") - err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(` + configmock.NewFromYAML(t, ` network_devices: autodiscovery: configs: @@ -604,8 +571,7 @@ network_devices: - network: 127.2.0.0/30 collect_topology: false - network: 127.3.0.0/30 -`)) - assert.NoError(t, err) +`) conf, err := NewListenerConfig() assert.NoError(t, err) diff --git a/pkg/trace/api/otlp.go b/pkg/trace/api/otlp.go index fb96ea6b1a930..8badf01d92852 100644 --- a/pkg/trace/api/otlp.go +++ b/pkg/trace/api/otlp.go @@ -208,7 +208,6 @@ func (o *OTLPReceiver) receiveResourceSpansV2(ctx context.Context, rspans ptrace otelres := rspans.Resource() resourceAttributes := otelres.Attributes() - topLevelByKind := o.conf.HasFeature("enable_otlp_compute_top_level_by_span_kind") tracesByID := make(map[uint64]pb.Trace) priorityByID := make(map[uint64]sampler.SamplingPriority) var spancount int64 @@ -225,7 +224,7 @@ func (o *OTLPReceiver) receiveResourceSpansV2(ctx context.Context, rspans ptrace if tracesByID[traceID] == nil { tracesByID[traceID] = pb.Trace{} } - ddspan := transform.OtelSpanToDDSpan(otelspan, otelres, libspans.Scope(), topLevelByKind, o.conf, nil) + ddspan := transform.OtelSpanToDDSpan(otelspan, otelres, libspans.Scope(), o.conf, nil) if p, ok := ddspan.Metrics["_sampling_priority_v1"]; ok { priorityByID[traceID] = sampler.SamplingPriority(p) diff --git a/pkg/trace/api/otlp_test.go b/pkg/trace/api/otlp_test.go index 5803609c04811..9ea2f39e3cfb4 100644 --- a/pkg/trace/api/otlp_test.go +++ b/pkg/trace/api/otlp_test.go @@ -1733,7 +1733,16 @@ func testOTLPConvertSpan(enableReceiveResourceSpansV2 bool, t *testing.T) { lib.SetVersion(tt.libver) assert := assert.New(t) want := tt.out - got := o.convertSpan(tt.rattr, lib, tt.in) + res := pcommon.NewResource() + for k, v := range tt.rattr { + res.Attributes().PutStr(k, v) + } + var got *pb.Span + if enableReceiveResourceSpansV2 { + got = transform.OtelSpanToDDSpan(tt.in, res, lib, o.conf, nil) + } else { + got = o.convertSpan(tt.rattr, lib, tt.in) + } if len(want.Meta) != len(got.Meta) { t.Fatalf("(%d) Meta count mismatch:\n%#v", i, got.Meta) } @@ -1779,7 +1788,11 @@ func testOTLPConvertSpan(enableReceiveResourceSpansV2 bool, t *testing.T) { // test new top-level identification feature flag o.conf.Features["enable_otlp_compute_top_level_by_span_kind"] = struct{}{} - got = o.convertSpan(tt.rattr, lib, tt.in) + if enableReceiveResourceSpansV2 { + got = transform.OtelSpanToDDSpan(tt.in, res, lib, o.conf, nil) + } else { + got = o.convertSpan(tt.rattr, lib, tt.in) + } wantMetrics := tt.topLevelOutMetrics if len(wantMetrics) != len(got.Metrics) { t.Fatalf("(%d) Metrics count mismatch:\n\n%v\n\n%v", i, wantMetrics, got.Metrics) @@ -2156,7 +2169,17 @@ func testOTLPConvertSpanSetPeerService(enableReceiveResourceSpansV2 bool, t *tes lib.SetName(tt.libname) lib.SetVersion(tt.libver) assert := assert.New(t) - assert.Equal(tt.out, o.convertSpan(tt.rattr, lib, tt.in), i) + res := pcommon.NewResource() + for k, v := range tt.rattr { + res.Attributes().PutStr(k, v) + } + var got *pb.Span + if enableReceiveResourceSpansV2 { + got = transform.OtelSpanToDDSpan(tt.in, res, lib, o.conf, nil) + } else { + got = o.convertSpan(tt.rattr, lib, tt.in) + } + assert.Equal(tt.out, got, i) }) } } diff --git a/pkg/trace/config/config.go b/pkg/trace/config/config.go index 2e8a94cd0e993..0426863d60be7 100644 --- a/pkg/trace/config/config.go +++ b/pkg/trace/config/config.go @@ -537,7 +537,9 @@ func New() *AgentConfig { MaxPayloadSize: 5 * 1024 * 1024, }, - Features: make(map[string]struct{}), + Features: make(map[string]struct{}), + PeerTagsAggregation: true, + ComputeStatsBySpanKind: true, } } diff --git a/pkg/trace/config/config_test.go b/pkg/trace/config/config_test.go index 145256b8986fe..97c4d88339bad 100644 --- a/pkg/trace/config/config_test.go +++ b/pkg/trace/config/config_test.go @@ -36,32 +36,31 @@ func TestInAzureAppServices(t *testing.T) { func TestPeerTagsAggregation(t *testing.T) { t.Run("disabled", func(t *testing.T) { cfg := New() + cfg.PeerTagsAggregation = false assert.False(t, cfg.PeerTagsAggregation) assert.Empty(t, cfg.PeerTags) assert.Empty(t, cfg.ConfiguredPeerTags()) }) - t.Run("enabled", func(t *testing.T) { + t.Run("default-enabled", func(t *testing.T) { cfg := New() - cfg.PeerTagsAggregation = true assert.Empty(t, cfg.PeerTags) assert.Equal(t, basePeerTags, cfg.ConfiguredPeerTags()) }) t.Run("disabled-user-tags", func(t *testing.T) { cfg := New() + cfg.PeerTagsAggregation = false cfg.PeerTags = []string{"user_peer_tag"} assert.False(t, cfg.PeerTagsAggregation) assert.Empty(t, cfg.ConfiguredPeerTags()) }) t.Run("enabled-user-tags", func(t *testing.T) { cfg := New() - cfg.PeerTagsAggregation = true cfg.PeerTags = []string{"user_peer_tag"} assert.Equal(t, append(basePeerTags, "user_peer_tag"), cfg.ConfiguredPeerTags()) }) t.Run("dedup", func(t *testing.T) { cfg := New() - cfg.PeerTagsAggregation = true cfg.PeerTags = basePeerTags[:2] assert.Equal(t, basePeerTags, cfg.ConfiguredPeerTags()) }) diff --git a/pkg/trace/traceutil/otel_util.go b/pkg/trace/traceutil/otel_util.go index e4a2ed753c7c7..df0c93641732d 100644 --- a/pkg/trace/traceutil/otel_util.go +++ b/pkg/trace/traceutil/otel_util.go @@ -106,6 +106,7 @@ func GetOTelAttrVal(attrs pcommon.Map, normalize bool, keys ...string) string { attrval, exists := attrs.Get(key) if exists { val = attrval.AsString() + break } } diff --git a/pkg/trace/transform/transform.go b/pkg/trace/transform/transform.go index ff245517d16fa..f19af44b5d636 100644 --- a/pkg/trace/transform/transform.go +++ b/pkg/trace/transform/transform.go @@ -78,27 +78,20 @@ func OtelSpanToDDSpan( otelspan ptrace.Span, otelres pcommon.Resource, lib pcommon.InstrumentationScope, - topLevelByKind bool, conf *config.AgentConfig, peerTagKeys []string, ) *pb.Span { spanKind := otelspan.Kind() - isTopLevel := otelspan.ParentSpanID() == pcommon.NewSpanIDEmpty() || spanKind == ptrace.SpanKindServer || spanKind == ptrace.SpanKindConsumer - + topLevelByKind := conf.HasFeature("enable_otlp_compute_top_level_by_span_kind") + isTopLevel := false + if topLevelByKind { + isTopLevel = otelspan.ParentSpanID() == pcommon.NewSpanIDEmpty() || spanKind == ptrace.SpanKindServer || spanKind == ptrace.SpanKindConsumer + } ddspan := OtelSpanToDDSpanMinimal(otelspan, otelres, lib, isTopLevel, topLevelByKind, conf, peerTagKeys) otelres.Attributes().Range(func(k string, v pcommon.Value) bool { - value := v.AsString() - if k == "analytics.event" { - if v, err := strconv.ParseBool(value); err == nil { - if v { - ddspan.Metrics[sampler.KeySamplingRateEventExtraction] = 1 - } else { - ddspan.Metrics[sampler.KeySamplingRateEventExtraction] = 0 - } - } - } else if k != "service.name" && k != "operation.name" && k != "resource.name" && k != "span.type" { - ddspan.Meta[k] = value + if k != "service.name" && k != "operation.name" && k != "resource.name" && k != "span.type" { + SetMetaOTLP(ddspan, k, v.AsString()) } return true }) @@ -111,6 +104,13 @@ func OtelSpanToDDSpan( } } + // TODO(songy23): use AttributeDeploymentEnvironmentName once collector version upgrade is unblocked + if _, ok := ddspan.Meta["env"]; !ok { + if env := traceutil.GetOTelAttrValInResAndSpanAttrs(otelspan, otelres, true, "deployment.environment.name", semconv.AttributeDeploymentEnvironment); env != "" { + ddspan.Meta["env"] = env + } + } + if otelspan.Events().Len() > 0 { ddspan.Meta["events"] = MarshalEvents(otelspan.Events()) } @@ -132,7 +132,7 @@ func OtelSpanToDDSpan( // Exclude Datadog APM conventions. // These are handled below explicitly. if k != "http.method" && k != "http.status_code" { - ddspan.Meta[k] = value + SetMetaOTLP(ddspan, k, value) } } diff --git a/pkg/util/clusteragent/clusteragent.go b/pkg/util/clusteragent/clusteragent.go index ab6d18cb04aa5..b378ccbbb7a66 100644 --- a/pkg/util/clusteragent/clusteragent.go +++ b/pkg/util/clusteragent/clusteragent.go @@ -14,9 +14,6 @@ import ( "io" "net" "net/http" - "net/url" - "os" - "strings" "sync" "time" @@ -26,6 +23,7 @@ import ( apiv1 "github.com/DataDog/datadog-agent/pkg/clusteragent/api/v1" "github.com/DataDog/datadog-agent/pkg/clusteragent/clusterchecks/types" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" + "github.com/DataDog/datadog-agent/pkg/config/utils" "github.com/DataDog/datadog-agent/pkg/errors" pbgo "github.com/DataDog/datadog-agent/pkg/proto/pbgo/process" "github.com/DataDog/datadog-agent/pkg/util/log" @@ -120,7 +118,7 @@ func GetClusterAgentClient() (DCAClientInterface, error) { func (c *DCAClient) init() error { var err error - c.clusterAgentAPIEndpoint, err = GetClusterAgentEndpoint() + c.clusterAgentAPIEndpoint, err = utils.GetClusterAgentEndpoint() if err != nil { return err } @@ -216,72 +214,6 @@ func (c *DCAClient) initLeaderClient() { c.leaderClient = newLeaderClient(c.clusterAgentAPIClient, c.clusterAgentAPIEndpoint) } -// GetClusterAgentEndpoint provides a validated https endpoint from configuration keys in datadog.yaml: -// 1st. configuration key "cluster_agent.url" (or the DD_CLUSTER_AGENT_URL environment variable), -// -// add the https prefix if the scheme isn't specified -// -// 2nd. environment variables associated with "cluster_agent.kubernetes_service_name" -// -// ${dcaServiceName}_SERVICE_HOST and ${dcaServiceName}_SERVICE_PORT -func GetClusterAgentEndpoint() (string, error) { - const configDcaURL = "cluster_agent.url" - const configDcaSvcName = "cluster_agent.kubernetes_service_name" - - dcaURL := pkgconfigsetup.Datadog().GetString(configDcaURL) - if dcaURL != "" { - if strings.HasPrefix(dcaURL, "http://") { - return "", fmt.Errorf("cannot get cluster agent endpoint, not a https scheme: %s", dcaURL) - } - if !strings.Contains(dcaURL, "://") { - log.Tracef("Adding https scheme to %s: https://%s", dcaURL, dcaURL) - dcaURL = fmt.Sprintf("https://%s", dcaURL) - } - u, err := url.Parse(dcaURL) - if err != nil { - return "", err - } - if u.Scheme != "https" { - return "", fmt.Errorf("cannot get cluster agent endpoint, not a https scheme: %s", u.Scheme) - } - log.Debugf("Connecting to the configured URL for the Datadog Cluster Agent: %s", dcaURL) - return u.String(), nil - } - - // Construct the URL with the Kubernetes service environment variables - // *_SERVICE_HOST and *_SERVICE_PORT - dcaSvc := pkgconfigsetup.Datadog().GetString(configDcaSvcName) - log.Debugf("Identified service for the Datadog Cluster Agent: %s", dcaSvc) - if dcaSvc == "" { - return "", fmt.Errorf("cannot get a cluster agent endpoint, both %s and %s are empty", configDcaURL, configDcaSvcName) - } - - dcaSvc = strings.ToUpper(dcaSvc) - dcaSvc = strings.Replace(dcaSvc, "-", "_", -1) // Kubernetes replaces "-" with "_" in the service names injected in the env var. - - // host - dcaSvcHostEnv := fmt.Sprintf("%s_SERVICE_HOST", dcaSvc) - dcaSvcHost := os.Getenv(dcaSvcHostEnv) - if dcaSvcHost == "" { - return "", fmt.Errorf("cannot get a cluster agent endpoint for kubernetes service %s, env %s is empty", dcaSvc, dcaSvcHostEnv) - } - - // port - dcaSvcPort := os.Getenv(fmt.Sprintf("%s_SERVICE_PORT", dcaSvc)) - if dcaSvcPort == "" { - return "", fmt.Errorf("cannot get a cluster agent endpoint for kubernetes service %s, env %s is empty", dcaSvc, dcaSvcPort) - } - - // validate the URL - dcaURL = fmt.Sprintf("https://%s:%s", dcaSvcHost, dcaSvcPort) - u, err := url.Parse(dcaURL) - if err != nil { - return "", err - } - - return u.String(), nil -} - // Version returns ClusterAgentVersion already stored in the DCAClient // It refreshes the cached version before returning it if withRefresh is true func (c *DCAClient) Version(withRefresh bool) version.Version { diff --git a/pkg/util/clusteragent/clusteragent_test.go b/pkg/util/clusteragent/clusteragent_test.go index f126bc283ab2f..a02bfa8f8a0c5 100644 --- a/pkg/util/clusteragent/clusteragent_test.go +++ b/pkg/util/clusteragent/clusteragent_test.go @@ -279,11 +279,8 @@ type clusterAgentSuite struct { } const ( - clusterAgentServiceName = "DATADOG_CLUSTER_AGENT" - clusterAgentServiceHost = clusterAgentServiceName + "_SERVICE_HOST" - clusterAgentServicePort = clusterAgentServiceName + "_SERVICE_PORT" - clusterAgentTokenValue = "01234567890123456789012345678901" - clcRunnerIP = "10.92.1.39" + clusterAgentTokenValue = "01234567890123456789012345678901" + clcRunnerIP = "10.92.1.39" ) func (suite *clusterAgentSuite) SetupTest() { @@ -292,16 +289,6 @@ func (suite *clusterAgentSuite) SetupTest() { suite.config.SetWithoutSource("cluster_agent.url", "") suite.config.SetWithoutSource("cluster_agent.kubernetes_service_name", "") suite.config.SetWithoutSource("clc_runner_host", clcRunnerIP) - os.Unsetenv(clusterAgentServiceHost) - os.Unsetenv(clusterAgentServicePort) -} - -func (suite *clusterAgentSuite) TestGetClusterAgentEndpointEmpty() { - suite.config.SetWithoutSource("cluster_agent.url", "") - suite.config.SetWithoutSource("cluster_agent.kubernetes_service_name", "") - - _, err := GetClusterAgentEndpoint() - require.NotNil(suite.T(), err) } func (suite *clusterAgentSuite) TestGetClusterAgentAuthTokenEmpty() { @@ -361,64 +348,6 @@ func (suite *clusterAgentSuite) TestGetClusterAgentAuthTokenTooShort() { require.NotNil(suite.T(), err, fmt.Sprintf("%v", err)) } -func (suite *clusterAgentSuite) TestGetClusterAgentEndpointFromUrl() { - suite.config.SetWithoutSource("cluster_agent.url", "https://127.0.0.1:8080") - suite.config.SetWithoutSource("cluster_agent.kubernetes_service_name", "") - _, err := GetClusterAgentEndpoint() - require.Nil(suite.T(), err, fmt.Sprintf("%v", err)) - - suite.config.SetWithoutSource("cluster_agent.url", "https://127.0.0.1") - _, err = GetClusterAgentEndpoint() - require.Nil(suite.T(), err, fmt.Sprintf("%v", err)) - - suite.config.SetWithoutSource("cluster_agent.url", "127.0.0.1") - endpoint, err := GetClusterAgentEndpoint() - require.Nil(suite.T(), err, fmt.Sprintf("%v", err)) - assert.Equal(suite.T(), "https://127.0.0.1", endpoint) - - suite.config.SetWithoutSource("cluster_agent.url", "127.0.0.1:1234") - endpoint, err = GetClusterAgentEndpoint() - require.Nil(suite.T(), err, fmt.Sprintf("%v", err)) - assert.Equal(suite.T(), "https://127.0.0.1:1234", endpoint) -} - -func (suite *clusterAgentSuite) TestGetClusterAgentEndpointFromUrlInvalid() { - suite.config.SetWithoutSource("cluster_agent.url", "http://127.0.0.1:8080") - suite.config.SetWithoutSource("cluster_agent.kubernetes_service_name", "") - _, err := GetClusterAgentEndpoint() - require.NotNil(suite.T(), err) - - suite.config.SetWithoutSource("cluster_agent.url", "tcp://127.0.0.1:8080") - _, err = GetClusterAgentEndpoint() - require.NotNil(suite.T(), err) -} - -func (suite *clusterAgentSuite) TestGetClusterAgentEndpointFromKubernetesSvc() { - suite.config.SetWithoutSource("cluster_agent.url", "") - suite.config.SetWithoutSource("cluster_agent.kubernetes_service_name", "datadog-cluster-agent") - suite.T().Setenv(clusterAgentServiceHost, "127.0.0.1") - suite.T().Setenv(clusterAgentServicePort, "443") - - endpoint, err := GetClusterAgentEndpoint() - require.Nil(suite.T(), err, fmt.Sprintf("%v", err)) - assert.Equal(suite.T(), "https://127.0.0.1:443", endpoint) -} - -func (suite *clusterAgentSuite) TestGetClusterAgentEndpointFromKubernetesSvcEmpty() { - suite.config.SetWithoutSource("cluster_agent.url", "") - suite.config.SetWithoutSource("cluster_agent.kubernetes_service_name", "datadog-cluster-agent") - suite.T().Setenv(clusterAgentServiceHost, "127.0.0.1") - suite.T().Setenv(clusterAgentServicePort, "") - - _, err := GetClusterAgentEndpoint() - require.NotNil(suite.T(), err, fmt.Sprintf("%v", err)) - - suite.T().Setenv(clusterAgentServiceHost, "") - suite.T().Setenv(clusterAgentServicePort, "443") - _, err = GetClusterAgentEndpoint() - require.NotNil(suite.T(), err, fmt.Sprintf("%v", err)) -} - func (suite *clusterAgentSuite) TestGetKubernetesNodeLabels() { dca, err := newDummyClusterAgent(suite.config) require.Nil(suite.T(), err, fmt.Sprintf("%v", err)) diff --git a/pkg/util/containerd/containerd_util.go b/pkg/util/containerd/containerd_util.go index 88fe4ecd91820..95e69f5bb7734 100644 --- a/pkg/util/containerd/containerd_util.go +++ b/pkg/util/containerd/containerd_util.go @@ -20,8 +20,10 @@ import ( "github.com/hashicorp/go-multierror" "github.com/opencontainers/image-spec/identity" + "github.com/DataDog/datadog-agent/pkg/config/env" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" dderrors "github.com/DataDog/datadog-agent/pkg/errors" + "github.com/DataDog/datadog-agent/pkg/util/containers/image" "github.com/DataDog/datadog-agent/pkg/util/log" "github.com/DataDog/datadog-agent/pkg/util/retry" @@ -454,30 +456,32 @@ func (c *ContainerdUtil) getMounts(ctx context.Context, expiration time.Duration return nil, nil, fmt.Errorf("No snapshots returned for image: %s", imageID) } - for i := range mounts { - mounts[i].Source = sanitizePath(mounts[i].Source) - - var errs error - for j, opt := range mounts[i].Options { - for _, prefix := range []string{"upperdir=", "lowerdir=", "workdir="} { - if strings.HasPrefix(opt, prefix) { - trimmedOpt := strings.TrimPrefix(opt, prefix) - dirs := strings.Split(trimmedOpt, ":") - for n, dir := range dirs { - dirs[n] = sanitizePath(dir) - if _, err := os.Stat(dirs[n]); err != nil { - errs = multierror.Append(errs, fmt.Errorf("unreachable folder %s for overlayfs mount: %w", dir, err)) + if env.IsContainerized() { + for i := range mounts { + mounts[i].Source = image.SanitizeHostPath(mounts[i].Source) + + var errs error + for j, opt := range mounts[i].Options { + for _, prefix := range []string{"upperdir=", "lowerdir=", "workdir="} { + if strings.HasPrefix(opt, prefix) { + trimmedOpt := strings.TrimPrefix(opt, prefix) + dirs := strings.Split(trimmedOpt, ":") + for n, dir := range dirs { + dirs[n] = image.SanitizeHostPath(dir) + if _, err := os.Stat(dirs[n]); err != nil { + errs = multierror.Append(errs, fmt.Errorf("unreachable folder %s for overlayfs mount: %w", dir, err)) + } } + mounts[i].Options[j] = prefix + strings.Join(dirs, ":") } - mounts[i].Options[j] = prefix + strings.Join(dirs, ":") } - } - log.Debugf("Sanitized overlayfs mount options to %s", strings.Join(mounts[i].Options, ",")) - } + log.Debugf("Sanitized overlayfs mount options to %s", strings.Join(mounts[i].Options, ",")) + } - if errs != nil { - log.Warnf("Unreachable path detected in mounts for image %s: %s", imageID, errs.Error()) + if errs != nil { + log.Warnf("Unreachable path detected in mounts for image %s: %s", imageID, errs.Error()) + } } } @@ -493,14 +497,6 @@ func (c *ContainerdUtil) getMounts(ctx context.Context, expiration time.Duration }, nil } -func sanitizePath(path string) string { - if index := strings.Index(path, "/var/lib"); index != -1 { - return "/host" + path[index:] - } - - return path -} - // Mounts returns the mounts for an image func (c *ContainerdUtil) Mounts(ctx context.Context, expiration time.Duration, namespace string, img containerd.Image) ([]mount.Mount, error) { mounts, clean, err := c.getMounts(ctx, expiration, namespace, img) diff --git a/pkg/util/containers/image/image.go b/pkg/util/containers/image/image.go index eaccc3f174460..b9886c2f70dc7 100644 --- a/pkg/util/containers/image/image.go +++ b/pkg/util/containers/image/image.go @@ -8,6 +8,7 @@ package image import ( "errors" + "os" "strings" ) @@ -60,3 +61,17 @@ func SplitImageName(image string) (string, string, string, string, error) { } return long, registry, short, tag, nil } + +// SanitizeHostPath changes the specified path by prepending the mount point of the host's filesystem +func SanitizeHostPath(path string) string { + hostPath := os.Getenv("HOST_ROOT") + if hostPath == "" { + hostPath = "/host" + } + + if index := strings.Index(path, "/var/lib"); index != -1 { + return hostPath + path[index:] + } + + return hostPath + path +} diff --git a/pkg/util/ec2/ec2.go b/pkg/util/ec2/ec2.go index 05cef31e3488c..91301ae37f6e0 100644 --- a/pkg/util/ec2/ec2.go +++ b/pkg/util/ec2/ec2.go @@ -36,6 +36,8 @@ var ( // DMIBoardVendor contains the DMI board vendor for EC2 DMIBoardVendor = "Amazon EC2" + ec2IMDSv2TransitionPayloadConfigFlag = "ec2_imdsv2_transition_payload_enabled" + currentMetadataSource = metadataSourceNone currentMetadataSourceMutex sync.Mutex ) @@ -94,16 +96,30 @@ func GetSourceName() string { } var instanceIDFetcher = cachedfetch.Fetcher{ - Name: "EC2 InstanceID", + Name: "EC2 or DMI InstanceID", Attempt: func(ctx context.Context) (interface{}, error) { - return getMetadataItemWithMaxLength(ctx, imdsInstanceID, false) + hostname, err := getMetadataItemWithMaxLength(ctx, imdsInstanceID, getIMDSVersion(false, false), true) + if err != nil { + if pkgconfigsetup.Datadog().GetBool(ec2IMDSv2TransitionPayloadConfigFlag) { + log.Debugf("Failed to get instance ID from IMDSv2 - ec2_imdsv2_transition_payload_enabled is set, falling back on DMI: %s", err.Error()) + return getInstanceIDFromDMI() + } + } + return hostname, err }, } var imdsv2InstanceIDFetcher = cachedfetch.Fetcher{ Name: "EC2 IMDSv2 InstanceID", Attempt: func(ctx context.Context) (interface{}, error) { - return getMetadataItemWithMaxLength(ctx, imdsInstanceID, true) + return getMetadataItemWithMaxLength(ctx, imdsInstanceID, imdsV2, true) + }, +} + +var legacyInstanceIDFetcher = cachedfetch.Fetcher{ + Name: "EC2 no IMDSv2 no DMI InstanceID", + Attempt: func(ctx context.Context) (interface{}, error) { + return getMetadataItemWithMaxLength(ctx, imdsInstanceID, imdsV1, false) }, } @@ -112,6 +128,11 @@ func GetInstanceID(ctx context.Context) (string, error) { return instanceIDFetcher.FetchString(ctx) } +// GetLegacyResolutionInstanceID fetches the instance id for current host from the EC2 metadata API without using IMDSv2 or DMI (ie: only IMDSv1) +func GetLegacyResolutionInstanceID(ctx context.Context) (string, error) { + return legacyInstanceIDFetcher.FetchString(ctx) +} + // GetIDMSv2InstanceID fetches the instance id for current host from the IMDSv2 EC2 metadata API func GetIDMSv2InstanceID(ctx context.Context) (string, error) { return imdsv2InstanceIDFetcher.FetchString(ctx) @@ -119,7 +140,7 @@ func GetIDMSv2InstanceID(ctx context.Context) (string, error) { // GetHostID returns the instanceID for the current EC2 host using IMDSv2 only. func GetHostID(ctx context.Context) string { - instanceID, err := getMetadataItemWithMaxLength(ctx, imdsInstanceID, true) + instanceID, err := getMetadataItemWithMaxLength(ctx, imdsInstanceID, imdsV2, true) log.Debugf("instanceID from IMDSv2 '%s' (error: %v)", instanceID, err) if err == nil { @@ -156,7 +177,8 @@ func GetHostAliases(ctx context.Context) ([]string, error) { log.Debugf("failed to get instance ID from DMI for Host Alias: %s", err) // Try to use IMSDv2 if GetInstanceID didn't try it already - if !UseIMDSv2(false) { + imdsv2Action := getIMDSVersion(false, false) + if imdsv2Action == imdsV1 { imsdv2InstanceID, err := GetIDMSv2InstanceID(ctx) if err == nil { return []string{imsdv2InstanceID}, nil @@ -171,7 +193,7 @@ func GetHostAliases(ctx context.Context) ([]string, error) { var hostnameFetcher = cachedfetch.Fetcher{ Name: "EC2 Hostname", Attempt: func(ctx context.Context) (interface{}, error) { - return getMetadataItemWithMaxLength(ctx, imdsHostname, false) + return getMetadataItemWithMaxLength(ctx, imdsHostname, getIMDSVersion(false, false), true) }, } diff --git a/pkg/util/ec2/ec2_tags.go b/pkg/util/ec2/ec2_tags.go index d60f93bf6256b..359f473decab7 100644 --- a/pkg/util/ec2/ec2_tags.go +++ b/pkg/util/ec2/ec2_tags.go @@ -56,7 +56,7 @@ func fetchEc2Tags(ctx context.Context) ([]string, error) { } func fetchEc2TagsFromIMDS(ctx context.Context) ([]string, error) { - keysStr, err := getMetadataItem(ctx, imdsTags, false) + keysStr, err := getMetadataItem(ctx, imdsTags, getIMDSVersion(false, false), true) if err != nil { return nil, err } @@ -73,7 +73,7 @@ func fetchEc2TagsFromIMDS(ctx context.Context) ([]string, error) { // > keys can only use letters (a-z, A-Z), numbers (0-9), and the // > following characters: -_+=,.@:. Instance tag keys can't use spaces, // > /, or the reserved names ., .., or _index. - val, err := getMetadataItem(ctx, imdsTags+"/"+key, false) + val, err := getMetadataItem(ctx, imdsTags+"/"+key, getIMDSVersion(false, false), true) if err != nil { return nil, err } @@ -194,7 +194,7 @@ type EC2Identity struct { // GetInstanceIdentity returns the instance identity document for the current instance func GetInstanceIdentity(ctx context.Context) (*EC2Identity, error) { instanceIdentity := &EC2Identity{} - res, err := doHTTPRequest(ctx, instanceIdentityURL, false) + res, err := doHTTPRequest(ctx, instanceIdentityURL, getIMDSVersion(false, false), true) if err != nil { return instanceIdentity, fmt.Errorf("unable to fetch EC2 API to get identity: %s", err) } @@ -221,7 +221,7 @@ func getSecurityCreds(ctx context.Context) (*ec2SecurityCred, error) { return iamParams, err } - res, err := doHTTPRequest(ctx, metadataURL+"/iam/security-credentials/"+iamRole, false) + res, err := doHTTPRequest(ctx, metadataURL+"/iam/security-credentials/"+iamRole, getIMDSVersion(false, false), true) if err != nil { return iamParams, fmt.Errorf("unable to fetch EC2 API to get iam role: %s", err) } @@ -234,7 +234,7 @@ func getSecurityCreds(ctx context.Context) (*ec2SecurityCred, error) { } func getIAMRole(ctx context.Context) (string, error) { - res, err := doHTTPRequest(ctx, metadataURL+"/iam/security-credentials/", false) + res, err := doHTTPRequest(ctx, metadataURL+"/iam/security-credentials/", getIMDSVersion(false, false), true) if err != nil { return "", fmt.Errorf("unable to fetch EC2 API to get security credentials: %s", err) } diff --git a/pkg/util/ec2/imds_helpers.go b/pkg/util/ec2/imds_helpers.go index 845d75b9c1471..c59fff2fa5d61 100644 --- a/pkg/util/ec2/imds_helpers.go +++ b/pkg/util/ec2/imds_helpers.go @@ -24,6 +24,15 @@ var ( imdsNetworkMacs = "/network/interfaces/macs" ) +// imdsVersion is an enum to determine how to interact with the IMDSv2 option +type imdsVersion int + +const ( + imdsV1 imdsVersion = iota + imdsAllVersions + imdsV2 +) + func getToken(ctx context.Context) (string, time.Time, error) { tokenLifetime := time.Duration(pkgconfigsetup.Datadog().GetInt("ec2_metadata_token_lifetime")) * time.Second // Set the local expiration date before requesting the metadata endpoint so the local expiration date will always @@ -44,8 +53,8 @@ func getToken(ctx context.Context) (string, time.Time, error) { return res, expirationDate, nil } -func getMetadataItemWithMaxLength(ctx context.Context, endpoint string, forceIMDSv2 bool) (string, error) { - result, err := getMetadataItem(ctx, endpoint, forceIMDSv2) +func getMetadataItemWithMaxLength(ctx context.Context, endpoint string, allowedIMDSVersions imdsVersion, updateMetadataSource bool) (string, error) { + result, err := getMetadataItem(ctx, endpoint, allowedIMDSVersions, updateMetadataSource) if err != nil { return result, err } @@ -57,39 +66,50 @@ func getMetadataItemWithMaxLength(ctx context.Context, endpoint string, forceIMD return result, err } -func getMetadataItem(ctx context.Context, endpoint string, forceIMDSv2 bool) (string, error) { +func getMetadataItem(ctx context.Context, endpoint string, allowedIMDSVersions imdsVersion, updateMetadataSource bool) (string, error) { if !pkgconfigsetup.IsCloudProviderEnabled(CloudProviderName, pkgconfigsetup.Datadog()) { return "", fmt.Errorf("cloud provider is disabled by configuration") } - return doHTTPRequest(ctx, metadataURL+endpoint, forceIMDSv2) + return doHTTPRequest(ctx, metadataURL+endpoint, allowedIMDSVersions, updateMetadataSource) } -// UseIMDSv2 returns true if the agent should use IMDSv2 -func UseIMDSv2(forceIMDSv2 bool) bool { - return pkgconfigsetup.Datadog().GetBool("ec2_prefer_imdsv2") || forceIMDSv2 +// getIMDSVersion returns true if the agent should use IMDSv2 +func getIMDSVersion(force bool, disable bool) imdsVersion { + // if force is set, we use IMDSv2, highest priority + if force { + return imdsV2 + // if disable is set, we disable IMDSv2 + } else if disable { + return imdsV1 + // if ec2_prefer_imdsv2 is set, we use IMDSv2 + } else if pkgconfigsetup.Datadog().GetBool("ec2_prefer_imdsv2") || pkgconfigsetup.Datadog().GetBool("ec2_imdsv2_transition_payload_enabled") { + return imdsAllVersions + } + // if nothing indicates to use IMDSv2, we default to IMDSv1 + return imdsV1 } -func doHTTPRequest(ctx context.Context, url string, forceIMDSv2 bool) (string, error) { +func doHTTPRequest(ctx context.Context, url string, allowedIMDSVersions imdsVersion, updateMetadataSource bool) (string, error) { source := metadataSourceIMDSv1 headers := map[string]string{} - if UseIMDSv2(forceIMDSv2) { + if allowedIMDSVersions == imdsAllVersions || allowedIMDSVersions == imdsV2 { tokenValue, err := token.Get(ctx) if err != nil { - if forceIMDSv2 { + if allowedIMDSVersions == imdsV2 { return "", fmt.Errorf("could not fetch token from IMDSv2") } log.Warnf("ec2_prefer_imdsv2 is set to true in the configuration but the agent was unable to proceed: %s", err) } else { headers["X-aws-ec2-metadata-token"] = tokenValue - if !forceIMDSv2 { + if allowedIMDSVersions != imdsV2 { source = metadataSourceIMDSv2 } } } res, err := httputils.Get(ctx, url, headers, time.Duration(pkgconfigsetup.Datadog().GetInt("ec2_metadata_timeout"))*time.Millisecond, pkgconfigsetup.Datadog()) // We don't want to register the source when we force imdsv2 - if err == nil && !forceIMDSv2 { + if err == nil && allowedIMDSVersions != imdsV2 && updateMetadataSource { setCloudProviderSource(source) } return res, err diff --git a/pkg/util/ec2/network.go b/pkg/util/ec2/network.go index a7fa4730513a7..f40e4a913b96c 100644 --- a/pkg/util/ec2/network.go +++ b/pkg/util/ec2/network.go @@ -18,7 +18,7 @@ import ( var publicIPv4Fetcher = cachedfetch.Fetcher{ Name: "EC2 Public IPv4 Address", Attempt: func(ctx context.Context) (interface{}, error) { - return getMetadataItem(ctx, imdsIPv4, false) + return getMetadataItem(ctx, imdsIPv4, getIMDSVersion(false, false), true) }, } @@ -30,7 +30,7 @@ func GetPublicIPv4(ctx context.Context) (string, error) { var networkIDFetcher = cachedfetch.Fetcher{ Name: "VPC IDs", Attempt: func(ctx context.Context) (interface{}, error) { - resp, err := getMetadataItem(ctx, imdsNetworkMacs, true) + resp, err := getMetadataItem(ctx, imdsNetworkMacs, imdsV2, true) if err != nil { return "", fmt.Errorf("EC2: GetNetworkID failed to get mac addresses: %w", err) } @@ -43,7 +43,7 @@ var networkIDFetcher = cachedfetch.Fetcher{ continue } mac = strings.TrimSuffix(mac, "/") - id, err := getMetadataItem(ctx, fmt.Sprintf("%s/%s/vpc-id", imdsNetworkMacs, mac), true) + id, err := getMetadataItem(ctx, fmt.Sprintf("%s/%s/vpc-id", imdsNetworkMacs, mac), imdsV2, true) if err != nil { return "", fmt.Errorf("EC2: GetNetworkID failed to get vpc id for mac %s: %w", mac, err) } @@ -83,14 +83,14 @@ func GetSubnetForHardwareAddr(ctx context.Context, hwAddr net.HardwareAddr) (sub } var resp string - resp, err = getMetadataItem(ctx, fmt.Sprintf("%s/%s/subnet-id", imdsNetworkMacs, hwAddr), true) + resp, err = getMetadataItem(ctx, fmt.Sprintf("%s/%s/subnet-id", imdsNetworkMacs, hwAddr), imdsV2, true) if err != nil { return } subnet.ID = strings.TrimSpace(resp) - resp, err = getMetadataItem(ctx, fmt.Sprintf("%s/%s/subnet-ipv4-cidr-block", imdsNetworkMacs, hwAddr), true) + resp, err = getMetadataItem(ctx, fmt.Sprintf("%s/%s/subnet-ipv4-cidr-block", imdsNetworkMacs, hwAddr), imdsV2, true) if err != nil { return } diff --git a/pkg/util/hostname/common.go b/pkg/util/hostname/common.go index 059076775949c..9ab603a717916 100644 --- a/pkg/util/hostname/common.go +++ b/pkg/util/hostname/common.go @@ -25,14 +25,15 @@ import ( // for testing purposes var ( - isFargateInstance = fargate.IsFargateInstance - ec2GetInstanceID = ec2.GetInstanceID - isContainerized = env.IsContainerized //nolint:unused - gceGetHostname = gce.GetHostname - azureGetHostname = azure.GetHostname - osHostname = os.Hostname - fqdnHostname = getSystemFQDN - osHostnameUsable = isOSHostnameUsable + isFargateInstance = fargate.IsFargateInstance + ec2GetInstanceID = ec2.GetInstanceID + ec2GetLegacyResolutionInstanceID = ec2.GetLegacyResolutionInstanceID + isContainerized = env.IsContainerized //nolint:unused + gceGetHostname = gce.GetHostname + azureGetHostname = azure.GetHostname + osHostname = os.Hostname + fqdnHostname = getSystemFQDN + osHostnameUsable = isOSHostnameUsable ) // Data contains hostname and the hostname provider @@ -111,8 +112,14 @@ func fromOS(ctx context.Context, currentHostname string) (string, error) { return "", fmt.Errorf("OS hostname is not usable") } -func getValidEC2Hostname(ctx context.Context) (string, error) { - instanceID, err := ec2GetInstanceID(ctx) +func getValidEC2Hostname(ctx context.Context, legacyHostnameResolution bool) (string, error) { + var instanceID string + var err error + if legacyHostnameResolution { + instanceID, err = ec2GetLegacyResolutionInstanceID(ctx) + } else { + instanceID, err = ec2GetInstanceID(ctx) + } if err == nil { err = validate.ValidHostname(instanceID) if err == nil { @@ -123,7 +130,7 @@ func getValidEC2Hostname(ctx context.Context) (string, error) { return "", fmt.Errorf("Unable to determine hostname from EC2: %s", err) } -func fromEC2(ctx context.Context, currentHostname string) (string, error) { +func resolveEC2Hostname(ctx context.Context, currentHostname string, legacyHostnameResolution bool) (string, error) { // We use the instance id if we're on an ECS cluster or we're on EC2 // and the hostname is one of the default ones @@ -136,7 +143,7 @@ func fromEC2(ctx context.Context, currentHostname string) (string, error) { // or ec2_prioritize_instance_id_as_hostname is set to true if env.IsFeaturePresent(env.ECSEC2) || ec2.IsDefaultHostname(currentHostname) || prioritizeEC2Hostname { log.Debugf("Trying to fetch hostname from EC2 metadata") - return getValidEC2Hostname(ctx) + return getValidEC2Hostname(ctx, legacyHostnameResolution) } else if ec2.IsWindowsDefaultHostname(currentHostname) { log.Debugf("Default EC2 Windows hostname detected") // Display a message when enabling `ec2_use_windows_prefix_detection` would make the hostname resolution change. @@ -144,7 +151,7 @@ func fromEC2(ctx context.Context, currentHostname string) (string, error) { // As we are in the else clause `ec2.IsDefaultHostname(currentHostname)` is false. If // `ec2.IsWindowsDefaultHostname(currentHostname)` // is `true` that means `ec2_use_windows_prefix_detection` is set to false. - ec2Hostname, err := getValidEC2Hostname(ctx) + ec2Hostname, err := getValidEC2Hostname(ctx, legacyHostnameResolution) // Check if we get a valid hostname when enabling `ec2_use_windows_prefix_detection` and the hostnames are different. if err == nil && ec2Hostname != currentHostname { @@ -155,3 +162,11 @@ func fromEC2(ctx context.Context, currentHostname string) (string, error) { } return "", fmt.Errorf("not retrieving hostname from AWS: the host is not an ECS instance and other providers already retrieve non-default hostnames") } + +func fromEC2(ctx context.Context, currentHostname string) (string, error) { + return resolveEC2Hostname(ctx, currentHostname, false) +} + +func fromEC2WithLegacyHostnameResolution(ctx context.Context, currentHostname string) (string, error) { + return resolveEC2Hostname(ctx, currentHostname, true) +} diff --git a/pkg/util/hostname/providers.go b/pkg/util/hostname/providers.go index b8fac38c6b4ff..c24f821892809 100644 --- a/pkg/util/hostname/providers.go +++ b/pkg/util/hostname/providers.go @@ -13,13 +13,14 @@ import ( "fmt" "github.com/DataDog/datadog-agent/comp/core/hostname/hostnameinterface" + pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/util/cache" "github.com/DataDog/datadog-agent/pkg/util/log" ) const ( - configProvider = hostnameinterface.ConfigProvider - fargateProvider = hostnameinterface.FargateProvider + configProviderName = hostnameinterface.ConfigProvider + fargateProviderName = hostnameinterface.FargateProvider ) var ( @@ -50,79 +51,115 @@ type provider struct { expvarName string } -// providerCatalog holds all the various kinds of hostname providers -// -// The order if this list matters: -// * Config (`hostname') -// * Config (`hostname_file') -// * Fargate -// * GCE -// * Azure -// * container (kube_apiserver, Docker, kubelet) -// * FQDN -// * OS hostname -// * EC2 -var providerCatalog = []provider{ - { - name: configProvider, +// List of hostname providers +var ( + configProvider = provider{ + name: configProviderName, cb: fromConfig, stopIfSuccessful: true, expvarName: "'hostname' configuration/environment", - }, - { + } + + hostnameFileProvider = provider{ name: "hostnameFile", cb: fromHostnameFile, stopIfSuccessful: true, expvarName: "'hostname_file' configuration/environment", - }, - { - name: fargateProvider, + } + + fargateProvider = provider{ + name: fargateProviderName, cb: fromFargate, stopIfSuccessful: true, expvarName: "fargate", - }, - { + } + + gceProvider = provider{ name: "gce", cb: fromGCE, stopIfSuccessful: true, expvarName: "gce", - }, - { + } + + azureProvider = provider{ name: "azure", cb: fromAzure, stopIfSuccessful: true, expvarName: "azure", - }, + } // The following providers are coupled. Their behavior changes depending on the result of the previous provider. // Therefore 'stopIfSuccessful' is set to false. - { + fqdnProvider = provider{ name: "fqdn", cb: fromFQDN, stopIfSuccessful: false, expvarName: "fqdn", - }, - { + } + + containerProvider = provider{ name: "container", cb: fromContainer, stopIfSuccessful: false, expvarName: "container", - }, - { + } + + osProvider = provider{ name: "os", cb: fromOS, stopIfSuccessful: false, expvarName: "os", - }, - { + } + + ec2Provider = provider{ name: "aws", // ie EC2 cb: fromEC2, stopIfSuccessful: false, expvarName: "aws", - }, + } + + ec2HostnameResolutionProvider = provider{ + name: "aws", + cb: fromEC2WithLegacyHostnameResolution, + stopIfSuccessful: false, + expvarName: "aws", + } +) + +// providerCatalog holds all the various kinds of hostname providers +// +// The order if this list matters: +// * Config (`hostname') +// * Config (`hostname_file') +// * Fargate +// * GCE +// * Azure +// * FQDN +// * container (kube_apiserver, Docker, kubelet) +// * OS hostname +// * EC2 +func getProviderCatalog(legacyHostnameResolution bool) []provider { + providerCatalog := []provider{ + configProvider, + hostnameFileProvider, + fargateProvider, + gceProvider, + azureProvider, + fqdnProvider, + containerProvider, + osProvider, + } + + if legacyHostnameResolution { + providerCatalog = append(providerCatalog, ec2HostnameResolutionProvider) + } else { + providerCatalog = append(providerCatalog, ec2Provider) + } + + return providerCatalog } -func saveHostname(cacheHostnameKey string, hostname string, providerName string) Data { +func saveHostname(cacheHostnameKey string, hostname string, providerName string, legacyHostnameResolution bool) Data { data := Data{ Hostname: hostname, Provider: providerName, @@ -131,7 +168,7 @@ func saveHostname(cacheHostnameKey string, hostname string, providerName string) cache.Cache.Set(cacheHostnameKey, data, cache.NoExpiration) // We don't have a hostname on fargate. 'fromFargate' will return an empty hostname and we don't want to show it // in the status page. - if providerName != "" && providerName != fargateProvider { + if providerName != "" && providerName != fargateProviderName && !legacyHostnameResolution { hostnameProvider.Set(providerName) } return data @@ -139,7 +176,21 @@ func saveHostname(cacheHostnameKey string, hostname string, providerName string) // GetWithProvider returns the hostname for the Agent and the provider that was use to retrieve it func GetWithProvider(ctx context.Context) (Data, error) { - cacheHostnameKey := cache.BuildAgentKey("hostname") + return getHostname(ctx, "hostname", false) +} + +// GetWithProviderLegacyResolution returns the hostname for the Agent and the provider that was used to retrieve it without using IMDSv2 and MDI +func GetWithProviderLegacyResolution(ctx context.Context) (Data, error) { + // If the user has set the ec2_prefer_imdsv2 then IMDSv2 is used by default by the user, `legacy_resolution_hostname` is not needed for the transition + // If the user has set the ec2_imdsv2_transition_payload_enabled then IMDSv2 is used by default by the agent, `legacy_resolution_hostname` is needed for the transition + if pkgconfigsetup.Datadog().GetBool("ec2_prefer_imdsv2") || !pkgconfigsetup.Datadog().GetBool("ec2_imdsv2_transition_payload_enabled") { + return Data{}, nil + } + return getHostname(ctx, "legacy_resolution_hostname", true) +} + +func getHostname(ctx context.Context, keyCache string, legacyHostnameResolution bool) (Data, error) { + cacheHostnameKey := cache.BuildAgentKey(keyCache) // first check if we have a hostname cached if cacheHostname, found := cache.Cache.Get(cacheHostnameKey); found { @@ -150,7 +201,7 @@ func GetWithProvider(ctx context.Context) (Data, error) { var hostname string var providerName string - for _, p := range providerCatalog { + for _, p := range getProviderCatalog(legacyHostnameResolution) { log.Debugf("trying to get hostname from '%s' provider", p.name) detectedHostname, err := p.cb(ctx, hostname) @@ -168,14 +219,15 @@ func GetWithProvider(ctx context.Context) (Data, error) { if p.stopIfSuccessful { log.Debugf("hostname provider '%s' succeeded, stoping here with hostname '%s'", p.name, detectedHostname) - return saveHostname(cacheHostnameKey, hostname, p.name), nil + return saveHostname(cacheHostnameKey, hostname, p.name, legacyHostnameResolution), nil + } } warnAboutFQDN(ctx, hostname) if hostname != "" { - return saveHostname(cacheHostnameKey, hostname, providerName), nil + return saveHostname(cacheHostnameKey, hostname, providerName, legacyHostnameResolution), nil } err = fmt.Errorf("unable to reliably determine the host name. You can define one in the agent config file or in your hosts file") diff --git a/pkg/util/hostname/providers_test.go b/pkg/util/hostname/providers_test.go index 9060f9678a6d7..7001a03c76633 100644 --- a/pkg/util/hostname/providers_test.go +++ b/pkg/util/hostname/providers_test.go @@ -157,7 +157,7 @@ func TestFromConfigurationTrue(t *testing.T) { EC2: true, EC2Proritized: true, expectedHostname: "hostname-from-configuration", - expectedProvider: configProvider, + expectedProvider: configProviderName, }) data, err := GetWithProvider(context.TODO()) @@ -180,7 +180,7 @@ func TestHostnamePrority(t *testing.T) { EC2: true, EC2Proritized: true, expectedHostname: "hostname-from-configuration", - expectedProvider: configProvider, + expectedProvider: configProviderName, }, { name: "configuration hostname file", diff --git a/pkg/util/trivy/trivy.go b/pkg/util/trivy/trivy.go index a4fdb87e79c57..e39d387b06276 100644 --- a/pkg/util/trivy/trivy.go +++ b/pkg/util/trivy/trivy.go @@ -26,8 +26,10 @@ import ( "github.com/DataDog/datadog-agent/comp/core/config" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" + "github.com/DataDog/datadog-agent/pkg/config/env" "github.com/DataDog/datadog-agent/pkg/sbom" cutil "github.com/DataDog/datadog-agent/pkg/util/containerd" + containersimage "github.com/DataDog/datadog-agent/pkg/util/containers/image" "github.com/DataDog/datadog-agent/pkg/util/log" "github.com/DataDog/datadog-agent/pkg/util/optional" @@ -276,6 +278,13 @@ func (c *Collector) ScanDockerImageFromGraphDriver(ctx context.Context, imgMeta if layerDirs, ok := fanalImage.inspect.GraphDriver.Data["UpperDir"]; ok { layers = append(layers, strings.Split(layerDirs, ":")...) } + + if env.IsContainerized() { + for i, layer := range layers { + layers[i] = containersimage.SanitizeHostPath(layer) + } + } + return c.scanOverlayFS(ctx, layers, imgMeta, scanOptions) } @@ -297,6 +306,7 @@ func (c *Collector) ScanDockerImage(ctx context.Context, imgMeta *workloadmeta.C } func (c *Collector) scanOverlayFS(ctx context.Context, layers []string, imgMeta *workloadmeta.ContainerImageMetadata, scanOptions sbom.ScanOptions) (sbom.Report, error) { + log.Debugf("Generating SBOM for image %s using overlayfs %+v", imgMeta.ID, layers) overlayFsReader := NewFS(layers) report, err := c.scanFilesystem(ctx, overlayFsReader, "/", imgMeta, scanOptions) if err != nil { diff --git a/pkg/util/winutil/scmmonitor_test.go b/pkg/util/winutil/scmmonitor_test.go index 98ab9e70058a5..d0de2db184545 100644 --- a/pkg/util/winutil/scmmonitor_test.go +++ b/pkg/util/winutil/scmmonitor_test.go @@ -13,6 +13,7 @@ import ( "strings" "sync" "testing" + "time" "github.com/stretchr/testify/assert" "golang.org/x/sys/windows" @@ -27,18 +28,24 @@ func (so *saveOutput) Write(p []byte) (n int, err error) { return os.Stdout.Write(p) } -var startTime windows.Filetime +var startTime uint64 var startTimeOnce sync.Once func testGetProcessStartTimeAsNs(_ uint64) (uint64, error) { startTimeOnce.Do(func() { - windows.GetSystemTimeAsFileTime(&startTime) - // move the start a bit earlier to make sure it's always - // before current - startTime.LowDateTime -= 1000000 + var t windows.Filetime + windows.GetSystemTimeAsFileTime(&t) + // move the start a bit earlier to make sure it's always before current. + // 16ms is Windows time resolution, so use a few of those. + offset := (3 * 16 * time.Millisecond).Nanoseconds() + ns := t.Nanoseconds() + if ns < offset { + panic("time is too early") + } + startTime = uint64(ns - offset) }) - return uint64(startTime.Nanoseconds()), nil + return startTime, nil } func TestServices(t *testing.T) { diff --git a/release.json b/release.json index f15f3e2bdc996..05d2306bff73e 100644 --- a/release.json +++ b/release.json @@ -49,7 +49,7 @@ "OMNIBUS_RUBY_VERSION": "7.56.0-rc.1", "JMXFETCH_VERSION": "0.49.5", "JMXFETCH_HASH": "d29f945af0353905a5c801ab6b6ac027aa0cb27535470f464ca9254f6f36ef23", - "SECURITY_AGENT_POLICIES_VERSION": "v0.59.0", + "SECURITY_AGENT_POLICIES_VERSION": "v0.60.0", "MACOS_BUILD_VERSION": "6.56.0-rc.3", "WINDOWS_DDNPM_DRIVER": "release-signed", "WINDOWS_DDNPM_VERSION": "2.7.1", @@ -64,7 +64,7 @@ "OMNIBUS_RUBY_VERSION": "7.56.0-rc.1", "JMXFETCH_VERSION": "0.49.5", "JMXFETCH_HASH": "d29f945af0353905a5c801ab6b6ac027aa0cb27535470f464ca9254f6f36ef23", - "SECURITY_AGENT_POLICIES_VERSION": "v0.59.0", + "SECURITY_AGENT_POLICIES_VERSION": "v0.60.0", "MACOS_BUILD_VERSION": "7.56.0-rc.3", "WINDOWS_DDNPM_DRIVER": "release-signed", "WINDOWS_DDNPM_VERSION": "2.7.1", diff --git a/releasenotes/notes/apm-peer-tag-aggr-defaults-bd89eb1e93393219.yaml b/releasenotes/notes/apm-peer-tag-aggr-defaults-bd89eb1e93393219.yaml new file mode 100644 index 0000000000000..2c6ceeeff35fb --- /dev/null +++ b/releasenotes/notes/apm-peer-tag-aggr-defaults-bd89eb1e93393219.yaml @@ -0,0 +1,20 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +upgrade: + - | + * Parameter ``peer_tags_aggregation`` (a.k.a. environment variable ``DD_APM_PEER_TAGS_AGGREGATION``) is now enabled by default. This means that aggregation of peer related tags (e.g., `peer.service`, `db.instance`, etc.) now happens in the Agent, which enables statistics for Inferred Entities. If you want to disable this feature, set `peer_tags_aggregation` to `false` in your Agent configuration. + + * Parameter ``compute_stats_by_span_kind`` (a.k.a. environment variable ``DD_APM_COMPUTE_STATS_BY_SPAN_KIND``) is now enabled by default. This means spans with an eligible `span.kind` will have stats computed. If disabled, only top-level and measured spans will have stats computed. If you want to disable this feature, set `compute_stats_by_span_kind` to `false` in your Agent configuration. + + Note: When using ``peer_tags_aggregation`` and ``compute_stats_by_span_kind``, a high cardinality of peer tags or APM resources can contribute to higher CPU and memory consumption. If enabling both causes the Agent to consume too many resources, try disabling `compute_stats_by_span_kind` first. + + It is recommended that you update your tracing libraries according to the instructions `here `_ and set ``DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED`` (or ``dd.trace.remove.integration-service-names.enabled``) to ``true``. +features: + - | + `Inferred Service dependencies `_ are now Generally Available (exiting Beta) and enabled by default. Inferred Services of all kinds now have trace metrics and are available in dependency maps. `apm_config.peer_tags_aggregation` and `apm_config.compute_stats_by_span_kind` both now default to `true` unless explicitly set to `false`. diff --git a/releasenotes/notes/btf-in-flare-92c4735d6507a27a.yaml b/releasenotes/notes/btf-in-flare-92c4735d6507a27a.yaml new file mode 100644 index 0000000000000..9e2f2ba0e3fcf --- /dev/null +++ b/releasenotes/notes/btf-in-flare-92c4735d6507a27a.yaml @@ -0,0 +1,11 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +enhancements: + - | + Added information about where the Agent sourced BTF data for eBPF to the Agent flare. When applicable, this will appear in ``system-probe/ebpf_btf_loader.log``. diff --git a/releasenotes/notes/deprecate-precompiled-ebpf-d887926d6a5fe377.yaml b/releasenotes/notes/deprecate-precompiled-ebpf-d887926d6a5fe377.yaml new file mode 100644 index 0000000000000..0d80e6def4630 --- /dev/null +++ b/releasenotes/notes/deprecate-precompiled-ebpf-d887926d6a5fe377.yaml @@ -0,0 +1,17 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +deprecations: + - | + Prebuilt eBPF for the network tracer system-probe module has been + deprecated in favor of CO-RE and runtime compilation variants on Linux + kernel versions 6+ and RHEL kernel versions 5.14+. To continue to use + the prebuilt eBPF network tracer, set + `system_probe_config.allow_prebuilt_fallback` in the + system-probe config file, or set the environment variable + `DD_ALLOW_PREBUILT_FALLBACK`, to `true` on these platforms. diff --git a/releasenotes/notes/network-path-use-reverse-dns-cache-2dc3dec296cabb01.yaml b/releasenotes/notes/network-path-use-reverse-dns-cache-2dc3dec296cabb01.yaml new file mode 100644 index 0000000000000..e1203564ea1b0 --- /dev/null +++ b/releasenotes/notes/network-path-use-reverse-dns-cache-2dc3dec296cabb01.yaml @@ -0,0 +1,15 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +enhancements: + - | + This change reduces the number of DNS queries made by Network Traffic + based paths in Network Path. + A cache of reverse DNS lookups is used to reduce the number of DNS + queries. Additionally, reverse DNS lookups are now performed only + for private IPs and not for public IPs. diff --git a/releasenotes/notes/oracle-activity-bug-external-client-12d1da009d5bf628.yaml b/releasenotes/notes/oracle-activity-bug-external-client-12d1da009d5bf628.yaml new file mode 100644 index 0000000000000..5db26de192ac1 --- /dev/null +++ b/releasenotes/notes/oracle-activity-bug-external-client-12d1da009d5bf628.yaml @@ -0,0 +1,11 @@ +# Each section from every release note are combined when the +# CHANGELOG.rst is rendered. So the text needs to be worded so that +# it does not depend on any information only available in another +# section. This may mean repeating some details, but each section +# must be readable independently of the other. +# +# Each section note must be formatted as reStructuredText. +--- +fixes: + - | + [oracle] Fix broken activity sampling with an external Oracle client. diff --git a/rtloader/common/builtins/_util.c b/rtloader/common/builtins/_util.c index 7dd43a1e0d099..831dde914d63f 100644 --- a/rtloader/common/builtins/_util.c +++ b/rtloader/common/builtins/_util.c @@ -243,7 +243,7 @@ PyObject *subprocess_output(PyObject *self, PyObject *args, PyObject *kw) PyObject *pyStdout = NULL; if (c_stdout) { - pyStdout = PyStringFromCString(c_stdout); + pyStdout = PyUnicode_FromString(c_stdout); } else { Py_INCREF(Py_None); pyStdout = Py_None; @@ -251,7 +251,7 @@ PyObject *subprocess_output(PyObject *self, PyObject *args, PyObject *kw) PyObject *pyStderr = NULL; if (c_stderr) { - pyStderr = PyStringFromCString(c_stderr); + pyStderr = PyUnicode_FromString(c_stderr); } else { Py_INCREF(Py_None); pyStderr = Py_None; diff --git a/rtloader/common/builtins/_util.h b/rtloader/common/builtins/_util.h index f29712f087057..2f4eef5c2f5cd 100644 --- a/rtloader/common/builtins/_util.h +++ b/rtloader/common/builtins/_util.h @@ -21,14 +21,6 @@ methods. A fresh reference to the module is created here. This function is python3 only. */ -/*! \fn void Py2_init__util() - \brief Initializes the _util builtin python module. - - The _util python builtin is created and registered here as per the module_def - PyMethodDef definition in `_util.c` with the corresponding C-implemented python - methods . A fresh reference to the module is created here. This function is - python2 only. -*/ /*! \fn void _set_get_subprocess_output_cb(cb_get_subprocess_output_t) \brief Sets a callback to be used by rtloader to run subprocess commands and collect their output. diff --git a/rtloader/common/builtins/aggregator.h b/rtloader/common/builtins/aggregator.h index 99b444fd23872..c8958d2874d73 100644 --- a/rtloader/common/builtins/aggregator.h +++ b/rtloader/common/builtins/aggregator.h @@ -22,11 +22,6 @@ This function is only available when python3 is enabled. */ -/*! \fn Py2Init_aggregator() - \brief A function to initialize the python aggregator module in Python2. - - This function is only available when Python2 is enabled. -*/ /*! \fn void _set_submit_metric_cb(cb_submit_metric_t) \brief Sets the submit metric callback to be used by rtloader for metric submission. \param cb A function pointer with cb_submit_metric_t prototype to the callback diff --git a/rtloader/common/builtins/containers.h b/rtloader/common/builtins/containers.h index fadc5442c67ff..53579b6b0441b 100644 --- a/rtloader/common/builtins/containers.h +++ b/rtloader/common/builtins/containers.h @@ -20,14 +20,6 @@ methods. A fresh reference to the module is created here. This function is python3 only. */ -/*! \fn void Py2_init_containers() - \brief Initializes the containers builtin python module. - - The containers python builtin is created and registered here as per the module_def - PyMethodDef definition in `containers.c` with the corresponding C-implemented python - methods. A fresh reference to the module is created here. This function is python2 - only. -*/ /*! \fn void _set_is_excluded_cb(cb_is_excluded_t) \brief Sets a callback to be used by rtloader to determine if a container is excluded from metric collection. diff --git a/rtloader/common/builtins/datadog_agent.c b/rtloader/common/builtins/datadog_agent.c index e20b8f8ff30c8..83c2373fca06f 100644 --- a/rtloader/common/builtins/datadog_agent.c +++ b/rtloader/common/builtins/datadog_agent.c @@ -182,7 +182,7 @@ PyObject *get_version(PyObject *self, PyObject *args) cb_get_version(&v); if (v != NULL) { - PyObject *retval = PyStringFromCString(v); + PyObject *retval = PyUnicode_FromString(v); // v is allocated from CGO and thus requires being freed with the // cgo_free callback for windows safety. cgo_free(v); @@ -329,7 +329,7 @@ PyObject *get_hostname(PyObject *self, PyObject *args) cb_get_hostname(&v); if (v != NULL) { - PyObject *retval = PyStringFromCString(v); + PyObject *retval = PyUnicode_FromString(v); cgo_free(v); return retval; } @@ -359,7 +359,7 @@ PyObject *get_host_tags(PyObject *self, PyObject *args) cb_get_host_tags(&v); if (v != NULL) { - PyObject *retval = PyStringFromCString(v); + PyObject *retval = PyUnicode_FromString(v); cgo_free(v); return retval; } @@ -389,7 +389,7 @@ PyObject *get_clustername(PyObject *self, PyObject *args) cb_get_clustername(&v); if (v != NULL) { - PyObject *retval = PyStringFromCString(v); + PyObject *retval = PyUnicode_FromString(v); cgo_free(v); return retval; } @@ -591,7 +591,7 @@ static PyObject *read_persistent_cache(PyObject *self, PyObject *args) return NULL; } - PyObject *retval = PyStringFromCString(v); + PyObject *retval = PyUnicode_FromString(v); cgo_free(v); return retval; } @@ -804,7 +804,7 @@ static PyObject *obfuscate_sql(PyObject *self, PyObject *args, PyObject *kwargs) // no error message and a null response. this should never happen so the go code is misbehaving PyErr_SetString(PyExc_RuntimeError, "internal error: empty cb_obfuscate_sql response"); } else { - retval = PyStringFromCString(obfQuery); + retval = PyUnicode_FromString(obfQuery); } cgo_free(error_message); @@ -841,7 +841,7 @@ static PyObject *obfuscate_sql_exec_plan(PyObject *self, PyObject *args, PyObjec // no error message and a null response. this should never happen so the go code is misbehaving PyErr_SetString(PyExc_RuntimeError, "internal error: empty cb_obfuscate_sql_exec_plan response"); } else { - retval = PyStringFromCString(obfPlan); + retval = PyUnicode_FromString(obfPlan); } cgo_free(error_message); @@ -916,7 +916,7 @@ static PyObject *obfuscate_mongodb_string(PyObject *self, PyObject *args, PyObje // no error message and a null response. this should never happen so the go code is misbehaving PyErr_SetString(PyExc_RuntimeError, "internal error: empty cb_obfuscate_mongodb_string response"); } else { - retval = PyStringFromCString(obfCmd); + retval = PyUnicode_FromString(obfCmd); } cgo_free(error_message); diff --git a/rtloader/common/builtins/datadog_agent.h b/rtloader/common/builtins/datadog_agent.h index 20a7b97391a6c..ceaba75397ea0 100644 --- a/rtloader/common/builtins/datadog_agent.h +++ b/rtloader/common/builtins/datadog_agent.h @@ -20,14 +20,6 @@ methods . A fresh reference to the module is created here. This function is python3 only. */ -/*! \fn void Py2_init_datadog_agent() - \brief Initializes the datadog_agent builtin python module. - - The datadog_agent python builtin is created and registered here as per the module_def - PyMethodDef definition in `datadog_agent.c` with the corresponding C-implemented python - methods . A fresh reference to the module is created here. This function is - python2 only. -*/ /*! \fn void _set_get_version_cb(cb_get_version_t) \brief Sets a callback to be used by rtloader to collect the agent version. \param object A function pointer with cb_get_version_t prototype to the callback diff --git a/rtloader/common/builtins/kubeutil.h b/rtloader/common/builtins/kubeutil.h index d5eb20ef8b1e1..570ba197c8f83 100644 --- a/rtloader/common/builtins/kubeutil.h +++ b/rtloader/common/builtins/kubeutil.h @@ -19,14 +19,6 @@ module. A fresh reference to the module is created here. This function is python3 only. */ -/*! \fn void Py2_init_kubeutil() - \brief Initializes the kubeutil builtin python module. - - The kubeutil python builtin is created and registered here as per the methods - PyMethodDef array definition. The get_connection_info method is registered with the - module. A fresh reference to the module is created here. This function is python2 - only. -*/ /*! \fn void _set_get_connection_info_cb(cb_get_connection_info_t) \brief Sets a callback to be used by rtloader for kubernetes connection information retrieval. diff --git a/rtloader/common/builtins/tagger.c b/rtloader/common/builtins/tagger.c index 4c35738e7c3a2..83ba34d9f3d80 100644 --- a/rtloader/common/builtins/tagger.c +++ b/rtloader/common/builtins/tagger.c @@ -56,7 +56,7 @@ PyObject *buildTagsList(char **tags) int i; for (i = 0; tags[i]; i++) { - PyObject *pyTag = PyStringFromCString(tags[i]); + PyObject *pyTag = PyUnicode_FromString(tags[i]); cgo_free(tags[i]); // PyList_Append (unlike `PyList_SetItem`) increments the refcount on pyTag diff --git a/rtloader/common/builtins/tagger.h b/rtloader/common/builtins/tagger.h index 7d30c1a219ed7..c4291f3e0a16c 100644 --- a/rtloader/common/builtins/tagger.h +++ b/rtloader/common/builtins/tagger.h @@ -21,14 +21,6 @@ tag and get_tags methods are registered with the module. This function is python3 only. */ -/*! \fn void Py2_init_tagger() - \brief Initializes the tagger builtin python module. - - The tagger python builtin is created and registered here as per the methods - PyMethodDef array definition. A fresh reference to the module is created here. - The tag and get_tags methods are registered with the module.This function is - python2 only. -*/ /*! \fn void _set_tags_cb(cb_tags_t) \brief Sets a callback to be used by rtloader for setting the relevant tags. \param object A function pointer with the cb_tags_t prototype to the diff --git a/rtloader/common/stringutils.h b/rtloader/common/stringutils.h index 1e19c8dd7e297..4a121019aeab5 100644 --- a/rtloader/common/stringutils.h +++ b/rtloader/common/stringutils.h @@ -54,13 +54,6 @@ The returned C-string YAML representation is allocated by the function and should be subsequently freed by the caller. */ -/*! \def PyStringFromCString(x) - \brief A macro that returns a Python string from C string x (char *). - - This macro is implemented differently in the Python2 and Python3 variants. - For Python2 this macro wraps and calls PyString_FromString(x). - For Python3 this macro wraps and calls PyUnicode_FromString(x). -*/ #ifdef __cplusplus extern "C" { @@ -73,8 +66,6 @@ char *as_string(PyObject *); PyObject *from_yaml(const char *); char *as_yaml(PyObject *); -#define PyStringFromCString(x) PyUnicode_FromString(x) - #ifdef __cplusplus } #endif diff --git a/rtloader/rtloader/CMakeLists.txt b/rtloader/rtloader/CMakeLists.txt index a830f18c995c3..1b9fb8b20e8a9 100644 --- a/rtloader/rtloader/CMakeLists.txt +++ b/rtloader/rtloader/CMakeLists.txt @@ -45,7 +45,7 @@ endif() set_target_properties(datadog-agent-rtloader PROPERTIES VERSION ${PROJECT_VERSION} - SOVERSION 1 + SOVERSION 2 PUBLIC_HEADER "../include/datadog_agent_rtloader.h;../include/rtloader_types.h;../common/rtloader_mem.h" ) @@ -78,4 +78,4 @@ ADD_CUSTOM_COMMAND( POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/libdatadog-agent-rtloader.a ${PROJECT_SOURCE_DIR}/libdatadog-agent-rtloader.a ) -endif() \ No newline at end of file +endif() diff --git a/rtloader/three/three.cpp b/rtloader/three/three.cpp index 7765672460f78..1df4c7bca26b8 100644 --- a/rtloader/three/three.cpp +++ b/rtloader/three/three.cpp @@ -855,7 +855,7 @@ void Three::setModuleAttrString(char *module, char *attr, char *value) return; } - PyObject *py_value = PyStringFromCString(value); + PyObject *py_value = PyUnicode_FromString(value); if (PyObject_SetAttrString(py_module, attr, py_value) != 0) { setError("error setting the '" + std::string(module) + "." + std::string(attr) + "' attribute: " + _fetchPythonError()); diff --git a/tasks/build_tags.py b/tasks/build_tags.py index 9b99845114f19..3a72346151582 100644 --- a/tasks/build_tags.py +++ b/tasks/build_tags.py @@ -37,6 +37,7 @@ "oracle", "orchestrator", "otlp", + "pcap", # used by system-probe to compile packet filters using google/gopacket/pcap, which requires cgo to link libpcap "podman", "process", "python", @@ -139,7 +140,7 @@ SERVERLESS_TAGS = {"serverless", "otlp"} # SYSTEM_PROBE_TAGS lists the tags necessary to build system-probe -SYSTEM_PROBE_TAGS = AGENT_TAGS.union({"linux_bpf", "npm", "remotewmonly"}).difference({"python", "systemd"}) +SYSTEM_PROBE_TAGS = AGENT_TAGS.union({"linux_bpf", "npm", "pcap", "remotewmonly"}).difference({"python", "systemd"}) # TRACE_AGENT_TAGS lists the tags that have to be added when the trace-agent TRACE_AGENT_TAGS = {"docker", "containerd", "datadog.no_waf", "kubeapiserver", "kubelet", "otlp", "netcgo", "podman"} @@ -162,7 +163,7 @@ ### Tag exclusion lists # List of tags to always remove when not building on Linux -LINUX_ONLY_TAGS = {"netcgo", "systemd", "jetson", "linux_bpf", "podman", "trivy"} +LINUX_ONLY_TAGS = {"netcgo", "systemd", "jetson", "linux_bpf", "pcap", "podman", "trivy"} # List of tags to always remove when building on Windows WINDOWS_EXCLUDE_TAGS = {"linux_bpf"} @@ -174,7 +175,7 @@ UNIT_TEST_TAGS = {"test"} # List of tags to always remove when running unit tests -UNIT_TEST_EXCLUDE_TAGS = {"datadog.no_waf"} +UNIT_TEST_EXCLUDE_TAGS = {"datadog.no_waf", "pcap"} # Build type: maps flavor to build tags map build_tags = { diff --git a/tasks/buildimages.py b/tasks/buildimages.py index 999a5006ea849..2f7d228d4d070 100644 --- a/tasks/buildimages.py +++ b/tasks/buildimages.py @@ -12,17 +12,29 @@ @task( help={ - "image_tag": "tag from build_image with format v_", - "test_version": "Is a test image or not", + "tag": "tag from build_image with format v_", + "images": "The image(s) to update, comma separated. If empty, updates all images. It support incomplete pattern, e.g. 'deb,rpm' will update all deb and rpm images. deb_x64 will update only one image. Use the --list-images flag to list all available images", + "test": "Is a test image or not", + "list_images": "List all available images", } ) -def update(_: Context, image_tag: str, test_version: bool = True): +def update(_: Context, tag: str = "", images: str = "", test: bool = True, list_images: bool = False): """ - Update local files to run with new image_tag from agent-buildimages - Use --no-test-version to commit without the _test_only suffixes + Update local files to use a new version of dedicated images from agent-buildimages + Use --no-test to commit without the _test_only suffixes + Use --list-images to list all available images """ - update_gitlab_config(".gitlab-ci.yml", image_tag, test_version=test_version) - update_circleci_config(".circleci/config.yml", image_tag, test_version=test_version) + if list_images: + print("List of available images:") + modified = update_gitlab_config(".gitlab-ci.yml", "", update=False) + modified.append("CIRCLECI_RUNNER") + else: + print("Updating images:") + modified = update_gitlab_config(".gitlab-ci.yml", tag, images, test=test) + if images == "" or "circle" in images: + update_circleci_config(".circleci/config.yml", tag, test=test) + modified.append("CIRCLECI_RUNNER") + print(f" {', '.join(modified)}") @task(help={"commit_sha": "commit sha from the test-infra-definitions repository"}) @@ -44,7 +56,7 @@ def update_test_infra_definitions(ctx: Context, commit_sha: str, go_mod_only: bo "new_build_image_tag": "The new build image tag", "old_go_version": "The old Go version", "new_go_version": "The new Go version", - "test_version": "Flag to indicate if this is a test version", + "test": "Flag to indicate if this is a test version", }, autoprint=True, ) @@ -54,13 +66,13 @@ def generate_pr_body( new_build_image_tag: str, old_go_version: str, new_go_version: str, - test_version: bool = False, + test: bool = False, ): """ Generate the PR body used for buildimages-update Github workflow """ buildimages_workflow_url = "https://github.com/DataDog/datadog-agent/actions/workflows/buildimages-update.yml" - test_version_str = "(test version)" if test_version else "" + test_version_str = "(test version)" if test else "" compare_url = f"https://github.com/DataDog/datadog-agent-buildimages/compare/{old_build_image_tag.split('-')[1]}...{new_build_image_tag.split('-')[1]}" pr_body = f"""This PR was automatically created by the [Update buildimages Github Workflow]({buildimages_workflow_url}). @@ -82,19 +94,37 @@ def generate_pr_body( @task( help={ "file_path": "path of the Gitlab configuration YAML file", + "image_type": "The type of image to get the tag for (e.g. deb_x64, rpm_armhf, etc). You can use any value defined by or CI_IMAGE_ in the gitlab-ci configuration variables. Get the DATADOG_AGENT_BUILDIMAGES version if image_type not specified", }, autoprint=True, ) -def get_tag(_, file_path=".gitlab-ci.yml"): +def get_tag(_, file_path=".gitlab-ci.yml", image_type=None): """ Print the current image tag of the given Gitlab configuration file (default: ".gitlab-ci.yml") """ yaml.SafeLoader.add_constructor(ReferenceTag.yaml_tag, ReferenceTag.from_yaml) with open(file_path) as gl: gitlab_ci = yaml.safe_load(gl) - if "variables" not in gitlab_ci or "DATADOG_AGENT_BUILDIMAGES" not in gitlab_ci["variables"]: + if "variables" not in gitlab_ci: raise Exit( - color_message(f"Impossible to find the version of image in {file_path} configuration file", "red"), + f'[{color_message("ERROR", "red")}] - No variables in gitlab configuration file {file_path}', + code=1, + ) + + if image_type is None: + return gitlab_ci["variables"].get( + "DATADOG_AGENT_BUILDIMAGES", + f'{color_message("Not found", "red")}: DATADOG_AGENT_BUILDIMAGES is not defined in the configuration', + ) + else: + available_images = set() + for key in gitlab_ci["variables"].keys(): + if key.startswith("CI_IMAGE"): + image = key.removeprefix("CI_IMAGE_").removesuffix("_SUFFIX").casefold() + available_images.add(image) + if image_type.casefold() == image: + return gitlab_ci["variables"][key] + raise Exit( + f'{color_message("ERROR", "red")}: {image_type} is not defined in the configuration. Available images: {", ".join(available_images)}', code=1, ) - return gitlab_ci["variables"]["DATADOG_AGENT_BUILDIMAGES"] diff --git a/tasks/github_tasks.py b/tasks/github_tasks.py index ffde98330edf6..97ef341cf5a12 100644 --- a/tasks/github_tasks.py +++ b/tasks/github_tasks.py @@ -409,3 +409,15 @@ def pr_commenter( if verbose: print(f"{action} comment on PR #{pr.number} - {pr.title}") + + +@task +def assign_codereview_label(_, pr_id=-1): + """ + Assigns a code review complexity label based on PR attributes (files changed, additions, deletions, comments) + """ + from tasks.libs.ciproviders.github_api import GithubAPI + + gh = GithubAPI('DataDog/datadog-agent') + complexity = gh.get_codereview_complexity(pr_id) + gh.update_review_complexity_labels(pr_id, complexity) diff --git a/tasks/kernel_matrix_testing/platforms.py b/tasks/kernel_matrix_testing/platforms.py index 2cadc07a997f4..4e156ca706b73 100644 --- a/tasks/kernel_matrix_testing/platforms.py +++ b/tasks/kernel_matrix_testing/platforms.py @@ -9,6 +9,7 @@ from tasks.kernel_matrix_testing.tool import Exit from tasks.kernel_matrix_testing.vars import KMT_SUPPORTED_ARCHS from tasks.libs.ciproviders.gitlab_api import ReferenceTag +from tasks.libs.types.arch import Arch if TYPE_CHECKING: from tasks.kernel_matrix_testing.types import ( @@ -26,7 +27,15 @@ def get_platforms(): return cast("Platforms", json.load(f)) -def filter_by_ci_component(platforms: Platforms, component: Component) -> Platforms: +class KMTTestJob: + def __init__(self, name: str, arch: KMTArchName, test_set: str, kernels: set[str]): + self.name = name + self.arch = arch + self.test_set = test_set + self.kernels = kernels + + +def filter_by_ci_component(platforms: Platforms, component: Component) -> dict[str, Platforms]: job_arch_mapping: dict[KMTArchName, str] = { "x86_64": "x64", "arm64": "arm64", @@ -35,7 +44,6 @@ def filter_by_ci_component(platforms: Platforms, component: Component) -> Platfo "system-probe": "sysprobe", "security-agent": "secagent", } - new_platforms = platforms.copy() target_file = ( Path(__file__).parent.parent.parent / ".gitlab" / "kernel_matrix_testing" / f"{component.replace('-', '_')}.yml" @@ -44,22 +52,44 @@ def filter_by_ci_component(platforms: Platforms, component: Component) -> Platfo with open(target_file) as f: ci_config = yaml.safe_load(f) + job_prefixes = [] for arch in KMT_SUPPORTED_ARCHS: - job_name = f"kmt_run_{job_component_mapping[component]}_tests_{job_arch_mapping[arch]}" - if job_name not in ci_config: - raise Exit(f"Job {job_name} not found in {target_file}, cannot extract used platforms") + job_prefixes.append(f"kmt_run_{job_component_mapping[component]}_tests_{job_arch_mapping[arch]}") + + test_jobs = [] + for job in ci_config: + for prefix in job_prefixes: + if not job.startswith(prefix): + continue + + arch = ci_config[job]["variables"]["ARCH"] + sets = ci_config[job]["parallel"]["matrix"][0]["TEST_SET"] + kernels = ci_config[job]["parallel"]["matrix"][0]["TAG"] + + test_jobs.append(KMTTestJob(job, Arch.from_str(arch).kmt_arch, sets, set(kernels))) + + new_platforms_by_set = {} + for job in test_jobs: + for s in job.test_set: + if s not in new_platforms_by_set: + new_platforms_by_set[s] = platforms.copy() + + # we need to index `new_platforms_by_set` by a literal to + # avoid mypy errors, which is why assign arch to `cur_arch` + cur_arch = None + for arch in KMT_SUPPORTED_ARCHS: + if job.arch == arch: + cur_arch = arch - try: - kernels = set(ci_config[job_name]["parallel"]["matrix"][0]["TAG"]) - except (KeyError, IndexError) as e: - raise Exit( - f"Cannot find list of kernels (parallel.matrix[0].TAG) in {job_name} job in {target_file}" - ) from e + if cur_arch is None: + raise Exit(f"Unsupported architecture {job.arch} detected for job {job.name}") - new_platforms[arch] = {k: v for k, v in new_platforms[arch].items() if k in kernels} + new_platforms_by_set[s][cur_arch] = { + k: v for k, v in new_platforms_by_set[s][cur_arch].items() if k in job.kernels + } - missing_kernels = kernels - set(new_platforms[arch].keys()) - if missing_kernels: - raise Exit(f"Kernels {missing_kernels} not found in {platforms_file} for {arch}") + missing_kernels = job.kernels - set(new_platforms_by_set[s][cur_arch].keys()) + if missing_kernels: + raise Exit(f"Kernels {missing_kernels} not found in {platforms_file} for {job.arch}") - return new_platforms + return new_platforms_by_set diff --git a/tasks/kernel_matrix_testing/vmconfig.py b/tasks/kernel_matrix_testing/vmconfig.py index 7590a8513a31d..9b6d4c4b865f7 100644 --- a/tasks/kernel_matrix_testing/vmconfig.py +++ b/tasks/kernel_matrix_testing/vmconfig.py @@ -507,11 +507,12 @@ def __repr__(self): class VMSet: - def __init__(self, arch: KMTArchNameOrLocal, recipe: Recipe, tags: set[str]): + def __init__(self, arch: KMTArchNameOrLocal, recipe: Recipe, testset: str, tags: set[str]): self.arch: KMTArchNameOrLocal = arch self.recipe: Recipe = recipe self.tags: set[str] = tags self.vms: list[VM] = [] + self.testset: str = testset def __eq__(self, other: Any): if not isinstance(other, VMSet): @@ -531,7 +532,7 @@ def __repr__(self): vm_str.append(vm.version) return f" tags={'-'.join(self.tags)} arch={self.arch} vms={','.join(vm_str)}" - def add_vm_if_belongs(self, recipe: Recipe, version: str, arch: KMTArchNameOrLocal): + def add_vm_if_belongs(self, recipe: Recipe, version: str, arch: KMTArchNameOrLocal, testset: str): if recipe == "custom": expected_tag = custom_version_prefix(version) found = False @@ -542,7 +543,7 @@ def add_vm_if_belongs(self, recipe: Recipe, version: str, arch: KMTArchNameOrLoc if not found: return - if self.recipe == recipe and self.arch == arch: + if self.recipe == recipe and self.arch == arch and self.testset == testset: self.vms.append(VM(version)) @@ -550,39 +551,32 @@ def custom_version_prefix(version: str) -> str: return "lte_414" if lte_414(version) else "gt_414" -def build_vmsets(normalized_vm_defs: list[VMDef], sets: list[str]) -> set[VMSet]: +def build_vmsets(normalized_vm_defs_by_set: dict[str, list[VMDef]]) -> set[VMSet]: vmsets: set[VMSet] = set() - for recipe, version, arch in normalized_vm_defs: - if recipe == "custom": - sets.append(custom_version_prefix(version)) - - # duplicate vm if multiple sets provided by user - for s in sets: - vmsets.add(VMSet(arch, recipe, {vmset_name(arch, recipe), s})) - - if len(sets) == 0: - vmsets.add(VMSet(arch, recipe, {vmset_name(arch, recipe)})) + for testset in normalized_vm_defs_by_set: + for recipe, _, arch in normalized_vm_defs_by_set[testset]: + vmsets.add(VMSet(arch, recipe, testset, {vmset_name(arch, recipe), testset})) # map vms to vmsets - for recipe, version, arch in normalized_vm_defs: - for vmset in vmsets: - vmset.add_vm_if_belongs(recipe, version, arch) + for testset in normalized_vm_defs_by_set: + for recipe, version, arch in normalized_vm_defs_by_set[testset]: + for vmset in vmsets: + vmset.add_vm_if_belongs(recipe, version, arch, testset) return vmsets def generate_vmconfig( vm_config: VMConfig, - normalized_vm_defs: list[VMDef], + normalized_vm_defs_by_set: list[VMDef], vcpu: list[int], memory: list[int], - sets: list[str], ci: bool, template: str, ) -> VMConfig: platforms = get_platforms() vmconfig_template = get_vmconfig_template(template) - vmsets = build_vmsets(normalized_vm_defs, sets) + vmsets = build_vmsets(normalized_vm_defs_by_set) # add new vmsets to new vm_config for vmset in vmsets: @@ -623,13 +617,22 @@ def ls_to_int(ls: list[Any]) -> list[int]: return int_ls -def build_normalized_vm_def_set(vms: str) -> list[VMDef]: +def build_normalized_vm_def_by_set(vms: str, sets: list[str]) -> dict[str, list[VMDef]]: vm_types = vms.split(',') if len(vm_types) == 0: raise Exit("No VMs to boot provided") possible = list_possible() - return [normalize_vm_def(possible, vm) for vm in vm_types] + normalized = [normalize_vm_def(possible, vm) for vm in vm_types] + + if len(sets) == 0: + sets = ["default"] + + normalized_by_set = {} + for s in sets: + normalized_by_set[s] = normalized + + return normalized_by_set def gen_config_for_stack( @@ -670,7 +673,7 @@ def gen_config_for_stack( orig_vm_config = f.read() vm_config = json.loads(orig_vm_config) - vm_config = generate_vmconfig(vm_config, build_normalized_vm_def_set(vms), vcpu, memory, sets, ci, template) + vm_config = generate_vmconfig(vm_config, build_normalized_vm_def_by_set(vms, sets), vcpu, memory, ci, template) vm_config_str = json.dumps(vm_config, indent=4) tmpfile = "/tmp/vm.json" @@ -705,15 +708,19 @@ def gen_config_for_stack( info(f"[+] vmconfig @ {vmconfig_file}") -def list_all_distro_normalized_vms(archs: list[KMTArchName], component: Component | None = None): +def list_all_distro_normalized_vms_by_test_set(archs: list[KMTArchName], component: Component | None = None): platforms = get_platforms() if component is not None: - platforms = filter_by_ci_component(platforms, component) + platforms_by_test_set = filter_by_ci_component(platforms, component) + + vms = {} + for testset in platforms_by_test_set: + for arch in archs: + for distro in platforms_by_test_set[testset][arch]: + if testset not in vms: + vms[testset] = [] - vms: list[VMDef] = [] - for arch in archs: - for distro in platforms[arch]: - vms.append(("distro", distro, arch)) + vms[testset].append(("distro", distro, arch)) return vms @@ -750,10 +757,16 @@ def gen_config( if arch != "": arch_ls = [Arch.from_str(arch).kmt_arch] - vms_to_generate = list_all_distro_normalized_vms(arch_ls, template) + vms_to_generate = list_all_distro_normalized_vms_by_test_set(arch_ls, template) vm_config = generate_vmconfig( - {"vmsets": []}, vms_to_generate, ls_to_int(vcpu_ls), ls_to_int(memory_ls), set_ls, ci, template + {"vmsets": []}, vms_to_generate, ls_to_int(vcpu_ls), ls_to_int(memory_ls), ci, template ) + print("Generated VMSets with tags:") + for vmset in vm_config["vmsets"]: + tags = vmset["tags"] + tags.sort() + print(f"- {', '.join(tags)}") + with open(output_file, "w") as f: f.write(json.dumps(vm_config, indent=4)) diff --git a/tasks/kmt.py b/tasks/kmt.py index 198dba2c3dcce..98f5545225ac1 100644 --- a/tasks/kmt.py +++ b/tasks/kmt.py @@ -488,7 +488,7 @@ def start_compiler(ctx: Context): def filter_target_domains(vms: str, infra: dict[KMTArchNameOrLocal, HostInstance], arch: Arch | None = None): - vmsets = vmconfig.build_vmsets(vmconfig.build_normalized_vm_def_set(vms), []) + vmsets = vmconfig.build_vmsets(vmconfig.build_normalized_vm_def_by_set(vms, [])) domains: list[LibvirtDomain] = [] for vmset in vmsets: if arch is not None and Arch.from_str(vmset.arch) != arch: @@ -880,9 +880,9 @@ def build_run_config(run: str | None, packages: list[str]): if p[:2] == "./": p = p[2:] if run is not None: - c["filters"][p] = {"run-only": [run]} + c["filters"] = {p: {"run-only": [run]}} else: - c["filters"][p] = {"exclude": False} + c["filters"] = {p: {"exclude": False}} return c @@ -1063,10 +1063,15 @@ def kmt_sysprobe_prepare( for cbin in TEST_HELPER_CBINS: source = Path(pkg) / "testdata" / f"{cbin}.c" if source.is_file(): - binary_path = os.path.join(target_path, "testdata", cbin) + testdata_folder = os.path.join(target_path, "testdata") + binary_path = os.path.join(testdata_folder, cbin) nw.build( inputs=[os.fspath(source)], outputs=[binary_path], + # Ensure that the testdata folder is created before the + # binary, to avoid races between this command and the + # copy command + implicit=[testdata_folder], rule="cbin", variables={ "cc": "clang", diff --git a/tasks/libs/ciproviders/circleci.py b/tasks/libs/ciproviders/circleci.py index 68d996830e359..ca35832e90d02 100644 --- a/tasks/libs/ciproviders/circleci.py +++ b/tasks/libs/ciproviders/circleci.py @@ -1,7 +1,7 @@ import re -def update_circleci_config(file_path, image_tag, test_version): +def update_circleci_config(file_path, image_tag, test): """ Override variables in .gitlab-ci.yml file """ @@ -11,6 +11,6 @@ def update_circleci_config(file_path, image_tag, test_version): match = re.search(rf"({image_name}(_test_only)?):([a-zA-Z0-9_-]+)\n", circle_ci) if not match: raise RuntimeError(f"Impossible to find the version of image {image_name} in circleci configuration file") - image = f"{image_name}_test_only" if test_version else image_name + image = f"{image_name}_test_only" if test else image_name with open(file_path, "w") as circle: circle.write(circle_ci.replace(f"{match.group(0)}", f"{image}:{image_tag}\n")) diff --git a/tasks/libs/ciproviders/github_api.py b/tasks/libs/ciproviders/github_api.py index 17860e68f08c6..1a8689ace7e6a 100644 --- a/tasks/libs/ciproviders/github_api.py +++ b/tasks/libs/ciproviders/github_api.py @@ -271,6 +271,22 @@ def get_pr_labels(self, pr_id: int) -> list[str]: return [label.name for label in pr.get_labels()] + def update_review_complexity_labels(self, pr_id: int, new_label: str) -> None: + """ + Updates the review complexity label of a pull request + """ + pr = self.get_pr(pr_id) + already_there = False + for label in pr.get_labels(): + if label.name.endswith(" review"): + if label.name == new_label: + already_there = True + else: + pr.remove_from_labels(label.name) + + if not already_there: + pr.add_to_labels(new_label) + def get_pr_files(self, pr_id: int) -> list[str]: """ Returns the files involved in the PR @@ -378,6 +394,33 @@ def create_release(self, tag, message, draft=True): draft=draft, ) + def get_codereview_complexity(self, pr_id: int) -> str: + """ + Get the complexity of the code review for a given PR, taking into account the number of files, lines and comments. + """ + pr = self._repository.get_pull(pr_id) + # Criteria are defined with the average of PR attributes (files, lines, comments) so that: + # - easy PRs are merged in less than 1 day + # - hard PRs are merged in more than 1 week + # More details about criteria definition: https://datadoghq.atlassian.net/wiki/spaces/agent/pages/4271079846/Code+Review+Experience+Improvement#Complexity-label + criteria = { + 'easy': {'files': 4, 'lines': 150, 'comments': 1}, + 'hard': {'files': 12, 'lines': 650, 'comments': 9}, + } + if ( + pr.changed_files < criteria['easy']['files'] + and pr.additions + pr.deletions < criteria['easy']['lines'] + and pr.review_comments < criteria['easy']['comments'] + ): + return 'short review' + elif ( + pr.changed_files > criteria['hard']['files'] + or pr.additions + pr.deletions > criteria['hard']['lines'] + or pr.review_comments > criteria['hard']['comments'] + ): + return 'long review' + return 'medium review' + def get_github_teams(users): for user in users: diff --git a/tasks/libs/ciproviders/gitlab_api.py b/tasks/libs/ciproviders/gitlab_api.py index b53c839d5c6d7..212e2ce38f142 100644 --- a/tasks/libs/ciproviders/gitlab_api.py +++ b/tasks/libs/ciproviders/gitlab_api.py @@ -1267,35 +1267,59 @@ def update_test_infra_def(file_path, image_tag): gl.write(line) -def update_gitlab_config(file_path, image_tag, test_version): +def update_gitlab_config(file_path, tag, images="", test=True, update=True): """ - Override variables in .gitlab-ci.yml file + Override variables in .gitlab-ci.yml file. """ with open(file_path) as gl: file_content = gl.readlines() yaml.SafeLoader.add_constructor(ReferenceTag.yaml_tag, ReferenceTag.from_yaml) gitlab_ci = yaml.safe_load("".join(file_content)) - # TEST_INFRA_DEFINITION_BUILDIMAGE label format differs from other buildimages - suffixes = [ - name - for name in gitlab_ci["variables"] - if name.endswith("SUFFIX") and not name.startswith("TEST_INFRA_DEFINITION") - ] - images = [name.replace("_SUFFIX", "") for name in suffixes] - with open(file_path, "w") as gl: - for line in file_content: - if any(re.search(rf"{suffix}:", line) for suffix in suffixes): - if test_version: - gl.write(line.replace('""', '"_test_only"')) - else: - gl.write(line.replace('"_test_only"', '""')) - elif any(re.search(rf"{image}:", line) for image in images): - current_version = re.search(r"v\d+-\w+", line) - if current_version: - gl.write(line.replace(current_version.group(0), image_tag)) + variables = gitlab_ci['variables'] + # Select the buildimages prefixed with CI_IMAGE matchins input images list + buildimages prefixed with DATADOG_AGENT_ + images_to_update = list(find_buildimages(variables, images, "CI_IMAGE_")) + list(find_buildimages(variables)) + if update: + output = update_image_tag(file_content, tag, images_to_update, test=test) + with open(file_path, "w") as gl: + gl.writelines(output) + return images_to_update + + +def find_buildimages(variables, images="", prefix="DATADOG_AGENT_"): + """ + Select the buildimages variables to update. + With default values, the former DATADOG_AGENT_ variables are updated. + """ + suffix = "_SUFFIX" + for variable in variables: + if ( + variable.startswith(prefix) + and variable.endswith(suffix) + and any(image in variable.casefold() for image in images.casefold().split(",")) + ): + yield variable.removesuffix(suffix) + + +def update_image_tag(lines, tag, variables, test=True): + """ + Update the variables in the .gitlab-ci.yml file. + We update the file content (instead of the yaml.load) to keep the original order/formatting. + """ + output = [] + tag_pattern = re.compile(r"v\d+-\w+") + for line in lines: + if any(variable in line for variable in variables): + if "SUFFIX" in line: + if test: + output.append(line.replace('""', '"_test_only"')) else: - raise RuntimeError( - f"Unable to find a version matching the v- pattern in line {line}" - ) + output.append(line.replace('"_test_only"', '""')) else: - gl.write(line) + is_tag = tag_pattern.search(line) + if is_tag: + output.append(line.replace(is_tag.group(), tag)) + else: + output.append(line) + else: + output.append(line) + return output diff --git a/tasks/libs/common/utils.py b/tasks/libs/common/utils.py index 76fb453ce9c37..051ddb974496a 100644 --- a/tasks/libs/common/utils.py +++ b/tasks/libs/common/utils.py @@ -162,10 +162,6 @@ def get_rtloader_paths(embedded_path=None, rtloader_root=None): return rtloader_lib, rtloader_headers, rtloader_common_headers -def get_win_py_runtime_var(): - return "PY3_RUNTIME" - - def get_embedded_path(ctx): base = os.path.dirname(os.path.abspath(__file__)) task_repo_root = os.path.abspath(os.path.join(base, "..", "..")) diff --git a/tasks/libs/pipeline/github_jira_map.yaml b/tasks/libs/pipeline/github_jira_map.yaml index e49a8fc64f6c9..ac4e37e186a1e 100644 --- a/tasks/libs/pipeline/github_jira_map.yaml +++ b/tasks/libs/pipeline/github_jira_map.yaml @@ -10,6 +10,8 @@ '@datadog/agent-security': CWS '@datadog/agent-apm': APMSP '@datadog/network-device-monitoring': NDMII +'@datadog/ndm-core': NDMII +'@datadog/ndm-integrations': NDINT '@datadog/processes': PROCS '@datadog/agent-metrics-logs': AMLII '@datadog/agent-shared-components': ASCII diff --git a/tasks/libs/pipeline/github_slack_map.yaml b/tasks/libs/pipeline/github_slack_map.yaml index 6d1e115d9798a..4e83262868150 100644 --- a/tasks/libs/pipeline/github_slack_map.yaml +++ b/tasks/libs/pipeline/github_slack_map.yaml @@ -12,6 +12,8 @@ '@datadog/agent-security': '#security-and-compliance-agent-ops' '@datadog/agent-apm': '#apm-agent' '@datadog/network-device-monitoring': '#network-device-monitoring' +'@datadog/ndm-core': '#ndm-core' +'@datadog/ndm-integrations': '#ndm-integrations' '@datadog/processes': '#process-agent-ops' '@datadog/agent-metrics-logs': '#agent-metrics-logs' '@datadog/agent-processing-and-routing': '#agent-processing-and-routing' diff --git a/tasks/new_e2e_tests.py b/tasks/new_e2e_tests.py index 40abe8121b4be..338c816c28ab1 100644 --- a/tasks/new_e2e_tests.py +++ b/tasks/new_e2e_tests.py @@ -24,7 +24,7 @@ from tasks.libs.common.go import download_go_dependencies from tasks.libs.common.utils import REPO_PATH, color_message, running_in_ci from tasks.modules import DEFAULT_MODULES -from tools.e2e_stacks import destroy_remote_stack +from tasks.tools.e2e_stacks import destroy_remote_stack @task( diff --git a/tasks/security_agent.py b/tasks/security_agent.py index 9990ca2a5091f..a2c6c6473d361 100644 --- a/tasks/security_agent.py +++ b/tasks/security_agent.py @@ -25,7 +25,6 @@ environ, get_build_flags, get_go_version, - get_gopath, get_version, ) from tasks.libs.types.arch import ARCH_AMD64, Arch @@ -33,8 +32,10 @@ from tasks.system_probe import ( CURRENT_ARCH, build_cws_object_files, + build_libpcap, check_for_ninja, copy_ebpf_and_related_files, + get_libpcap_cgo_flags, ninja_define_ebpf_compiler, ninja_define_exe_compiler, ) @@ -45,8 +46,6 @@ BIN_DIR = os.path.join(".", "bin") BIN_PATH = os.path.join(BIN_DIR, "security-agent", bin_name("security-agent")) CI_PROJECT_DIR = os.environ.get("CI_PROJECT_DIR", ".") -KITCHEN_DIR = os.getenv('DD_AGENT_TESTING_DIR') or os.path.normpath(os.path.join(os.getcwd(), "test", "kitchen")) -KITCHEN_ARTIFACT_DIR = os.path.join(KITCHEN_DIR, "site-cookbooks", "dd-security-agent-check", "files") STRESS_TEST_SUITE = "stresssuite" @@ -234,7 +233,7 @@ def build_go_syscall_tester(ctx, build_dir): syscall_tester_go_dir = os.path.join(".", "pkg", "security", "tests", "syscall_tester", "go") syscall_tester_exe_file = os.path.join(build_dir, "syscall_go_tester") ctx.run( - f"go build -o {syscall_tester_exe_file} -tags syscalltesters,osusergo,netgo -ldflags=\"-extldflags=-static\" {syscall_tester_go_dir}/syscall_go_tester.go" + f"go build -o {syscall_tester_exe_file} -tags syscalltesters,osusergo,netgo -ldflags=\"-extldflags=-static\" {syscall_tester_go_dir}/syscall_go_tester.go", ) return syscall_tester_exe_file @@ -328,7 +327,9 @@ def create_dir_if_needed(dir): @task -def build_embed_syscall_tester(ctx, arch: str | Arch = CURRENT_ARCH, static=True, compiler="clang"): +def build_embed_syscall_tester( + ctx, arch: str | Arch = CURRENT_ARCH, static=True, compiler="clang", ebpf_compiler="clang" +): arch = Arch.from_str(arch) check_for_ninja(ctx) build_dir = os.path.join("pkg", "security", "tests", "syscall_tester", "bin") @@ -338,7 +339,7 @@ def build_embed_syscall_tester(ctx, arch: str | Arch = CURRENT_ARCH, static=True nf_path = os.path.join(ctx.cwd, 'syscall-tester.ninja') with open(nf_path, 'w') as ninja_file: nw = NinjaWriter(ninja_file, width=120) - ninja_define_ebpf_compiler(nw, arch=arch) + ninja_define_ebpf_compiler(nw, arch=arch, compiler=ebpf_compiler) ninja_define_exe_compiler(nw, compiler=compiler) ninja_syscall_tester(nw, build_dir, static=static, compiler=compiler) @@ -380,7 +381,7 @@ def build_functional_tests( bundle_ebpf=bundle_ebpf, ebpf_compiler=ebpf_compiler, ) - build_embed_syscall_tester(ctx, compiler=syscall_tester_compiler) + build_embed_syscall_tester(ctx, compiler=syscall_tester_compiler, ebpf_compiler=ebpf_compiler) arch = Arch.from_str(arch) ldflags, gcflags, env = get_build_flags(ctx, major_version=major_version, static=static, arch=arch) @@ -397,6 +398,16 @@ def build_functional_tests( if bundle_ebpf: build_tags.append("ebpf_bindata") + build_tags.append("pcap") + build_libpcap(ctx) + cgo_flags = get_libpcap_cgo_flags(ctx) + # append libpcap cgo-related environment variables to any existing ones + for k, v in cgo_flags.items(): + if k in env: + env[k] += f" {v}" + else: + env[k] = v + if static: build_tags.extend(["osusergo", "netgo"]) @@ -541,32 +552,6 @@ def ebpfless_functional_tests( ) -@task -def kitchen_functional_tests( - ctx, - verbose=False, - major_version='7', - build_tests=False, - testflags='', -): - if build_tests: - functional_tests( - ctx, - verbose=verbose, - major_version=major_version, - output="test/kitchen/site-cookbooks/dd-security-agent-check/files/testsuite", - testflags=testflags, - ) - - kitchen_dir = os.path.join("test", "kitchen") - shutil.copy( - os.path.join(kitchen_dir, "kitchen-vagrant-security-agent.yml"), os.path.join(kitchen_dir, "kitchen.yml") - ) - - with ctx.cd(kitchen_dir): - ctx.run("kitchen test") - - @task def docker_functional_tests( ctx, @@ -801,19 +786,18 @@ def go_generate_check(ctx): raise Exit(code=1) +E2E_ARTIFACT_DIR = os.path.join(CI_PROJECT_DIR, "test", "new-e2e", "tests", "security-agent-functional", "artifacts") + + @task -def kitchen_prepare(ctx, skip_linters=False): +def e2e_prepare_win(ctx): """ - Compile test suite for kitchen + Compile test suite for CWS windows new-e2e tests """ - out_binary = "testsuite" - race = True - if is_windows: - out_binary = "testsuite.exe" - race = False + out_binary = "testsuite.exe" - testsuite_out_dir = os.path.join(KITCHEN_ARTIFACT_DIR, "tests") + testsuite_out_dir = E2E_ARTIFACT_DIR # Clean up previous build if os.path.exists(testsuite_out_dir): shutil.rmtree(testsuite_out_dir) @@ -822,48 +806,24 @@ def kitchen_prepare(ctx, skip_linters=False): build_functional_tests( ctx, bundle_ebpf=False, - race=race, + race=False, debug=True, output=testsuite_out_path, - skip_linters=skip_linters, + skip_linters=True, ) - if is_windows: - # build the ETW tests binary also - testsuite_out_path = os.path.join(KITCHEN_ARTIFACT_DIR, "tests", "etw", out_binary) - srcpath = 'pkg/security/probe' - build_functional_tests( - ctx, - output=testsuite_out_path, - srcpath=srcpath, - bundle_ebpf=False, - race=race, - debug=True, - skip_linters=skip_linters, - ) - - return - - stresssuite_out_path = os.path.join(KITCHEN_ARTIFACT_DIR, "tests", STRESS_TEST_SUITE) - build_stress_tests(ctx, output=stresssuite_out_path, skip_linters=skip_linters) - - # Copy clang binaries - for bin in ["clang-bpf", "llc-bpf"]: - ctx.run(f"cp /opt/datadog-agent/embedded/bin/{bin} {KITCHEN_ARTIFACT_DIR}/{bin}") - - # Copy gotestsum binary - gopath = get_gopath(ctx) - ctx.run(f"cp {gopath}/bin/gotestsum {KITCHEN_ARTIFACT_DIR}/") - # Build test2json binary - ctx.run(f"go build -o {KITCHEN_ARTIFACT_DIR}/test2json -ldflags=\"-s -w\" cmd/test2json", env={"CGO_ENABLED": "0"}) - - ebpf_bytecode_dir = os.path.join(KITCHEN_ARTIFACT_DIR, "ebpf_bytecode") - ebpf_runtime_dir = os.path.join(ebpf_bytecode_dir, "runtime") - bytecode_build_dir = os.path.join(CI_PROJECT_DIR, "pkg", "ebpf", "bytecode", "build") - - ctx.run(f"mkdir -p {ebpf_runtime_dir}") - ctx.run(f"cp {bytecode_build_dir}/runtime-security* {ebpf_bytecode_dir}") - ctx.run(f"cp {bytecode_build_dir}/runtime/runtime-security* {ebpf_runtime_dir}") + # build the ETW tests binary also + testsuite_out_path = os.path.join(E2E_ARTIFACT_DIR, "etw", out_binary) + srcpath = 'pkg/security/probe' + build_functional_tests( + ctx, + output=testsuite_out_path, + srcpath=srcpath, + bundle_ebpf=False, + race=False, + debug=True, + skip_linters=True, + ) @task diff --git a/tasks/system_probe.py b/tasks/system_probe.py index 2f1de1a07a1bb..f17419c7491d8 100644 --- a/tasks/system_probe.py +++ b/tasks/system_probe.py @@ -32,6 +32,7 @@ environ, get_build_flags, get_common_test_args, + get_embedded_path, get_gobin, parse_kernel_version, ) @@ -56,6 +57,8 @@ "./pkg/process/monitor/...", "./pkg/dynamicinstrumentation/...", "./pkg/gpu/...", + "./cmd/system-probe/config/...", + "./comp/metadata/inventoryagent/...", ] TEST_PACKAGES = " ".join(TEST_PACKAGES_LIST) # change `timeouts` in `test/new-e2e/system-probe/test-runner/main.go` if you change them here @@ -84,6 +87,9 @@ CURRENT_ARCH = arch_mapping.get(platform.machine(), "x64") CLANG_VERSION_RUNTIME = "12.0.1" CLANG_VERSION_SYSTEM_PREFIX = "12.0" +# system-probe doesn't depend on any particular version of libpcap so use the latest one (as of 2024-10-28) +# this version should be kept in sync with the one in the agent omnibus build +LIBPCAP_VERSION = "1.10.5" TEST_HELPER_CBINS = ["cudasample"] @@ -605,6 +611,64 @@ def ninja_generate( ninja_cgo_type_files(nw) +@task +def build_libpcap(ctx): + """Download and build libpcap as a static library in the agent dev directory. + The library is not rebuilt if it already exists. + """ + embedded_path = get_embedded_path(ctx) + assert embedded_path, "Failed to find embedded path" + target_file = os.path.join(embedded_path, "lib", "libpcap.a") + if os.path.exists(target_file): + version = ctx.run(f"strings {target_file} | grep -E '^libpcap version' | cut -d ' ' -f 3").stdout.strip() + if version == LIBPCAP_VERSION: + ctx.run(f"echo 'libpcap version {version} already exists at {target_file}'") + return + dist_dir = os.path.join(embedded_path, "dist") + lib_dir = os.path.join(dist_dir, f"libpcap-{LIBPCAP_VERSION}") + ctx.run(f"rm -rf {lib_dir}") + with ctx.cd(dist_dir): + ctx.run(f"curl -L https://www.tcpdump.org/release/libpcap-{LIBPCAP_VERSION}.tar.xz | tar xJ") + with ctx.cd(lib_dir): + config_opts = [ + f"--prefix={embedded_path}", + "--disable-shared", + "--disable-largefile", + "--disable-instrument-functions", + "--disable-remote", + "--disable-usb", + "--disable-netmap", + "--disable-bluetooth", + "--disable-dbus", + "--disable-rdma", + ] + ctx.run(f"./configure {' '.join(config_opts)}") + ctx.run("make install") + ctx.run(f"rm -f {os.path.join(embedded_path, 'bin', 'pcap-config')}") + ctx.run(f"rm -rf {os.path.join(embedded_path, 'share')}") + ctx.run(f"rm -rf {os.path.join(embedded_path, 'lib', 'pkgconfig')}") + ctx.run(f"rm -rf {lib_dir}") + ctx.run(f"strip -g {target_file}") + + +def get_libpcap_cgo_flags(ctx, install_path: str = None): + """Return a dictionary with the CGO flags needed to link against libpcap. + If install_path is provided, then we expect this path to contain libpcap as a shared library. + """ + if install_path is not None: + return { + 'CGO_CFLAGS': f"-I{os.path.join(install_path, 'embedded', 'include')}", + 'CGO_LDFLAGS': f"-L{os.path.join(install_path, 'embedded', 'lib')}", + } + else: + embedded_path = get_embedded_path(ctx) + assert embedded_path, "Failed to find embedded path" + return { + 'CGO_CFLAGS': f"-I{os.path.join(embedded_path, 'include')}", + 'CGO_LDFLAGS': f"-L{os.path.join(embedded_path, 'lib')}", + } + + @task def build( ctx, @@ -621,6 +685,7 @@ def build( with_unit_test=False, bundle=True, ebpf_compiler='clang', + static=False, ): """ Build the system-probe @@ -647,6 +712,7 @@ def build( strip_binary=strip_binary, bundle=bundle, arch=arch, + static=static, ) @@ -673,6 +739,7 @@ def build_sysprobe_binary( bundle_ebpf=False, strip_binary=False, bundle=True, + static=False, ) -> None: if bundle and not is_windows: return agent_build( @@ -686,7 +753,13 @@ def build_sysprobe_binary( arch_obj = Arch.from_str(arch) - ldflags, gcflags, env = get_build_flags(ctx, install_path=install_path, major_version=major_version, arch=arch_obj) + ldflags, gcflags, env = get_build_flags( + ctx, + install_path=install_path, + major_version=major_version, + arch=arch_obj, + static=static, + ) build_tags = get_default_build_tags(build="system-probe") if bundle_ebpf: @@ -694,6 +767,20 @@ def build_sysprobe_binary( if strip_binary: ldflags += ' -s -w' + if static: + build_tags.extend(["osusergo", "netgo"]) + build_tags = list(set(build_tags).difference({"netcgo"})) + + if not is_windows and "pcap" in build_tags: + build_libpcap(ctx) + cgo_flags = get_libpcap_cgo_flags(ctx, install_path) + # append libpcap cgo-related environment variables to any existing ones + for k, v in cgo_flags.items(): + if k in env: + env[k] += f" {v}" + else: + env[k] = v + if os.path.exists(binary): os.remove(binary) @@ -1495,6 +1582,7 @@ def build_cws_object_files( strip_object_files=strip_object_files, kernel_release=kernel_release, with_unit_test=with_unit_test, + ebpf_compiler=ebpf_compiler, ) if bundle_ebpf: diff --git a/tasks/unit_tests/circleci_tests.py b/tasks/unit_tests/circleci_tests.py index 73612edd8abc1..5839b9ea5a42a 100644 --- a/tasks/unit_tests/circleci_tests.py +++ b/tasks/unit_tests/circleci_tests.py @@ -23,7 +23,7 @@ def tearDown(self) -> None: return super().tearDown() def test_nominal(self): - update_circleci_config(self.circleci_test, "1m4g3", test_version=True) + update_circleci_config(self.circleci_test, "1m4g3", test=True) with open(self.circleci_test) as gl: circle_ci = yaml.safe_load(gl) full_image = circle_ci['templates']['job_template']['docker'][0]['image'] @@ -32,7 +32,7 @@ def test_nominal(self): self.assertEqual("1m4g3", version) def test_update_no_test(self): - update_circleci_config(self.circleci_test, "1m4g3", test_version=False) + update_circleci_config(self.circleci_test, "1m4g3", test=False) with open(self.circleci_test) as gl: circle_ci = yaml.safe_load(gl) full_image = circle_ci['templates']['job_template']['docker'][0]['image'] @@ -42,4 +42,4 @@ def test_update_no_test(self): def test_raise(self): with self.assertRaises(RuntimeError): - update_circleci_config(self.erroneous_file, "1m4g3", test_version=False) + update_circleci_config(self.erroneous_file, "1m4g3", test=False) diff --git a/tasks/unit_tests/github_api_tests.py b/tasks/unit_tests/github_api_tests.py index e200a2ec74290..adfed31baffcb 100644 --- a/tasks/unit_tests/github_api_tests.py +++ b/tasks/unit_tests/github_api_tests.py @@ -56,3 +56,35 @@ def test_org(self, _): github = GithubAPI(repository="org/test", public_repo=True) self.assertEqual(github._organization, "org") + + +class TestUpdateReviewComplexityLabel(unittest.TestCase): + @patch("tasks.libs.ciproviders.github_api.Github", autospec=True) + def test_add_label(self, _): + github = GithubAPI(repository="test", public_repo=True) + with patch.object(github, '_repository') as mock_repo: + mock_pr = mock_repo.get_pull.return_value + mock_pr.get_labels.return_value = [Label("changelog/no-changelog")] + github.update_review_complexity_labels(1, "short review") + mock_pr.remove_from_labels.assert_not_called() + mock_pr.add_to_labels.assert_called_with("short review") + + @patch("tasks.libs.ciproviders.github_api.Github", autospec=True) + def test_add_same_label(self, _): + github = GithubAPI(repository="test", public_repo=True) + with patch.object(github, '_repository') as mock_repo: + mock_pr = mock_repo.get_pull.return_value + mock_pr.get_labels.return_value = [Label("changelog/no-changelog"), Label("short review")] + github.update_review_complexity_labels(1, "short review") + mock_pr.remove_from_labels.assert_not_called() + mock_pr.add_to_labels.assert_not_called() + + @patch("tasks.libs.ciproviders.github_api.Github", autospec=True) + def test_add_new_label(self, _): + github = GithubAPI(repository="test", public_repo=True) + with patch.object(github, '_repository') as mock_repo: + mock_pr = mock_repo.get_pull.return_value + mock_pr.get_labels.return_value = [Label("changelog/no-changelog"), Label("short review")] + github.update_review_complexity_labels(1, "medium review") + mock_pr.remove_from_labels.assert_called_with("short review") + mock_pr.add_to_labels.assert_called_with("medium review") diff --git a/tasks/unit_tests/gitlab_api_tests.py b/tasks/unit_tests/gitlab_api_tests.py index 781777f2037d2..4fd0016b10779 100644 --- a/tasks/unit_tests/gitlab_api_tests.py +++ b/tasks/unit_tests/gitlab_api_tests.py @@ -1,4 +1,3 @@ -import subprocess import unittest from collections import OrderedDict from unittest.mock import MagicMock, patch @@ -9,13 +8,16 @@ from tasks.libs.ciproviders.gitlab_api import ( GitlabCIDiff, MultiGitlabCIDiff, + ReferenceTag, clean_gitlab_ci_configuration, expand_matrix_jobs, filter_gitlab_ci_configuration, + find_buildimages, gitlab_configuration_is_modified, read_includes, retrieve_all_paths, update_gitlab_config, + update_image_tag, ) @@ -483,31 +485,181 @@ def test_two_modified_files(self): self.assertTrue(gitlab_configuration_is_modified(c)) -class TestUpdateGitlabCI(unittest.TestCase): - gitlabci_file = "tasks/unit_tests/testdata/fake_gitlab-ci.yml" - erroneous_file = "tasks/unit_tests/testdata/erroneous_gitlab-ci.yml" - - def tearDown(self) -> None: - subprocess.run(f"git checkout -- {self.gitlabci_file} {self.erroneous_file}".split()) - return super().tearDown() - - def test_nominal(self): - update_gitlab_config(self.gitlabci_file, "1mageV3rsi0n", test_version=True) - with open(self.gitlabci_file) as gl: - gitlab_ci = yaml.safe_load(gl) - for variable, value in gitlab_ci["variables"].items(): - # TEST_INFRA_DEFINITION_BUILDIMAGE label format differs from other buildimages - if variable.endswith("_SUFFIX") and not variable.startswith("TEST_INFRA_DEFINITION"): - self.assertEqual("_test_only", value) +class TestFilterVariables(unittest.TestCase): + def test_no_images(self): + variables = { + 'DATADOG_AGENT_BUILDIMAGES_SUFFIX': '', + 'DATADOG_AGENT_BUILDIMAGES': 'haddock', + 'DATADOG_AGENT_SYSPROBE_BUILDIMAGES_SUFFIX': '', + 'DATADOG_AGENT_SYSPROBE_BUILDIMAGES': 'v46542806-c7a4a6be', + 'CI_IMAGE_AGENT': 'tintin', + 'CI_IMAGE_AGENT_SUFFIX': '', + 'OTHER_VARIABLE_SUFFIX': '', + 'OTHER_VARIABLE': 'lampion', + } + self.assertEqual( + list(find_buildimages(variables)), ['DATADOG_AGENT_BUILDIMAGES', 'DATADOG_AGENT_SYSPROBE_BUILDIMAGES'] + ) + + def test_one_image(self): + variables = { + 'DATADOG_AGENT_BUILDIMAGES_SUFFIX': '', + 'DATADOG_AGENT_BUILDIMAGES': 'haddock', + 'CI_IMAGE_AGENT': 'tintin', + 'CI_IMAGE_AGENT_SUFFIX': '', + 'CI_IMAGE_OWNER': 'tournesol', + 'CI_IMAGE_OWNER_SUFFIX': '', + 'OTHER_VARIABLE_SUFFIX': '', + 'OTHER_VARIABLE': 'lampion', + } + self.assertEqual(list(find_buildimages(variables, "agent", "CI_IMAGE")), ['CI_IMAGE_AGENT']) + self.assertEqual(list(find_buildimages(variables, "AGENT", "CI_IMAGE")), ['CI_IMAGE_AGENT']) + + def test_multi_match(self): + variables = { + 'DATADOG_AGENT_BUILDIMAGES_SUFFIX': '', + 'DATADOG_AGENT_BUILDIMAGES': 'haddock', + 'CI_IMAGE_AGENT': 'tintin', + 'CI_IMAGE_AGENT_SUFFIX': '', + 'CI_IMAGE_AGENT_42': 'tournesol', + 'CI_IMAGE_AGENT_42_SUFFIX': '', + } + self.assertEqual( + list(find_buildimages(variables, "agent", "CI_IMAGE")), ['CI_IMAGE_AGENT', 'CI_IMAGE_AGENT_42'] + ) + self.assertEqual( + list(find_buildimages(variables, "AGENT", "CI_IMAGE")), ['CI_IMAGE_AGENT', 'CI_IMAGE_AGENT_42'] + ) + + def test_all_images(self): + variables = { + 'DATADOG_AGENT_BUILDIMAGES_SUFFIX': '', + 'DATADOG_AGENT_BUILDIMAGES': 'haddock', + 'CI_IMAGE_AGENT': 'tintin', + 'CI_IMAGE_AGENT_SUFFIX': '', + 'CI_IMAGE_AGENT_42': 'tournesol', + 'CI_IMAGE_AGENT_42_SUFFIX': '', + 'CI_IMAGE_OWNER': 'tapioca', + 'CI_IMAGE_OWNER_SUFFIX': '', + } + self.assertEqual( + list(find_buildimages(variables, "", "CI_IMAGE")), ['CI_IMAGE_AGENT', 'CI_IMAGE_AGENT_42', 'CI_IMAGE_OWNER'] + ) + self.assertEqual( + list(find_buildimages(variables, "", "CI_IMAGE")), ['CI_IMAGE_AGENT', 'CI_IMAGE_AGENT_42', 'CI_IMAGE_OWNER'] + ) + + +class TestModifyContent(unittest.TestCase): + gitlab_ci = None + + def setUp(self) -> None: + with open("tasks/unit_tests/testdata/variables.yml") as gl: + self.gitlab_ci = gl.readlines() + return super().setUp() + + def test_all_buildimages(self): + prefix = 'DATADOG_AGENT_' + images = [ + 'DATADOG_AGENT_BUILDIMAGES', + 'DATADOG_AGENT_WINBUILDIMAGES', + 'DATADOG_AGENT_ARMBUILDIMAGES', + 'DATADOG_AGENT_SYSPROBE_BUILDIMAGES', + 'DATADOG_AGENT_BTF_GEN_BUILDIMAGES', + ] + modified = update_image_tag(self.gitlab_ci, "1mageV3rsi0n", images) + yaml.SafeLoader.add_constructor(ReferenceTag.yaml_tag, ReferenceTag.from_yaml) + config = yaml.safe_load("".join(modified)) + self.assertEqual( + 5, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "_test_only") + ) + self.assertEqual( + 5, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "1mageV3rsi0n") + ) + + def test_one_buildimage(self): + prefix = 'DATADOG_AGENT_' + images = ['DATADOG_AGENT_BTF_GEN_BUILDIMAGES'] + modified = update_image_tag(self.gitlab_ci, "1mageV3rsi0n", images) + yaml.SafeLoader.add_constructor(ReferenceTag.yaml_tag, ReferenceTag.from_yaml) + config = yaml.safe_load("".join(modified)) + self.assertEqual( + 1, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "_test_only") + ) + self.assertEqual( + 1, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "1mageV3rsi0n") + ) + + def test_one_image(self): + prefix = "CI_IMAGE_" + images = ['CI_IMAGE_DEB_X64'] + modified = update_image_tag(self.gitlab_ci, "1mageV3rsi0n", images) + yaml.SafeLoader.add_constructor(ReferenceTag.yaml_tag, ReferenceTag.from_yaml) + config = yaml.safe_load("".join(modified)) + self.assertEqual( + 1, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "_test_only") + ) + self.assertEqual( + 1, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "1mageV3rsi0n") + ) + + def test_several_images(self): + prefix = "CI_IMAGE_" + images = ['CI_IMAGE_DEB_X64', 'CI_IMAGE_RPM_ARMHF'] + modified = update_image_tag(self.gitlab_ci, "1mageV3rsi0n", images) + yaml.SafeLoader.add_constructor(ReferenceTag.yaml_tag, ReferenceTag.from_yaml) + config = yaml.safe_load("".join(modified)) + self.assertEqual( + 2, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "_test_only") + ) + self.assertEqual( + 2, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "1mageV3rsi0n") + ) + + def test_multimatch(self): + prefix = "CI_IMAGE_" + images = ['X64'] + modified = update_image_tag(self.gitlab_ci, "1mageV3rsi0n", images) + yaml.SafeLoader.add_constructor(ReferenceTag.yaml_tag, ReferenceTag.from_yaml) + config = yaml.safe_load("".join(modified)) + self.assertEqual( + 7, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "_test_only") + ) + self.assertEqual( + 7, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "1mageV3rsi0n") + ) def test_update_no_test(self): - update_gitlab_config(self.gitlabci_file, "1mageV3rsi0n", test_version=False) - with open(self.gitlabci_file) as gl: - gitlab_ci = yaml.safe_load(gl) - for variable, value in gitlab_ci["variables"].items(): - if variable.endswith("_SUFFIX"): - self.assertEqual("", value) - - def test_raise(self): - with self.assertRaises(RuntimeError): - update_gitlab_config(self.erroneous_file, "1mageV3rsi0n", test_version=False) + prefix = "CI_IMAGE_" + images = [ + 'GITLAB_AGENT_DEPLOY', + 'CI_IMAGE_BTF_GEN', + 'DEB', + 'DD_AGENT_TESTING', + 'DOCKER', + 'GLIBC', + 'SYSTEM_PROBE', + 'RPM', + 'WIN', + ] + modified = update_image_tag(self.gitlab_ci, "1mageV3rsi0n", images, test=False) + yaml.SafeLoader.add_constructor(ReferenceTag.yaml_tag, ReferenceTag.from_yaml) + config = yaml.safe_load("".join(modified)) + self.assertEqual( + 0, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "_test_only") + ) + self.assertEqual( + 17, sum(1 for k, v in config["variables"].items() if k.startswith(prefix) and v == "1mageV3rsi0n") + ) + + +class TestUpdateGitlabConfig(unittest.TestCase): + def test_old_images(self): + self.assertEqual( + len(update_gitlab_config(".gitlab-ci.yml", tag="gru", images="", test=False, update=False)), 22 + ) + + def test_multi_update(self): + self.assertEqual( + len(update_gitlab_config(".gitlab-ci.yml", tag="gru", images="deb,rpm", test=False, update=False)), 11 + ) diff --git a/tasks/unit_tests/junit_tests.py b/tasks/unit_tests/junit_tests.py index 42ea6123cbb6f..58ae7f10a6e5c 100644 --- a/tasks/unit_tests/junit_tests.py +++ b/tasks/unit_tests/junit_tests.py @@ -55,7 +55,7 @@ def test_without_split(self): def test_with_split(self): xml_file = Path("./tasks/unit_tests/testdata/secret.tar.gz/-go-src-datadog-agent-junit-out-base.xml") owners = read_owners(".github/CODEOWNERS") - self.assertEqual(junit.split_junitxml(xml_file.parent, xml_file, owners, []), 27) + self.assertEqual(junit.split_junitxml(xml_file.parent, xml_file, owners, []), 29) class TestGroupPerTag(unittest.TestCase): @@ -129,4 +129,4 @@ def test_e2e(self, mock_popen): mock_popen.return_value = mock_instance junit.junit_upload_from_tgz("tasks/unit_tests/testdata/testjunit-tests_deb-x64-py3.tgz") mock_popen.assert_called() - self.assertEqual(mock_popen.call_count, 29) + self.assertEqual(mock_popen.call_count, 31) diff --git a/tasks/unit_tests/testdata/erroneous_gitlab-ci.yml b/tasks/unit_tests/testdata/erroneous_gitlab-ci.yml deleted file mode 100644 index 55456e2da4875..0000000000000 --- a/tasks/unit_tests/testdata/erroneous_gitlab-ci.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -variables: - DD_AGENT_IMAGE_SUFFIX: '' - DD_AGENT_IMAGE: 42 \ No newline at end of file diff --git a/tasks/unit_tests/testdata/fake_circleci_config.yml b/tasks/unit_tests/testdata/fake_circleci_config.yml deleted file mode 100644 index 22e93f769d59f..0000000000000 --- a/tasks/unit_tests/testdata/fake_circleci_config.yml +++ /dev/null @@ -1,358 +0,0 @@ -version: 2 - -# This file uses YAML anchors to deduplicate steps -# see https://circleci.com/blog/circleci-hacks-reuse-yaml-in-your-circleci-config-with-yaml/ -# and https://learnxinyminutes.com/docs/yaml/ - -experimental: - # For some reason filtering out notifications keeps being undocumented and - # marked as experimental but as of today, it's still working. - notify: - branches: - only: - - main - -templates: - job_template: &job_template - docker: - - image: gcr.io/datadoghq/agent-circleci-runner:v17660676-da3ba55 - environment: - USE_SYSTEM_LIBS: "1" - working_directory: /go/src/github.com/DataDog/datadog-agent - - step_templates: - - restore_cache: &restore_deps - keys: - # The first match will be used. Doing that so new branches - # use the default branch's cache but don't pollute it back. - # - # If incremental dep fails, increase the cache gen number - # in restore_deps AND save_deps - # See https://github.com/DataDog/datadog-agent/pull/2384 - - gen19-godeps-{{ checksum "requirements.txt" }}-{{ checksum ".circleci/requirements.txt" }}-{{ checksum ".circleci/images/runner/Dockerfile" }}-{{ .Branch }}-{{ .Revision }} - - gen19-godeps-{{ checksum "requirements.txt" }}-{{ checksum ".circleci/requirements.txt" }}-{{ checksum ".circleci/images/runner/Dockerfile" }}-{{ .Branch }}- - - gen19-godeps-{{ checksum "requirements.txt" }}-{{ checksum ".circleci/requirements.txt" }}-{{ checksum ".circleci/images/runner/Dockerfile" }}-main- - - save_cache: &save_deps - key: gen19-godeps-{{ checksum "requirements.txt" }}-{{ checksum ".circleci/requirements.txt" }}-{{ checksum ".circleci/images/runner/Dockerfile" }}-{{ .Branch }}-{{ .Revision }} - - restore_cache: &restore_source - keys: - # Cache retrieval is faster than full git checkout - - v5-repo-{{ .Revision }} - - save_cache: &save_source - key: v5-repo-{{ .Revision }} - -jobs: - checkout_code: - docker: - - image: alpine/git:latest - working_directory: /go/src/github.com/DataDog/datadog-agent - steps: - - checkout - - save_cache: - <<: *save_source - paths: - - /go/src/github.com/DataDog/datadog-agent - - dependencies: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: setup python deps - command: | - python3 -m pip install wheel - python3 -m pip install -r requirements.txt - python3 -m pip install -r .circleci/requirements.txt - - run: - name: check go version - command: | - inv -e check-go-version - - run: - name: grab go deps - command: | - inv -e deps - - run: - name: build rtloader - command: | - inv rtloader.make --install-prefix=/go/src/github.com/DataDog/datadog-agent/dev - inv rtloader.install - - run: - name: lint rtloader - command: | - inv rtloader.format --raise-if-changed - - run: - name: test rtloader - command: | - inv rtloader.test - - run: - name: install go tooling - command: | - inv -e install-tools - - save_cache: - <<: *save_deps - paths: - - /go/pkg/mod - - /go/bin - - /go/src/github.com/DataDog/datadog-agent/dev - - /usr/local/lib/python3.8/dist-packages - - /usr/local/bin - - unit_tests: - <<: *job_template - resource_class: xlarge - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: run unit tests - no_output_timeout: 20m - command: inv -e test --rerun-fails=2 --coverage --race --profile --cpus 8 - - integration_tests: - <<: *job_template - resource_class: large - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - setup_remote_docker - - run: - name: run integration tests - command: inv -e integration-tests --race --remote-docker - - release_note: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - command: inv -e linter.releasenote - name: run PR check for release note - - team_label: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - command: inv -e lint-teamassignment - name: run PR check for team assignment labels - - milestone: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - command: inv -e lint-milestone - name: run PR check for milestone assignment - - go_linting: - <<: *job_template - resource_class: xlarge - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: run go linters - no_output_timeout: 20m - command: inv -e linter.go - - licenses_linting: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: run license linting - command: inv -e lint-licenses - - copyrights_linting: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: run copyrights linting - command: inv -e linter.copyrights - - filename_linting: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: run filename linting - command: inv -e linter.filenames - - shell_linting: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: Install shellcheck - command: inv -e install-shellcheck - - run: - name: Print shellcheck version - command: shellcheck --version - - run: - name: Run shellcheck - #Excludes: - #SC2028: echo may not expand escape sequences. Use printf. - #SC2059: Don't use variables in the printf format string. Use printf "..%s.." "$foo". - command: shellcheck --severity=info -e SC2059 -e SC2028 --shell=bash ./cmd/**/*.sh ./omnibus/package-scripts/*/* - - python_linting: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: setting env vars for click - command: | - echo 'export LC_ALL="C.UTF-8"' >> $BASH_ENV - echo 'export LANG="C.UTF-8"' >> $BASH_ENV - - run: - name: lint python files - command: inv -e linter.python - - component_linting: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: run component linting - command: inv -e lint-components - - codeowner_linting: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: run CODEOWNER linting - command: inv -e github.lint-codeowner - - docker_tests: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - setup_remote_docker - - run: - name: run docker image tests - command: inv -e docker.test - - run: - name: run docker image integration tests - command: inv -e docker.integration-tests - - build_binaries: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: build dogstatsd - command: inv -e dogstatsd.build --static - - run: - name: build agent - command: inv -e agent.build --exclude-rtloader - - build_iot_agent: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: build iot agent - command: inv -e agent.build --flavor iot - - run: - name: test iot agent - command: DD_HOSTNAME=test-circleci-hostname ./bin/agent/agent -c ./bin/agent/dist check cpu - - documentation_generation: - <<: *job_template - steps: - - restore_cache: *restore_source - - restore_cache: *restore_deps - - run: - name: generate doxygen documentation - command: inv -e rtloader.generate-doc - -workflows: - version: 2 - test_and_build: - jobs: - - checkout_code - - dependencies: - requires: - - checkout_code - - unit_tests: - requires: - - dependencies - - integration_tests: - requires: - - dependencies - - release_note: - filters: - branches: - ignore: - - main - requires: - - dependencies - - team_label: - filters: - branches: - ignore: - - main - requires: - - dependencies - - milestone: - filters: - branches: - ignore: - - main - requires: - - dependencies - - go_linting: - requires: - - dependencies - - licenses_linting: - requires: - - dependencies - - copyrights_linting: - requires: - - dependencies - - filename_linting: - requires: - - dependencies - - shell_linting: - requires: - - dependencies - - python_linting: - requires: - - dependencies - - component_linting: - requires: - - dependencies - - codeowner_linting: - requires: - - dependencies - - docker_tests: - requires: - - dependencies - - documentation_generation: - requires: - - dependencies - - build_binaries: - requires: - - unit_tests - - integration_tests - - docker_tests - - build_iot_agent: - requires: - - unit_tests - - integration_tests - - docker_tests diff --git a/tasks/unit_tests/testdata/fake_gitlab-ci.yml b/tasks/unit_tests/testdata/fake_gitlab-ci.yml deleted file mode 100644 index 06478a78e1dcb..0000000000000 --- a/tasks/unit_tests/testdata/fake_gitlab-ci.yml +++ /dev/null @@ -1,931 +0,0 @@ ---- -include: - - .gitlab/setup.yml - - .gitlab/shared.yml - - .gitlab/maintenance_jobs.yml - - .gitlab/deps_build.yml - - .gitlab/package_deps_build.yml - - .gitlab/deps_fetch.yml - - .gitlab/source_test.yml - - .gitlab/source_test_junit_upload.yml - - .gitlab/binary_build.yml - - .gitlab/cancel-prev-pipelines.yml - - .gitlab/do_not_merge.yml - - .gitlab/integration_test.yml - - .gitlab/package_build.yml - - .gitlab/kitchen_deploy.yml - - .gitlab/kitchen_testing.yml - - .gitlab/kitchen_tests_upload.yml - - .gitlab/new-e2e_testing.yml - - .gitlab/new-e2e_common/testing.yml - - .gitlab/install_script_testing.yml - - .gitlab/pkg_metrics.yml - - .gitlab/container_build.yml - - .gitlab/container_scan.yml - - .gitlab/check_deploy.yml - - .gitlab/dev_container_deploy.yml - - .gitlab/deploy_common.yml - - .gitlab/deploy_containers.yml - - .gitlab/deploy_packages.yml - - .gitlab/deploy_dca.yml - - .gitlab/choco_build.yml - - .gitlab/choco_deploy.yml - - .gitlab/internal_image_deploy.yml - - .gitlab/trigger_release.yml - - .gitlab/e2e.yml - - .gitlab/e2e_test_junit_upload.yml - - .gitlab/fakeintake.yml - - .gitlab/kitchen_cleanup.yml - - .gitlab/functional_test.yml - - .gitlab/functional_test_cleanup.yml - - .gitlab/functional_test_junit_upload.yml - - .gitlab/internal_kubernetes_deploy.yml - - .gitlab/notify.yml - - .gitlab/kitchen_common/cleanup.yml - - .gitlab/kitchen_common/testing.yml - - .gitlab/benchmarks/benchmarks.yml - - .gitlab/benchmarks/macrobenchmarks.yml - -default: - retry: - max: 2 - when: - - runner_system_failure - - stuck_or_timeout_failure - - unknown_failure - - api_failure - -stages: - - .pre - - setup - - maintenance_jobs - - deps_build - - deps_fetch - - source_test - - source_test_junit_upload - - binary_build - - package_deps_build - - kernel_matrix_testing - - integration_test - - benchmarks - - package_build - - kitchen_deploy - - kitchen_testing - - kitchen_tests_upload - - pkg_metrics - - container_build - - container_scan - - check_deploy - - dev_container_deploy - - deploy_containers - - deploy_packages - - trigger_release - - deploy_dca - - choco_build - - choco_deploy - - internal_image_deploy - - install_script_testing - - e2e - - e2e_test_junit_upload - - kitchen_cleanup - - functional_test - - functional_test_cleanup - - functional_test_junit_upload - - internal_kubernetes_deploy - - notify - -variables: - # Directory in which we execute the omnibus build. - # For an unknown reason, it does not go well with - # a ruby dependency if we build directly into $CI_PROJECT_DIR/.omnibus - OMNIBUS_BASE_DIR: /omnibus - # Directory in which we put the artifacts after the build - # Must be in $CI_PROJECT_DIR - OMNIBUS_PACKAGE_DIR: $CI_PROJECT_DIR/omnibus/pkg/ - # Directory in which we put the SUSE artifacts after the SUSE build - # Must be in $CI_PROJECT_DIR - # RPM builds and SUSE RPM builds create artifacts with the same name. - # To differentiate them, we put them in different folders. That also - # avoids accidentally overwriting files when downloading artifacts from - # both RPM and SUSE rpm jobs. - OMNIBUS_PACKAGE_DIR_SUSE: $CI_PROJECT_DIR/omnibus/suse/pkg - DD_AGENT_TESTING_DIR: $CI_PROJECT_DIR/test/kitchen - STATIC_BINARIES_DIR: bin/static - DOGSTATSD_BINARIES_DIR: bin/dogstatsd - AGENT_BINARIES_DIR: bin/agent - CLUSTER_AGENT_BINARIES_DIR: bin/datadog-cluster-agent - CWS_INSTRUMENTATION_BINARIES_DIR: bin/cws-instrumentation - CLUSTER_AGENT_CLOUDFOUNDRY_BINARIES_DIR: bin/datadog-cluster-agent-cloudfoundry - SYSTEM_PROBE_BINARIES_DIR: bin/system-probe - DEB_S3_BUCKET: apt.datad0g.com - RPM_S3_BUCKET: yum.datad0g.com - MACOS_S3_BUCKET: dd-agent-macostesting - WIN_S3_BUCKET: dd-agent-mstesting - PROCESS_S3_BUCKET: datad0g-process-agent - BUCKET_BRANCH: dev # path inside the staging s3 buckets to release to: 'nightly', 'oldnightly', 'beta' or 'stable' - DEB_TESTING_S3_BUCKET: apttesting.datad0g.com - RPM_TESTING_S3_BUCKET: yumtesting.datad0g.com - WINDOWS_TESTING_S3_BUCKET_A6: pipelines/A6/$CI_PIPELINE_ID - WINDOWS_TESTING_S3_BUCKET_A7: pipelines/A7/$CI_PIPELINE_ID - WINDOWS_BUILDS_S3_BUCKET: $WIN_S3_BUCKET/builds - DEB_RPM_TESTING_BUCKET_BRANCH: testing # branch of the DEB_TESTING_S3_BUCKET and RPM_TESTING_S3_BUCKET repos to release to, 'testing' - DD_REPO_BRANCH_NAME: $CI_COMMIT_REF_NAME - S3_CP_OPTIONS: --only-show-errors --region us-east-1 --sse AES256 - S3_CP_CMD: aws s3 cp $S3_CP_OPTIONS - S3_ARTIFACTS_URI: s3://dd-ci-artefacts-build-stable/$CI_PROJECT_NAME/$CI_PIPELINE_ID - S3_PERMANENT_ARTIFACTS_URI: s3://dd-ci-persistent-artefacts-build-stable/$CI_PROJECT_NAME - S3_SBOM_STORAGE_URI: s3://sbom-root-us1-ddbuild-io/$CI_PROJECT_NAME/$CI_PIPELINE_ID - S3_RELEASE_ARTIFACTS_URI: s3://dd-release-artifacts/$CI_PROJECT_NAME/$CI_PIPELINE_ID - ## comment out both lines below (S3_OMNIBUS_CACHE_BUCKET and USE_S3_CACHING) to allow - ## build to succeed with S3 caching disabled. - S3_OMNIBUS_CACHE_BUCKET: dd-ci-datadog-agent-omnibus-cache-build-stable - USE_S3_CACHING: --omnibus-s3-cache - ## comment out the line below to disable integration wheels cache - INTEGRATION_WHEELS_CACHE_BUCKET: dd-agent-omnibus - S3_DD_AGENT_OMNIBUS_LLVM_URI: s3://dd-agent-omnibus/llvm - S3_DD_AGENT_OMNIBUS_BTFS_URI: s3://dd-agent-omnibus/btfs - GENERAL_ARTIFACTS_CACHE_BUCKET_URL: https://dd-agent-omnibus.s3.amazonaws.com - S3_DSD6_URI: s3://dsd6-staging - RELEASE_VERSION_6: nightly - RELEASE_VERSION_7: nightly-a7 - - # Build images versions - # To use images from datadog-agent-buildimages dev branches, set the corresponding - # SUFFIX variable to _test_only - DATADOG_AGENT_BUILDIMAGES_SUFFIX: "" - DATADOG_AGENT_BUILDIMAGES: v21999990-f991d55 - DATADOG_AGENT_WINBUILDIMAGES_SUFFIX: "" - DATADOG_AGENT_WINBUILDIMAGES: v21999990-f991d55 - DATADOG_AGENT_ARMBUILDIMAGES_SUFFIX: "" - DATADOG_AGENT_ARMBUILDIMAGES: v21999990-f991d55 - DATADOG_AGENT_SYSPROBE_BUILDIMAGES_SUFFIX: "" - DATADOG_AGENT_SYSPROBE_BUILDIMAGES: v21999990-f991d55 - DATADOG_AGENT_KERNEL_MATRIX_TESTING_BUILDIMAGES_SUFFIX: "" - DATADOG_AGENT_KERNEL_MATRIX_TESTING_BUILDIMAGES: v21999990-f991d55 - DATADOG_AGENT_NIKOS_BUILDIMAGES_SUFFIX: "" - DATADOG_AGENT_NIKOS_BUILDIMAGES: v21999990-f991d55 - DATADOG_AGENT_BTF_GEN_BUILDIMAGES_SUFFIX: "" - DATADOG_AGENT_BTF_GEN_BUILDIMAGES: v21999990-f991d55 - # To use images from test-infra-definitions dev branches, set the SUFFIX variable to -dev - # and check the job creating the image to make sure you have the right SHA prefix - TEST_INFRA_DEFINITIONS_BUILDIMAGES_SUFFIX: "" - TEST_INFRA_DEFINITIONS_BUILDIMAGES: 59215b0d47c4 - - DATADOG_AGENT_EMBEDDED_PATH: /opt/datadog-agent/embedded - DEB_GPG_KEY_ID: ad9589b7 - DEB_GPG_KEY_NAME: "Datadog, Inc. Master key" - DEB_GPG_KEY: ci.datadog-agent.deb_signing_private_key_${DEB_GPG_KEY_ID} - DEB_SIGNING_PASSPHRASE: ci.datadog-agent.deb_signing_key_passphrase_${DEB_GPG_KEY_ID} - RPM_GPG_KEY_ID: fd4bf915 - RPM_GPG_KEY_NAME: "Datadog, Inc. RPM key" - RPM_GPG_KEY: ci.datadog-agent.rpm_signing_private_key_${RPM_GPG_KEY_ID} - RPM_SIGNING_PASSPHRASE: ci.datadog-agent.rpm_signing_key_passphrase_${RPM_GPG_KEY_ID} - # docker.io authentication - DOCKER_REGISTRY_LOGIN: docker_hub_login - DOCKER_REGISTRY_PWD: docker_hub_pwd - DOCKER_REGISTRY_URL: docker.io - KITCHEN_INFRASTRUCTURE_FLAKES_RETRY: 2 - CLANG_LLVM_VER: 12.0.1 - KERNEL_MATRIX_TESTING_X86_AMI_ID: "ami-098ea4991ff2d244c" - KERNEL_MATRIX_TESTING_ARM_AMI_ID: "ami-04493daab2918046c" - -# -# Condition mixins for simplification of rules -# -.if_main_branch: &if_main_branch - if: $CI_COMMIT_BRANCH == "main" - -.if_not_main_branch: &if_not_main_branch - if: $CI_COMMIT_BRANCH != "main" - -.if_release_branch: &if_release_branch - if: $CI_COMMIT_BRANCH =~ /^[0-9]+\.[0-9]+\.x$/ - -.if_version_6: &if_version_6 - if: $RELEASE_VERSION_6 != "" - -.if_not_version_6: &if_not_version_6 - if: $RELEASE_VERSION_6 == "" - -.if_version_7: &if_version_7 - if: $RELEASE_VERSION_7 != "" - -.if_not_version_7: &if_not_version_7 - if: $RELEASE_VERSION_7 == "" - -.if_deploy: &if_deploy - if: $DEPLOY_AGENT == "true" - -.if_not_deploy: &if_not_deploy - if: $DEPLOY_AGENT != "true" - -.if_tagged_commit: &if_tagged_commit - if: $CI_COMMIT_TAG != null - -.if_not_nightly_repo_branch: &if_not_nightly_repo_branch - if: $BUCKET_BRANCH != "nightly" && $BUCKET_BRANCH != "oldnightly" - -.if_not_nightly_or_dev_repo_branch: &if_not_nightly_or_dev_repo_branch - if: $BUCKET_BRANCH != "nightly" && $BUCKET_BRANCH != "oldnightly" && $BUCKET_BRANCH != "dev" - -.if_not_stable_or_beta_repo_branch: &if_not_stable_or_beta_repo_branch - if: $BUCKET_BRANCH != "beta" && $BUCKET_BRANCH != "stable" - -.if_not_stable_repo_branch: &if_not_stable_repo_branch - if: $BUCKET_BRANCH != "stable" - -# CI_PIPELINE_SOURCE can be set to "trigger" or "pipeline" depending on how the trigger was done. -# See https://docs.gitlab.com/ee/ci/triggers/index.html#configure-cicd-jobs-to-run-in-triggered-pipelines. -.if_triggered_pipeline: &if_triggered_pipeline - if: $CI_PIPELINE_SOURCE == "trigger" || $CI_PIPELINE_SOURCE == "pipeline" - -# Rule to trigger all builds conditionally. -# By default: -# - on main and deploy pipelines, all builds are run -# - on branch pipelines, only a subset of build jobs are run (the ARM and MacOS jobs are not run). -# RUN_ALL_BUILDS can be set to true to force all build jobs to be run on a branch pipeline. -# RUN_ALL_BUILDS has no effect on main/deploy pipelines: they always run all builds (as some jobs -# on main and deploy pipelines depend on jobs that are only run if we run all builds). -.if_run_all_builds: &if_run_all_builds - if: $CI_COMMIT_BRANCH == "main" || $DEPLOY_AGENT == "true" || $RUN_ALL_BUILDS == "true" - -.if_not_run_all_builds: &if_not_run_all_builds - if: $CI_COMMIT_BRANCH != "main" && $DEPLOY_AGENT != "true" && $RUN_ALL_BUILDS != "true" - -# Rule to trigger test kitchen setup, run, and cleanup. -# By default: -# - on main and deploy pipelines, kitchen tests are run -# - on branch pipelines, kitchen tests are not run -# RUN_KITCHEN_TESTS can be set to true to force kitchen tests to be run on a branch pipeline. -# RUN_KITCHEN_TESTS can be set to false to force kitchen tests to not run on main/deploy pipelines. -.if_kitchen: &if_kitchen - if: ($CI_COMMIT_BRANCH == "main" || $DEPLOY_AGENT == "true" || $RUN_KITCHEN_TESTS == "true") && $RUN_KITCHEN_TESTS != "false" - -# Rules to trigger default kitchen tests. -# Some of the kitchen tests are run on all pipelines by default. They can only be disabled -# by setting RUN_KITCHEN_TESTS to false. -.if_default_kitchen: &if_default_kitchen - if: $RUN_KITCHEN_TESTS != "false" - -.if_testing_cleanup: &if_testing_cleanup - if: $TESTING_CLEANUP == "true" - -.if_not_e2e: &if_not_e2e - if: $RUN_KITCHEN_TESTS == "false" - -.if_deploy_on_beta_repo_branch: &if_deploy_on_beta_repo_branch - if: $DEPLOY_AGENT == "true" && $BUCKET_BRANCH == "beta" - -.if_deploy_on_stable_repo_branch: &if_deploy_on_stable_repo_branch - if: $DEPLOY_AGENT == "true" && $BUCKET_BRANCH == "stable" - -# Rule to trigger jobs only when a tag matches a given pattern (for RCs) -# on the beta branch. -# Note: due to workflow rules, rc tag => deploy pipeline, so there's technically no -# need to check again if the pipeline is a deploy pipeline, but it doesn't hurt -# to explicitly add it. -.if_deploy_on_rc_tag_on_beta_repo_branch: &if_rc_tag_on_beta_repo_branch - if: $DEPLOY_AGENT == "true" && $BUCKET_BRANCH == "beta" && $CI_COMMIT_TAG =~ /^[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$/ - -.if_scheduled_main: &if_scheduled_main - if: $CI_PIPELINE_SOURCE == "schedule" && $CI_COMMIT_BRANCH == "main" - -# -# Workflow rules -# Rules used to define whether a pipeline should run, and with which variables -# - -workflow: - rules: - - <<: *if_triggered_pipeline - - <<: *if_main_branch - - <<: *if_release_branch - - <<: *if_deploy - - if: $CI_COMMIT_TAG == null - -# -# List of rule blocks used in the pipeline -# Any job in the pipeline either runs (with when: on_success) in all pipelines, or follows one of the below rule blocks. -# - -.manual: - - when: manual - allow_failure: true - -.on_a6: - - <<: *if_version_6 - -.on_a6_manual: - - <<: *if_version_6 - when: manual - allow_failure: true - -.on_a7: - - <<: *if_version_7 - -.on_a7_manual: - - <<: *if_version_7 - when: manual - allow_failure: true - -.on_dev_branch_manual: - - <<: *if_main_branch - when: never - - <<: *if_tagged_commit - when: never - - when: manual - allow_failure: true - -.on_main: - - <<: *if_main_branch - -.on_main_manual: - - <<: *if_main_branch - when: manual - allow_failure: true - -.on_main_a6: - - <<: *if_not_version_6 - when: never - - <<: *if_main_branch - -.on_main_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_main_branch - -.on_tag_or_a7: - - <<: *if_tagged_commit - - <<: *if_version_7 - -.on_tag_or_a7_all_builds: - - <<: *if_not_run_all_builds - when: never - - <<: *if_tagged_commit - - <<: *if_version_7 - -.on_deploy: - - <<: *if_deploy - -.on_deploy_failure: - - <<: *if_deploy - when: on_failure - -.on_deploy_a6: - - <<: *if_not_version_6 - when: never - - <<: *if_deploy - -.on_deploy_a6_failure: - - <<: *if_not_version_6 - when: never - - <<: *if_deploy - when: on_failure - -.on_deploy_a6_rc: - - <<: *if_not_version_6 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_rc_tag_on_beta_repo_branch - when: on_success - variables: - AGENT_REPOSITORY: agent - DSD_REPOSITORY: dogstatsd - IMG_REGISTRIES: public - -.on_deploy_a6_manual: - - <<: *if_not_version_6 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent-dev - IMG_REGISTRIES: dev - - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent - IMG_REGISTRIES: public - -# Same as on_deploy_a6_manual, except the job would not run on pipelines -# using beta branch, it would only run for the final release. -.on_deploy_a6_manual_final: - - <<: *if_not_version_6 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_deploy_on_beta_repo_branch - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent-dev - IMG_REGISTRIES: dev - - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent - IMG_REGISTRIES: public - -# This rule is a variation of on_deploy_a6_manual where -# the job is usually run manually, except when the pipeline -# builds an RC: in this case, the job is run automatically. -# This is done to reduce the number of manual steps that have -# to be done when creating RCs. -.on_deploy_a6_manual_auto_on_rc: - - <<: *if_not_version_6 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent-dev - IMG_REGISTRIES: dev - - <<: *if_rc_tag_on_beta_repo_branch - when: on_success - variables: - AGENT_REPOSITORY: agent - DSD_REPOSITORY: dogstatsd - IMG_REGISTRIES: public - - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent - IMG_REGISTRIES: public - -.on_deploy_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_deploy - -.on_deploy_a7_failure: - - <<: *if_not_version_7 - when: never - - <<: *if_deploy - when: on_failure - -.on_deploy_a7_rc: - - <<: *if_not_version_7 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_rc_tag_on_beta_repo_branch - when: on_success - variables: - AGENT_REPOSITORY: agent - DSD_REPOSITORY: dogstatsd - IMG_REGISTRIES: public - -.on_deploy_a7_manual: - - <<: *if_not_version_7 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent-dev - DSD_REPOSITORY: dogstatsd-dev - IMG_REGISTRIES: dev - - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent - DSD_REPOSITORY: dogstatsd - IMG_REGISTRIES: public - -# rule to trigger job for internal image deployment if deploy is set or -# manually if not -.on_deploy_a7_internal_or_manual: - - <<: *if_not_version_7 - when: never - - <<: *if_deploy - variables: - RELEASE_PROD: "true" - - when: manual - allow_failure: true - variables: - RELEASE_PROD: "false" - -# Same as on_deploy_a7_manual, except the job would not run on pipelines -# using beta branch, it would only run for the final release. -.on_deploy_a7_manual_final: - - <<: *if_not_version_7 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_deploy_on_beta_repo_branch - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent-dev - DSD_REPOSITORY: dogstatsd-dev - IMG_REGISTRIES: dev - - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent - DSD_REPOSITORY: dogstatsd - IMG_REGISTRIES: public - -# This rule is a variation of on_deploy_a7_manual where -# the job is usually run manually, except when the pipeline -# builds an RC: in this case, the job is run automatically. -# This is done to reduce the number of manual steps that have -# to be done when creating RCs. -.on_deploy_a7_manual_auto_on_rc: - - <<: *if_not_version_7 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent-dev - DSD_REPOSITORY: dogstatsd-dev - IMG_REGISTRIES: dev - - <<: *if_rc_tag_on_beta_repo_branch - when: on_success - variables: - AGENT_REPOSITORY: agent - DSD_REPOSITORY: dogstatsd - IMG_REGISTRIES: public - - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: agent - DSD_REPOSITORY: dogstatsd - IMG_REGISTRIES: public - -# This is used for image vulnerability scanning. Because agent 6 -# uses python 2, which has many vulnerabilities that will not get -# patched, we do not wish to scan this image. For this reason, only -# agent 7 versions should be published internally using these -# configurations. -.on_deploy_a7_internal_rc: - - <<: *if_not_version_7 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_rc_tag_on_beta_repo_branch - when: on_success - variables: - AGENT_REPOSITORY: ci/datadog-agent/agent-release - CLUSTER_AGENT_REPOSITORY: ci/datadog-agent/cluster-agent-release - DSD_REPOSITORY: ci/datadog-agent/dogstatsd-release - IMG_REGISTRIES: internal-aws-ddbuild - -# Same as on_deploy_a7_manual_final, except the job is used to publish images -# to our internal registries. -.on_deploy_a7_internal_manual_final: - - <<: *if_not_version_7 - when: never - - <<: *if_not_deploy - when: never - - <<: *if_deploy_on_beta_repo_branch - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: never - - when: manual - allow_failure: true - variables: - AGENT_REPOSITORY: ci/datadog-agent/agent-release - CLUSTER_AGENT_REPOSITORY: ci/datadog-agent/cluster-agent-release - DSD_REPOSITORY: ci/datadog-agent/dogstatsd-release - IMG_REGISTRIES: internal-aws-ddbuild - -.on_deploy_nightly_repo_branch_a6: - - <<: *if_not_version_6 - when: never - - <<: *if_not_nightly_repo_branch - when: never - - <<: *if_deploy - -.on_deploy_nightly_repo_branch_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_not_nightly_repo_branch - when: never - - <<: *if_deploy - -.on_deploy_stable_or_beta_repo_branch: - - <<: *if_not_stable_or_beta_repo_branch - when: never - - <<: *if_deploy - -.on_deploy_stable_or_beta_repo_branch_a6: - - <<: *if_not_version_6 - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: never - - <<: *if_deploy - -.on_deploy_stable_or_beta_repo_branch_a6_manual: - - <<: *if_not_version_6 - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: never - - <<: *if_deploy - when: manual - allow_failure: true - -.on_deploy_stable_or_beta_repo_branch_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: never - - <<: *if_deploy - -.on_deploy_stable_or_beta_repo_branch_a7_manual: - - <<: *if_not_version_7 - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: never - - <<: *if_deploy - when: manual - allow_failure: true - -.on_deploy_stable_or_rc_tag_on_beta_repo_branch_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: never - - <<: *if_rc_tag_on_beta_repo_branch - when: on_success - - <<: *if_deploy_on_stable_repo_branch - when: on_success - - when: never - -.on_deploy_stable_or_rc_tag_on_beta_repo_branch_a7_manual_on_stable: - - <<: *if_not_version_7 - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: never - - <<: *if_rc_tag_on_beta_repo_branch - when: on_success - - <<: *if_deploy_on_stable_repo_branch - when: manual - allow_failure: true - - when: never - -# This rule is a variation of on_deploy_stable_or_beta_repo_branch_a7_manual where -# the job is usually run manually, except when the pipeline -# builds an RC: in this case, the job is run automatically. -# This is done to reduce the number of manual steps that have -# to be done when creating RCs. -.on_deploy_stable_or_beta_repo_branch_a7_manual_auto_on_rc: - - <<: *if_not_version_7 - when: never - - <<: *if_not_stable_or_beta_repo_branch - when: never - - <<: *if_rc_tag_on_beta_repo_branch - when: on_success - - <<: *if_deploy - when: manual - allow_failure: true - -# This rule will add the job as manual when running on beta deploy branch -# and will add it as a regular automatically running job when running -# on stable deploy branch. -.on_deploy_stable_or_beta_manual_auto_on_stable: - - <<: *if_not_stable_or_beta_repo_branch - when: never - - <<: *if_not_deploy - when: never - - <<: *if_not_stable_repo_branch - when: manual - allow_failure: true - - when: on_success - -.on_deploy_stable_repo_branch_a7_manual: - - <<: *if_not_version_7 - when: never - - <<: *if_not_stable_repo_branch - when: never - - <<: *if_deploy - when: manual - allow_failure: true - -.except_deploy: - - <<: *if_deploy - when: never - -.on_a6_except_deploy: - - <<: *if_not_version_6 - when: never - - <<: *if_deploy - when: never - - when: on_success - -.on_a7_except_deploy: - - <<: *if_not_version_7 - when: never - - <<: *if_deploy - when: never - - when: on_success - -.on_main_or_release_branch: - - <<: *if_main_branch - - <<: *if_release_branch - -.except_main_or_release_branch: - - <<: *if_main_branch - when: never - - <<: *if_release_branch - when: never - -.on_main_or_release_branch_or_deploy_always: - - <<: *if_deploy - when: always - - <<: *if_main_branch - when: always - - <<: *if_release_branch - when: always - -.on_all_builds: - - <<: *if_run_all_builds - -.on_all_builds_a6: - - <<: *if_not_version_6 - when: never - - <<: *if_run_all_builds - -.on_all_builds_a6_manual: - - <<: *if_not_version_6 - when: never - - <<: *if_run_all_builds - when: manual - allow_failure: true - -.on_all_builds_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_run_all_builds - -.on_all_builds_a7_manual: - - <<: *if_not_version_7 - when: never - - <<: *if_run_all_builds - when: manual - allow_failure: true - -.on_kitchen_tests_a6: - - <<: *if_not_version_6 - when: never - - <<: *if_kitchen - -.on_kitchen_tests_a6_always: - - <<: *if_not_version_6 - when: never - - <<: *if_kitchen - when: always - -.on_all_kitchen_builds_a6: - - <<: *if_not_version_6 - when: never - - <<: *if_not_run_all_builds - when: never - - <<: *if_kitchen - -.on_kitchen_tests_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_kitchen - -.on_kitchen_tests_a7_always: - - <<: *if_not_version_7 - when: never - - <<: *if_kitchen - when: always - -.on_all_kitchen_builds_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_not_run_all_builds - when: never - - <<: *if_kitchen - -# Default kitchen tests are also run on dev branches -# In that case, the target OS versions is a subset of the -# available versions, stored in DEFAULT_KITCHEN_OSVERS -.on_default_kitchen_tests_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_kitchen - - <<: *if_default_kitchen - variables: - KITCHEN_OSVERS: $DEFAULT_KITCHEN_OSVERS - -.on_default_new-e2e_tests_a7: - - <<: *if_not_version_7 - when: never - - <<: *if_kitchen - - <<: *if_default_kitchen - variables: - E2E_OSVERS: $E2E_BRANCH_OSVERS - -.on_default_kitchen_tests_a7_always: - - <<: *if_not_version_7 - when: never - - <<: *if_kitchen - when: always - - <<: *if_default_kitchen - when: always - variables: - KITCHEN_OSVERS: $DEFAULT_KITCHEN_OSVERS - -.on_main_or_testing_cleanup: - - <<: *if_main_branch - - <<: *if_testing_cleanup - -.on_testing_cleanup: - - <<: *if_testing_cleanup - -.on_security_agent_changes_or_manual: - - <<: *if_main_branch - allow_failure: true - - changes: - paths: - - pkg/ebpf/**/* - - pkg/security/**/* - - pkg/eventmonitor/**/* - - test/kitchen/site-cookbooks/dd-security-agent-check/**/* - - test/kitchen/test/integration/security-agent-test/**/* - - test/kitchen/test/integration/security-agent-stress/**/* - - .gitlab/functional_test/security_agent.yml - compare_to: main # TODO: use a variable, when this is supported https://gitlab.com/gitlab-org/gitlab/-/issues/369916 - when: on_success - - when: manual - allow_failure: true - -.on_system_probe_or_e2e_changes_or_manual: - - <<: *if_main_branch - - changes: - paths: - - pkg/collector/corechecks/ebpf/**/* - - pkg/ebpf/**/* - - pkg/network/**/* - - pkg/process/monitor/* - - pkg/util/kernel/**/* - - test/kitchen/site-cookbooks/dd-system-probe-check/**/* - - test/kitchen/test/integration/system-probe-test/**/* - - test/kitchen/test/integration/win-sysprobe-test/**/* - - .gitlab/functional_test_sysprobe/system_probe.yml - - .gitlab/kernel_version_testing/system_probe.yml - - test/new-e2e/system-probe/**/* - - test/new-e2e/scenarios/system-probe/**/* - - test/new-e2e/runner/**/* - - test/new-e2e-utils/**/* - - test/new-e2e/go.mod - - tasks/system_probe.py - compare_to: main # TODO: use a variable, when this is supported https://gitlab.com/gitlab-org/gitlab/-/issues/369916 - when: on_success - - when: manual - allow_failure: true - -.on_install_script_release_manual: - - <<: *if_not_version_7 - when: never - - <<: *if_not_version_6 - when: never - - <<: *if_not_main_branch - when: never - - <<: *if_kitchen - when: manual - allow_failure: true - -.on_trace_agent_changes_or_manual: - - changes: - - pkg/trace/**/* - - .gitlab/benchmarks/* - when: on_success - - when: manual - allow_failure: true - -.on_scheduled_main: - - <<: *if_scheduled_main - -.on_scheduled_main_or_manual: - - <<: *if_scheduled_main - when: always - - when: manual - allow_failure: true - -.on_main_or_rc_and_no_skip_e2e: - - <<: *if_not_e2e - when: never - - <<: *if_tagged_commit - when: on_success - - <<: *if_main_branch - when: on_success diff --git a/tasks/unit_tests/testdata/variables.yml b/tasks/unit_tests/testdata/variables.yml new file mode 100644 index 0000000000000..1583ab354d5cc --- /dev/null +++ b/tasks/unit_tests/testdata/variables.yml @@ -0,0 +1,208 @@ +--- +variables: + # Directory in which we execute the omnibus build. + # For an unknown reason, it does not go well with + # a ruby dependency if we build directly into $CI_PROJECT_DIR/.omnibus + OMNIBUS_BASE_DIR: /omnibus + # Directory in which we put the artifacts after the build + # Must be in $CI_PROJECT_DIR + OMNIBUS_PACKAGE_DIR: $CI_PROJECT_DIR/omnibus/pkg/ + # Directory in which we put the SUSE artifacts after the SUSE build + # Must be in $CI_PROJECT_DIR + # RPM builds and SUSE RPM builds create artifacts with the same name. + # To differentiate them, we put them in different folders. That also + # avoids accidentally overwriting files when downloading artifacts from + # both RPM and SUSE rpm jobs. + OMNIBUS_PACKAGE_DIR_SUSE: $CI_PROJECT_DIR/omnibus/suse/pkg + DD_AGENT_TESTING_DIR: $CI_PROJECT_DIR/test/kitchen + STATIC_BINARIES_DIR: bin/static + DOGSTATSD_BINARIES_DIR: bin/dogstatsd + AGENT_BINARIES_DIR: bin/agent + CLUSTER_AGENT_BINARIES_DIR: bin/datadog-cluster-agent + CWS_INSTRUMENTATION_BINARIES_DIR: bin/cws-instrumentation + CLUSTER_AGENT_CLOUDFOUNDRY_BINARIES_DIR: bin/datadog-cluster-agent-cloudfoundry + SYSTEM_PROBE_BINARIES_DIR: bin/system-probe + DEB_S3_BUCKET: apt.datad0g.com + RPM_S3_BUCKET: yum.datad0g.com + MACOS_S3_BUCKET: dd-agent-macostesting + WIN_S3_BUCKET: dd-agent-mstesting + PROCESS_S3_BUCKET: datad0g-process-agent + BUCKET_BRANCH: dev # path inside the staging s3 buckets to release to: 'dev', 'nightly', 'oldnightly', 'beta' or 'stable' + DEB_TESTING_S3_BUCKET: apttesting.datad0g.com + RPM_TESTING_S3_BUCKET: yumtesting.datad0g.com + WINDOWS_TESTING_S3_BUCKET_A6: pipelines/A6/$CI_PIPELINE_ID + WINDOWS_TESTING_S3_BUCKET_A7: pipelines/A7/$CI_PIPELINE_ID + WINDOWS_BUILDS_S3_BUCKET: $WIN_S3_BUCKET/builds + WINDOWS_POWERSHELL_DIR: $CI_PROJECT_DIR/signed_scripts + DEB_RPM_TESTING_BUCKET_BRANCH: testing # branch of the DEB_TESTING_S3_BUCKET and RPM_TESTING_S3_BUCKET repos to release to, 'testing' + S3_CP_OPTIONS: --no-progress --region us-east-1 --sse AES256 + S3_CP_CMD: aws s3 cp $S3_CP_OPTIONS + S3_ARTIFACTS_URI: s3://dd-ci-artefacts-build-stable/$CI_PROJECT_NAME/$CI_PIPELINE_ID + S3_PROJECT_ARTIFACTS_URI: s3://dd-ci-artefacts-build-stable/$CI_PROJECT_NAME + S3_PERMANENT_ARTIFACTS_URI: s3://dd-ci-persistent-artefacts-build-stable/$CI_PROJECT_NAME + S3_SBOM_STORAGE_URI: s3://sbom-root-us1-ddbuild-io/$CI_PROJECT_NAME/$CI_PIPELINE_ID + S3_RELEASE_ARTIFACTS_URI: s3://dd-release-artifacts/$CI_PROJECT_NAME/$CI_PIPELINE_ID + S3_RELEASE_INSTALLER_ARTIFACTS_URI: s3://dd-release-artifacts/datadog-installer/$CI_PIPELINE_ID + ## comment out both lines below (S3_OMNIBUS_CACHE_BUCKET and USE_S3_CACHING) to allow + ## build to succeed with S3 caching disabled. + S3_OMNIBUS_CACHE_BUCKET: dd-ci-datadog-agent-omnibus-cache-build-stable + USE_S3_CACHING: --omnibus-s3-cache + OMNIBUS_GIT_CACHE_DIR: /tmp/omnibus-git-cache + ## comment out the line below to disable integration wheels cache + INTEGRATION_WHEELS_CACHE_BUCKET: dd-agent-omnibus + S3_DD_AGENT_OMNIBUS_LLVM_URI: s3://dd-agent-omnibus/llvm + S3_DD_AGENT_OMNIBUS_BTFS_URI: s3://dd-agent-omnibus/btfs + BTFHUB_ARCHIVE_BRANCH: main + GENERAL_ARTIFACTS_CACHE_BUCKET_URL: https://dd-agent-omnibus.s3.amazonaws.com + S3_DSD6_URI: s3://dsd6-staging + RELEASE_VERSION_6: nightly + RELEASE_VERSION_7: nightly-a7 + + # Build images versions + # To use images from datadog-agent-buildimages dev branches, set the corresponding + # SUFFIX variable to _test_only + DATADOG_AGENT_BUILDIMAGES_SUFFIX: "" + DATADOG_AGENT_BUILDIMAGES: v46542806-c7a4a6be + DATADOG_AGENT_WINBUILDIMAGES_SUFFIX: "" + DATADOG_AGENT_WINBUILDIMAGES: v46542806-c7a4a6be + DATADOG_AGENT_ARMBUILDIMAGES_SUFFIX: "" + DATADOG_AGENT_ARMBUILDIMAGES: v46542806-c7a4a6be + DATADOG_AGENT_SYSPROBE_BUILDIMAGES_SUFFIX: "" + DATADOG_AGENT_SYSPROBE_BUILDIMAGES: v46542806-c7a4a6be + DATADOG_AGENT_BTF_GEN_BUILDIMAGES_SUFFIX: "" + DATADOG_AGENT_BTF_GEN_BUILDIMAGES: v46542806-c7a4a6be + # New images to enable different version per image - not used yet + CI_IMAGE_BTF_GEN: v46542806-c7a4a6be + CI_IMAGE_BTF_GEN_SUFFIX: "" + CI_IMAGE_DEB_X64: v46542806-c7a4a6be + CI_IMAGE_DEB_X64_SUFFIX: "" + CI_IMAGE_DEB_ARM64: v46542806-c7a4a6be + CI_IMAGE_DEB_ARM64_SUFFIX: "" + CI_IMAGE_DEB_ARMHF: v46542806-c7a4a6be + CI_IMAGE_DEB_ARMHF_SUFFIX: "" + CI_IMAGE_DD_AGENT_TESTING: v46542806-c7a4a6be + CI_IMAGE_DD_AGENT_TESTING_SUFFIX: "" + CI_IMAGE_DOCKER_X64: v46542806-c7a4a6be + CI_IMAGE_DOCKER_X64_SUFFIX: "" + CI_IMAGE_DOCKER_ARM64: v46542806-c7a4a6be + CI_IMAGE_DOCKER_ARM64_SUFFIX: "" + CI_IMAGE_GITLAB_AGENT_DEPLOY: v46542806-c7a4a6be + CI_IMAGE_GITLAB_AGENT_DEPLOY_SUFFIX: "" + CI_IMAGE_LINUX_GLIBC_2_17_X64: v46542806-c7a4a6be + CI_IMAGE_LINUX_GLIBC_2_17_X64_SUFFIX: "" + CI_IMAGE_LINUX_GLIBC_2_23_ARM64: v46542806-c7a4a6be + CI_IMAGE_LINUX_GLIBC_2_23_ARM64_SUFFIX: "" + CI_IMAGE_SYSTEM_PROBE_X64: v46542806-c7a4a6be + CI_IMAGE_SYSTEM_PROBE_X64_SUFFIX: "" + CI_IMAGE_SYSTEM_PROBE_ARM64: v46542806-c7a4a6be + CI_IMAGE_SYSTEM_PROBE_ARM64_SUFFIX: "" + CI_IMAGE_RPM_X64: v46542806-c7a4a6be + CI_IMAGE_RPM_X64_SUFFIX: "" + CI_IMAGE_RPM_ARM64: v46542806-c7a4a6be + CI_IMAGE_RPM_ARM64_SUFFIX: "" + CI_IMAGE_RPM_ARMHF: v46542806-c7a4a6be + CI_IMAGE_RPM_ARMHF_SUFFIX: "" + CI_IMAGE_WIN_1809_X64: v46542806-c7a4a6be + CI_IMAGE_WIN_1809_X64_SUFFIX: "" + CI_IMAGE_WIN_LTSC2022_X64: v46542806-c7a4a6be + CI_IMAGE_WIN_LTSC2022_X64_SUFFIX: "" + + DATADOG_AGENT_EMBEDDED_PATH: /opt/datadog-agent/embedded + DEB_GPG_KEY_ID: c0962c7d + DEB_GPG_KEY_NAME: "Datadog, Inc. APT key" + RPM_GPG_KEY_ID: b01082d3 + RPM_GPG_KEY_NAME: "Datadog, Inc. RPM key" + DOCKER_REGISTRY_URL: docker.io + KITCHEN_INFRASTRUCTURE_FLAKES_RETRY: 2 + CLANG_LLVM_VER: 12.0.1 + KERNEL_MATRIX_TESTING_X86_AMI_ID: "ami-013ea43cbe85107c0" + KERNEL_MATRIX_TESTING_ARM_AMI_ID: "ami-02fbd245475d6a63d" + RUN_E2E_TESTS: "auto" # Should be "off", "auto" or "on" it will change the trigger condition for new-e2e tests on branch != main + RUN_KMT_TESTS: "auto" # Should be "auto" or "on". "on" forces all Kernel Matrix Testing jobs to run. + RUN_UNIT_TESTS: "auto" # Should be "auto", "on", "off" it will change the trigger condition for unit tests on branch != main + # skip known flaky tests by default + GO_TEST_SKIP_FLAKE: "true" + + # Start aws ssm variables + # They must be defined as environment variables in the GitLab CI/CD settings, to ease rotation if needed + AGENT_QA_PROFILE: ci.datadog-agent.agent-qa-profile # agent-devx-infra + API_KEY_ORG2: ci.datadog-agent.datadog_api_key_org2 # agent-devx-infra + API_KEY_DDDEV: ci.datadog-agent.datadog_api_key # agent-devx-infra + APP_KEY_ORG2: ci.datadog-agent.datadog_app_key_org2 # agent-devx-infra + CHANGELOG_COMMIT_SHA: ci.datadog-agent.gitlab_changelog_commit_sha # agent-devx-infra + CHOCOLATEY_API_KEY: ci.datadog-agent.chocolatey_api_key # windows-agent + CODECOV_TOKEN: ci.datadog-agent.codecov_token # agent-devx-infra + DEB_GPG_KEY: ci.datadog-agent.deb_signing_private_key_${DEB_GPG_KEY_ID} # agent-delivery + DEB_SIGNING_PASSPHRASE: ci.datadog-agent.deb_signing_key_passphrase_${DEB_GPG_KEY_ID} # agent-delivery + DOCKER_REGISTRY_LOGIN: ci.datadog-agent.docker_hub_login # container-integrations + DOCKER_REGISTRY_PWD: ci.datadog-agent.docker_hub_pwd # container-integrations + E2E_TESTS_API_KEY: ci.datadog-agent.e2e_tests_api_key # agent-devx-loops + E2E_TESTS_APP_KEY: ci.datadog-agent.e2e_tests_app_key # agent-devx-loops + E2E_TESTS_RC_KEY: ci.datadog-agent.e2e_tests_rc_key # agent-devx-loops + E2E_TESTS_AZURE_CLIENT_ID: ci.datadog-agent.e2e_tests_azure_client_id # agent-devx-loops + E2E_TESTS_AZURE_CLIENT_SECRET: ci.datadog-agent.e2e_tests_azure_client_secret # agent-devx-loops + E2E_TESTS_AZURE_TENANT_ID: ci.datadog-agent.e2e_tests_azure_tenant_id # agent-devx-loops + E2E_TESTS_AZURE_SUBSCRIPTION_ID: ci.datadog-agent.e2e_tests_azure_subscription_id # agent-devx-loops + E2E_TESTS_GCP_CREDENTIALS: ci.datadog-agent.e2e_tests_gcp_credentials # agent-devx-loops + E2E_PULUMI_CONFIG_PASSPHRASE: ci.datadog-agent.pulumi_password # agent-devx-loops + KITCHEN_EC2_SSH_KEY: ci.datadog-agent.aws_ec2_kitchen_ssh_key # agent-devx-loops + KITCHEN_AZURE_CLIENT_ID: ci.datadog-agent.azure_kitchen_client_id # agent-devx-loops + KITCHEN_AZURE_CLIENT_SECRET: ci.datadog-agent.azure_kitchen_client_secret # agent-devx-loops + KITCHEN_AZURE_SUBSCRIPTION_ID: ci.datadog-agent.azure_kitchen_subscription_id # agent-devx-loops + KITCHEN_AZURE_TENANT_ID: ci.datadog-agent.azure_kitchen_tenant_id # agent-devx-loops + GITHUB_PR_COMMENTER_APP_KEY: pr-commenter.github_app_key # agent-devx-infra + GITHUB_PR_COMMENTER_INTEGRATION_ID: pr-commenter.github_integration_id # agent-devx-infra + GITHUB_PR_COMMENTER_INSTALLATION_ID: pr-commenter.github_installation_id # agent-devx-infra + GITLAB_SCHEDULER_TOKEN: ci.datadog-agent.gitlab_pipelines_scheduler_token # ci-cd + GITLAB_READ_API_TOKEN: ci.datadog-agent.gitlab_read_api_token # ci-cd + GITLAB_FULL_API_TOKEN: ci.datadog-agent.gitlab_full_api_token # ci-cd + INSTALL_SCRIPT_API_KEY: ci.agent-linux-install-script.datadog_api_key_2 # agent-delivery + JIRA_READ_API_TOKEN: ci.datadog-agent.jira_read_api_token # agent-devx-infra + AGENT_GITHUB_APP_ID: ci.datadog-agent.platform-github-app-id # agent-devx-infra + AGENT_GITHUB_INSTALLATION_ID: ci.datadog-agent.platform-github-app-installation-id # agent-devx-infra + AGENT_GITHUB_KEY: ci.datadog-agent.platform-github-app-key # agent-devx-infra + MACOS_GITHUB_APP_ID: ci.datadog-agent.macos_github_app_id # agent-devx-infra + MACOS_GITHUB_INSTALLATION_ID: ci.datadog-agent.macos_github_installation_id # agent-devx-infra + MACOS_GITHUB_KEY: ci.datadog-agent.macos_github_key_b64 # agent-devx-infra + MACOS_GITHUB_APP_ID_2: ci.datadog-agent.macos_github_app_id_2 # agent-devx-infra + MACOS_GITHUB_INSTALLATION_ID_2: ci.datadog-agent.macos_github_installation_id_2 # agent-devx-infra + MACOS_GITHUB_KEY_2: ci.datadog-agent.macos_github_key_b64_2 # agent-devx-infra + RPM_GPG_KEY: ci.datadog-agent.rpm_signing_private_key_${RPM_GPG_KEY_ID} # agent-delivery + RPM_SIGNING_PASSPHRASE: ci.datadog-agent.rpm_signing_key_passphrase_${RPM_GPG_KEY_ID} # agent-delivery + SLACK_AGENT_CI_TOKEN: ci.datadog-agent.slack_agent_ci_token # agent-devx-infra + SMP_ACCOUNT_ID: ci.datadog-agent.single-machine-performance-account-id # single-machine-performance + SMP_AGENT_TEAM_ID: ci.datadog-agent.single-machine-performance-agent-team-id # single-machine-performance + SMP_API: ci.datadog-agent.single-machine-performance-api # single-machine-performance + SMP_BOT_ACCESS_KEY: ci.datadog-agent.single-machine-performance-bot-access-key # single-machine-performance + SMP_BOT_ACCESS_KEY_ID: ci.datadog-agent.single-machine-performance-bot-access-key-id # single-machine-performance + SSH_KEY: ci.datadog-agent.ssh_key # system-probe + SSH_KEY_RSA: ci.datadog-agent.ssh_key_rsa # agent-devx-loops + SSH_PUBLIC_KEY_RSA: ci.datadog-agent.ssh_public_key_rsa # agent-devx-loops + VCPKG_BLOB_SAS_URL: ci.datadog-agent-buildimages.vcpkg_blob_sas_url # windows-agent + WINGET_PAT: ci.datadog-agent.winget_pat # windows-agent + # End aws ssm variables + + # Start vault variables + AGENT_API_KEY_ORG2: agent-api-key-org-2 # agent-devx-infra + AGENT_APP_KEY_ORG2: agent-ci-app-key-org-2 # agent-devx-infra + AGENT_GITHUB_APP: agent-github-app # agent-devx-infra + AGENT_QA_E2E: agent-qa-e2e # agent-devx-loops + ATLASSIAN_WRITE: atlassian-write # agent-devx-infra + DOCKER_REGISTRY_RO: dockerhub-readonly # agent-delivery + GITLAB_TOKEN: gitlab-token # agent-devx-infra + INSTALL_SCRIPT_API_KEY_ORG2: install-script-api-key-org-2 # agent-devx-infra + MACOS_GITHUB_APP_1: macos-github-app-one # agent-devx-infra + MACOS_GITHUB_APP_2: macos-github-app-two # agent-devx-infra + SLACK_AGENT: slack-agent-ci # agent-devx-infra + # End vault variables + + DD_PKG_VERSION: "latest" + + # Job stage attempts (see https://docs.gitlab.com/ee/ci/runners/configure_runners.html#job-stages-attempts) + ARTIFACT_DOWNLOAD_ATTEMPTS: 2 + EXECUTOR_JOB_SECTION_ATTEMPTS: 2 + GET_SOURCES_ATTEMPTS: 2 + RESTORE_CACHE_ATTEMPTS: 2 + # Feature flags + FF_SCRIPT_SECTIONS: 1 # Prevent multiline scripts log collapsing, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3392 + FF_KUBERNETES_HONOR_ENTRYPOINT: true # Honor the entrypoint in the Docker image when running Kubernetes jobs \ No newline at end of file diff --git a/tasks/update_go.py b/tasks/update_go.py index 9794f8df5b82c..29eec6ce4374c 100644 --- a/tasks/update_go.py +++ b/tasks/update_go.py @@ -49,7 +49,7 @@ def go_version(_): help={ "version": "The version of Go to use", "image_tag": "Tag from buildimages with format v_", - "test_version": "Whether the image is a test image or not", + "test": "Whether the image is a test image or not", "warn": "Don't exit in case of matching error, just warn.", "release_note": "Whether to create a release note or not. The default behaviour is to create a release note", "include_otel_modules": "Whether to update the version in go.mod files used by otel.", @@ -59,7 +59,7 @@ def update_go( ctx: Context, version: str, image_tag: str | None = None, - test_version: bool = True, + test: bool = True, warn: bool = False, release_note: bool = True, include_otel_modules: bool = False, @@ -82,7 +82,7 @@ def update_go( if image_tag: try: - update_gitlab_config(".gitlab-ci.yml", image_tag, test_version=test_version) + update_gitlab_config(".gitlab-ci.yml", image_tag, test=test) except RuntimeError as e: if warn: print(color_message(f"WARNING: {str(e)}", "orange")) @@ -90,7 +90,7 @@ def update_go( raise try: - update_circleci_config(".circleci/config.yml", image_tag, test_version=test_version) + update_circleci_config(".circleci/config.yml", image_tag, test=test) except RuntimeError as e: if warn: print(color_message(f"WARNING: {str(e)}", "orange")) diff --git a/tasks/winbuildscripts/Generate-Chocolatey-Package.ps1 b/tasks/winbuildscripts/Generate-Chocolatey-Package.ps1 index 6bebdf98db105..9780b4a3a4103 100644 --- a/tasks/winbuildscripts/Generate-Chocolatey-Package.ps1 +++ b/tasks/winbuildscripts/Generate-Chocolatey-Package.ps1 @@ -2,7 +2,11 @@ Param( [Parameter(Mandatory=$true,Position=0)] [ValidateSet("offline", "online")] [String] - $installMethod + $installMethod, + + [Parameter(Mandatory=$false,Position=1)] + [String] + $msiDirectory ) $ErrorActionPreference = 'Stop'; @@ -15,12 +19,12 @@ $env:chocolateyUseWindowsCompression = 'true'; Invoke-Expression ((New-Object Sy pip3 install -r requirements.txt $outputDirectory = "c:\mnt\build-out" -$rawAgentVersion = (inv agent.version) +$rawAgentVersion = (inv agent.version --url-safe --major-version 7) $copyright = "Datadog {0}" -f (Get-Date).Year $releasePattern = "(\d+\.\d+\.\d+)" $releaseCandidatePattern = "(\d+\.\d+\.\d+)-rc\.(\d+)" -$develPattern = "(\d+\.\d+\.\d+)-devel\+git\.\d+\.(.+)" +$develPattern = "(\d+\.\d+\.\d+)-devel\.git\.\d+\.(.+)" $nuspecFile = "c:\mnt\chocolatey\datadog-agent-online.nuspec" $licensePath = "c:\mnt\chocolatey\tools-online\LICENSE.txt" @@ -61,25 +65,24 @@ Invoke-WebRequest -Uri "https://raw.githubusercontent.com/DataDog/datadog-agent/ Write-Host "Generating Chocolatey $installMethod package version $agentVersion in $outputDirectory" -Write-Host ("Downloading {0}" -f $url) -$statusCode = -1 -try { - $tempMsi = "$(Get-Location)\ddagent.msi" - Remove-Item $tempMsi -ErrorAction Ignore - (New-Object net.webclient).Downloadfile($url, $tempMsi) - $checksum = (Get-FileHash $tempMsi -Algorithm SHA256).Hash - Remove-Item $tempMsi -} -catch { - Write-Host "Could not generate checksum for package $($url): $($_)" - exit 4 -} - if (!(Test-Path $outputDirectory)) { New-Item -ItemType Directory -Path $outputDirectory } if ($installMethod -eq "online") { + try { + $tempMsi = Join-Path -Path "$msiDirectory" "datadog-agent-$rawAgentVersion-1-x86_64.msi" + if (!(Test-Path $tempMsi)) { + Write-Host "Error: Could not find MSI file in $tempMsi" + Get-ChildItem "$msiDirectory" + exit 1 + } + $checksum = (Get-FileHash $tempMsi -Algorithm SHA256).Hash + } + catch { + Write-Host "Error: Could not generate checksum for package $($tempMsi): $($_)" + exit 4 + } # Set the $url in the install script (Get-Content $installScript).replace('$__url_from_ci__', '"' + $url + '"').replace('$__checksum_from_ci__', '"' + $checksum + '"') | Set-Content $installScript } diff --git a/tasks/winbuildscripts/buildlocal.bat b/tasks/winbuildscripts/buildlocal.bat index 6ceae806c8351..c2aaab3b4bfa8 100644 --- a/tasks/winbuildscripts/buildlocal.bat +++ b/tasks/winbuildscripts/buildlocal.bat @@ -1,14 +1,12 @@ @echo RELEASE_VERSION %RELEASE_VERSION% @echo MAJOR_VERSION %MAJOR_VERSION% -@echo PY_RUNTIMES %PY_RUNTIMES% REM set up variables for local build. REM assumes attempting to build A7/x64 nightly -REM assumes target directory is mounted in the container +REM assumes target directory is mounted in the container REM (vs. copied in as in CI build) if NOT DEFINED RELEASE_VERSION set RELEASE_VERSION=nightly if NOT DEFINED MAJOR_VERSION set MAJOR_VERSION=7 -if NOT DEFINED PY_RUNTIMES set PY_RUNTIMES="3" if NOT DEFINED CI_JOB_ID set CI_JOB_ID=1 if NOT DEFINED TARGET_ARCH set TARGET_ARCH=x64 diff --git a/tasks/winbuildscripts/chocopack.bat b/tasks/winbuildscripts/chocopack.bat index 60811a681ea11..df8915ae14698 100644 --- a/tasks/winbuildscripts/chocopack.bat +++ b/tasks/winbuildscripts/chocopack.bat @@ -2,7 +2,7 @@ if not exist c:\mnt\ goto nomntdir @echo c:\mnt found, continuing -Powershell -C "C:\mnt\tasks\winbuildscripts\Generate-Chocolatey-Package.ps1 %1" || exit /b 1 +Powershell -C "C:\mnt\tasks\winbuildscripts\Generate-Chocolatey-Package.ps1 %1 %2" || exit /b 1 goto :EOF :nomntdir diff --git a/tasks/winbuildscripts/integrationtests.bat b/tasks/winbuildscripts/integrationtests.bat index 504111ffce3d7..9264cefeb7dea 100644 --- a/tasks/winbuildscripts/integrationtests.bat +++ b/tasks/winbuildscripts/integrationtests.bat @@ -3,9 +3,6 @@ if not exist c:\mnt\ goto nomntdir @echo c:\mnt found, continuing @echo PARAMS %* -@echo PY_RUNTIMES %PY_RUNTIMES% - -if NOT DEFINED PY_RUNTIMES set PY_RUNTIMES=%~1 set TEST_ROOT=c:\test-root mkdir %TEST_ROOT%\datadog-agent diff --git a/tasks/winbuildscripts/integrationtests.ps1 b/tasks/winbuildscripts/integrationtests.ps1 index a08cd61a61fd3..4a83f7252270c 100644 --- a/tasks/winbuildscripts/integrationtests.ps1 +++ b/tasks/winbuildscripts/integrationtests.ps1 @@ -12,7 +12,7 @@ $UT_BUILD_ROOT=(Get-Location).Path $Env:PATH="$UT_BUILD_ROOT\dev\lib;$Env:GOPATH\bin;$Env:Python3_ROOT_DIR;$Env:Python3_ROOT_DIR\Scripts;$Env:PATH" & inv -e deps -& .\tasks\winbuildscripts\pre-go-build.ps1 -PythonRuntimes "$Env:PY_RUNTIMES" +& .\tasks\winbuildscripts\pre-go-build.ps1 & inv -e install-tools & inv -e integration-tests diff --git a/tasks/winbuildscripts/lint.bat b/tasks/winbuildscripts/lint.bat index 8d023e952014d..ae5677fd26d40 100644 --- a/tasks/winbuildscripts/lint.bat +++ b/tasks/winbuildscripts/lint.bat @@ -3,9 +3,6 @@ if not exist c:\mnt\ goto nomntdir @echo c:\mnt found, continuing @echo PARAMS %* -@echo PY_RUNTIMES %PY_RUNTIMES% - -if NOT DEFINED PY_RUNTIMES set PY_RUNTIMES=%~1 set TEST_ROOT=c:\buildroot diff --git a/tasks/winbuildscripts/lint.ps1 b/tasks/winbuildscripts/lint.ps1 index aac4f363ba201..f749316dcee40 100644 --- a/tasks/winbuildscripts/lint.ps1 +++ b/tasks/winbuildscripts/lint.ps1 @@ -9,7 +9,7 @@ $LINT_ROOT=(Get-Location).Path $Env:PATH="$LINT_ROOT\dev\lib;$Env:GOPATH\bin;$Env:Python3_ROOT_DIR;$Env:Python3_ROOT_DIR\Scripts;$Env:PATH;$Env:VSTUDIO_ROOT\VC\Tools\Llvm\bin" & inv -e deps -& .\tasks\winbuildscripts\pre-go-build.ps1 -PythonRuntimes "$Env:PY_RUNTIMES" +& .\tasks\winbuildscripts\pre-go-build.ps1 & inv -e rtloader.format --raise-if-changed $err = $LASTEXITCODE diff --git a/tasks/winbuildscripts/secagent.bat b/tasks/winbuildscripts/secagent.bat index f6a6c30aeed58..532e971287284 100644 --- a/tasks/winbuildscripts/secagent.bat +++ b/tasks/winbuildscripts/secagent.bat @@ -3,10 +3,6 @@ if not exist c:\mnt\ goto nomntdir @echo c:\mnt found, continuing @echo PARAMS %* -@echo PY_RUNTIMES %PY_RUNTIMES% - -if NOT DEFINED PY_RUNTIMES set PY_RUNTIMES=%~1 - set BUILD_ROOT=c:\buildroot mkdir %BUILD_ROOT%\datadog-agent @@ -21,5 +17,5 @@ call %BUILD_ROOT%\datadog-agent\tasks\winbuildscripts\extract-modcache.bat %BUIL Powershell -C "%BUILD_ROOT%\datadog-agent\tasks\winbuildscripts\secagent.ps1" || exit /b 5 REM copy resulting packages to expected location for collection by gitlab. -if not exist c:\mnt\test\kitchen\site-cookbooks\dd-security-agent-check\files\tests\ mkdir c:\mnt\test\kitchen\site-cookbooks\dd-security-agent-check\files\tests\ || exit /b 6 -xcopy /e/s/q %BUILD_ROOT%\datadog-agent\test\kitchen\site-cookbooks\dd-security-agent-check\files\tests\*.* c:\mnt\test\kitchen\site-cookbooks\dd-security-agent-check\files\tests\ || exit /b 7 +if not exist c:\mnt\test\new-e2e\tests\security-agent-functional\artifacts\ mkdir c:\mnt\test\new-e2e\tests\security-agent-functional\artifacts\ || exit /b 6 +xcopy /e/s/q %BUILD_ROOT%\datadog-agent\test\new-e2e\tests\security-agent-functional\artifacts\*.* c:\mnt\test\new-e2e\tests\security-agent-functional\artifacts\ || exit /b 7 diff --git a/tasks/winbuildscripts/secagent.ps1 b/tasks/winbuildscripts/secagent.ps1 index 6f60f1ed5961a..0ff6a448cf737 100644 --- a/tasks/winbuildscripts/secagent.ps1 +++ b/tasks/winbuildscripts/secagent.ps1 @@ -21,7 +21,7 @@ if ($Env:TARGET_ARCH -eq "x86") { $archflag = "x86" } -& inv -e security-agent.kitchen-prepare --skip-linters +& inv -e security-agent.e2e-prepare-win $err = $LASTEXITCODE if($err -ne 0){ diff --git a/tasks/winbuildscripts/sysprobe.bat b/tasks/winbuildscripts/sysprobe.bat index 585f4283198fe..4281fa5028a93 100644 --- a/tasks/winbuildscripts/sysprobe.bat +++ b/tasks/winbuildscripts/sysprobe.bat @@ -3,9 +3,6 @@ if not exist c:\mnt\ goto nomntdir @echo c:\mnt found, continuing @echo PARAMS %* -@echo PY_RUNTIMES %PY_RUNTIMES% - -if NOT DEFINED PY_RUNTIMES set PY_RUNTIMES=%~1 set BUILD_ROOT=c:\buildroot diff --git a/tasks/winbuildscripts/unitlocal.bat b/tasks/winbuildscripts/unitlocal.bat index 10fc219deb4b7..a2aeb4e293de1 100644 --- a/tasks/winbuildscripts/unitlocal.bat +++ b/tasks/winbuildscripts/unitlocal.bat @@ -1,7 +1,4 @@ @echo PARAMS %* -@echo PY_RUNTIMES %PY_RUNTIMES% - -if NOT DEFINED PY_RUNTIMES set PY_RUNTIMES=%~1 cd \dev\go\src\github.com\DataDog\datadog-agent diff --git a/tasks/winbuildscripts/unittests.bat b/tasks/winbuildscripts/unittests.bat index 9673769c4c329..2a62a413b6511 100644 --- a/tasks/winbuildscripts/unittests.bat +++ b/tasks/winbuildscripts/unittests.bat @@ -3,9 +3,6 @@ if not exist c:\mnt\ goto nomntdir @echo c:\mnt found, continuing @echo PARAMS %* -@echo PY_RUNTIMES %PY_RUNTIMES% - -if NOT DEFINED PY_RUNTIMES set PY_RUNTIMES=%~1 set TEST_ROOT=c:\test-root mkdir %TEST_ROOT%\datadog-agent diff --git a/tasks/windows_resources.py b/tasks/windows_resources.py index 6e8ac75b0735f..3e4493a222b73 100644 --- a/tasks/windows_resources.py +++ b/tasks/windows_resources.py @@ -2,7 +2,6 @@ from invoke import task -from tasks.libs.common.utils import get_win_py_runtime_var from tasks.libs.releasing.version import get_version_numeric_only MESSAGESTRINGS_MC_PATH = "pkg/util/winutil/messagestrings/messagestrings.mc" @@ -48,12 +47,11 @@ def build_rc(ctx, rc_file, vars=None, out=None): def versioninfo_vars(ctx, major_version='7'): - py_runtime_var = get_win_py_runtime_var() ver = get_version_numeric_only(ctx, major_version=major_version) build_maj, build_min, build_patch = ver.split(".") return { - f'{py_runtime_var}': 1, + 'PY3_RUNTIME': 1, 'MAJ_VER': build_maj, 'MIN_VER': build_min, 'PATCH_VER': build_patch, diff --git a/test/integration/corechecks/docker/main_test.go b/test/integration/corechecks/docker/main_test.go index 5d2d8a73ebff5..643e6f6eb6d7f 100644 --- a/test/integration/corechecks/docker/main_test.go +++ b/test/integration/corechecks/docker/main_test.go @@ -87,7 +87,7 @@ func TestMain(m *testing.M) { var lastRunResult int var retryCount int - store, err := setup() + store, taggerComp, err := setup() if err != nil { log.Infof("Test setup failed: %v", err) tearOffAndExit(1) @@ -98,7 +98,7 @@ func TestMain(m *testing.M) { case <-retryTicker.C: retryCount++ log.Infof("Starting run %d", retryCount) - lastRunResult = doRun(m, store) + lastRunResult = doRun(m, store, taggerComp) if lastRunResult == 0 { tearOffAndExit(0) } @@ -116,12 +116,12 @@ type testDeps struct { } // Called before for first test run: compose up -func setup() (workloadmeta.Component, error) { +func setup() (workloadmeta.Component, tagger.Component, error) { // Setup global conf pkgconfigsetup.Datadog().SetConfigType("yaml") err := pkgconfigsetup.Datadog().ReadConfig(strings.NewReader(datadogCfgString)) if err != nil { - return nil, err + return nil, nil, err } env.SetFeaturesNoCleanup(env.Docker) @@ -151,15 +151,15 @@ func setup() (workloadmeta.Component, error) { output, err := compose.Start() if err != nil { log.Errorf("Compose didn't start properly: %s", string(output)) - return nil, err + return nil, nil, err } } - return store, nil + return store, deps.TaggerComp, nil } // Reset the state and trigger a new run -func doRun(m *testing.M, store workloadmeta.Component) int { - factory := docker.Factory(store) +func doRun(m *testing.M, store workloadmeta.Component, tagger tagger.Component) int { + factory := docker.Factory(store, tagger) checkFactory, _ := factory.Get() dockerCheck = checkFactory() diff --git a/test/integration/listeners/docker/docker_listener_test.go b/test/integration/listeners/docker/docker_listener_test.go index 33049fe225c3b..73cc531323f26 100644 --- a/test/integration/listeners/docker/docker_listener_test.go +++ b/test/integration/listeners/docker/docker_listener_test.go @@ -52,6 +52,7 @@ type DockerListenerTestSuite struct { m sync.RWMutex wmeta workloadmeta.Component telemetryStore *acTelemetry.Store + tagger tagger.Component } type deps struct { @@ -95,6 +96,7 @@ func (suite *DockerListenerTestSuite) SetupSuite() { suite.wmeta = deps.WMeta suite.telemetryStore = acTelemetry.NewStore(deps.Telemetry) suite.dockerutil, err = docker.GetDockerUtil() + suite.tagger = deps.Tagger require.Nil(suite.T(), err, "can't connect to docker") suite.compose = utils.ComposeConf{ @@ -108,7 +110,12 @@ func (suite *DockerListenerTestSuite) TearDownSuite() { } func (suite *DockerListenerTestSuite) SetupTest() { - dl, err := listeners.NewContainerListener(&pkgconfigsetup.Listeners{}, optional.NewOption(suite.wmeta), suite.telemetryStore) + dl, err := listeners.NewContainerListener(listeners.ServiceListernerDeps{ + Config: &pkgconfigsetup.Listeners{}, + Wmeta: optional.NewOption(suite.wmeta), + Telemetry: suite.telemetryStore, + Tagger: suite.tagger, + }) if err != nil { panic(err) } diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/.gitignore b/test/kitchen/site-cookbooks/dd-security-agent-check/.gitignore deleted file mode 100644 index 085fb2292683d..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -.vagrant -Berksfile.lock -*~ -*# -.#* -\#*# -.*.sw[a-z] -*.un~ -/cookbooks - -# Bundler -Gemfile.lock -bin/* -.bundle/* - -# Exclude test files generated by running inv -e security-agent.kitchen-prepare -files/clang-bpf -files/llc-bpf -files/ebpf_bytecode/* -files/tests/testsuite -files/tests/stresssuite -files/gotestsum -files/test2json diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/Berksfile b/test/kitchen/site-cookbooks/dd-security-agent-check/Berksfile deleted file mode 100644 index c4bb297b7275b..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/Berksfile +++ /dev/null @@ -1,3 +0,0 @@ -site :opscode - -metadata diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/Gemfile b/test/kitchen/site-cookbooks/dd-security-agent-check/Gemfile deleted file mode 100644 index 01b5db30b2f16..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/Gemfile +++ /dev/null @@ -1,4 +0,0 @@ -source 'https://rubygems.org' - -gem 'bundler', '~> 2.2.17' -gem 'berkshelf' diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/README.md b/test/kitchen/site-cookbooks/dd-security-agent-check/README.md deleted file mode 100644 index 98904538da9e6..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# dd-security-agent-check - -Copy the runtime security agent functional tests and executes them. diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/attributes/default.rb b/test/kitchen/site-cookbooks/dd-security-agent-check/attributes/default.rb deleted file mode 100644 index 35381331f78bf..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/attributes/default.rb +++ /dev/null @@ -1 +0,0 @@ -default['common']['work_dir'] = '/tmp/security-agent' diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/chefignore b/test/kitchen/site-cookbooks/dd-security-agent-check/chefignore deleted file mode 100644 index fafc53145500c..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/chefignore +++ /dev/null @@ -1,95 +0,0 @@ -# Put files/directories that should be ignored in this file when uploading -# or sharing to the community site. -# Lines that start with '# ' are comments. - -# OS generated files # -###################### -.DS_Store -Icon? -nohup.out -ehthumbs.db -Thumbs.db - -# SASS # -######## -.sass-cache - -# EDITORS # -########### -\#* -.#* -*~ -*.sw[a-z] -*.bak -REVISION -TAGS* -tmtags -*_flymake.* -*_flymake -*.tmproj -.project -.settings -mkmf.log - -## COMPILED ## -############## -a.out -*.pyc -*.so -*.com -*.class -*.dll -## *.exe need exe files to be copied (testsuite.exe) -*/rdoc/ - -# Testing # -########### -.watchr -.rspec -spec/* -spec/fixtures/* -test/* -features/* -Guardfile -Procfile - -# SCM # -####### -.git -*/.git -.gitignore -.gitmodules -.gitconfig -.gitattributes -.svn -*/.bzr/* -*/.hg/* -*/.svn/* - -# Berkshelf # -############# -Berksfile -Berksfile.lock -cookbooks/* -tmp - -# Cookbooks # -############# -CONTRIBUTING -CHANGELOG* - -# Strainer # -############ -Colanderfile -Strainerfile -.colander -.strainer - -# Vagrant # -########### -.vagrant -Vagrantfile - -# Travis # -########## -.travis.yml diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/files/windows/decompress_merge_module.ps1 b/test/kitchen/site-cookbooks/dd-security-agent-check/files/windows/decompress_merge_module.ps1 deleted file mode 100644 index 13d2c62887c7d..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/files/windows/decompress_merge_module.ps1 +++ /dev/null @@ -1,61 +0,0 @@ -param( - [Parameter(Mandatory = $true)][string] $file, - [Parameter(Mandatory = $true)][string] $targetDir - ) - - -[Reflection.Assembly]::LoadFrom("$($Env:WIX)\Microsoft.Deployment.WindowsInstaller.dll") - -write-host "Extracting files from merge module: "$file - -if(![IO.Directory]::Exists($targetDir)) { new-item -type directory -path $targetDir } - -$cabFile = join-path $targetDir "temp.cab" -if([IO.File]::Exists($cabFile)) { remove-item $cabFile } - -$db = new-object Microsoft.Deployment.WindowsInstaller.DataBase($file, [Microsoft.Deployment.WindowsInstaller.DataBaseOpenMode]::ReadOnly) -$view = $db.OpenView("SELECT `Name`,`Data` FROM _Streams WHERE `Name`= 'MergeModule.CABinet'") -$view.Execute() -$record = $view.Fetch() -$record.GetStream(2, $cabFile) -$view.Dispose() - -& "$($Env:WINDIR)\system32\expand" -F:* $cabFile $targetDir - -remove-item $cabFile - -$extractedFiles = get-childitem $targetDir -$hashFiles = @{} -foreach($extracted in $extractedFiles) -{ - try - { - $longName = $db.ExecuteScalar("SELECT `FileName` FROM `File` WHERE `File`='{0}'", $extracted.Name) - } - catch - { - write-host "$($extracted.Name) is not in the MSM file" - } - - if($longName) - { - $longName = $LongName.SubString($LongName.IndexOf("|") + 1) - Write-host $longName - - #There are duplicates in the - if($hashFiles.Contains($longName)) - { - write-host "Removing duplicate of $longName" - remove-item $extracted.FullName - } - else - { - write-host "Rename $($extracted.Name) to $longName" - $hashFiles[$longName] = $extracted - $targetFilePath = join-path $targetDir $longName - if([IO.File]::Exists($targetFilePath)) {remove-item $targetFilePath} - rename-item $extracted.FullName -NewName $longName - } - } -} -$db.Dispose() diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/metadata.rb b/test/kitchen/site-cookbooks/dd-security-agent-check/metadata.rb deleted file mode 100644 index ac6fd846f69db..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/metadata.rb +++ /dev/null @@ -1,9 +0,0 @@ -name "dd-security-agent-check" -maintainer "Datadog" -description "Test the runtime security agent" -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version "0.1.0" - -depends 'datadog' -depends 'docker' -depends 'selinux' \ No newline at end of file diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/default.rb b/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/default.rb deleted file mode 100644 index 83902a61413fd..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/default.rb +++ /dev/null @@ -1,13 +0,0 @@ -# -# Cookbook Name:: dd-security-agent-check -# Recipe:: default -# -# Copyright (C) 2020-present Datadog -# - - -if platform?('windows') - include_recipe "::windows" -else - include_recipe "::linux" -end diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/functional-tests.rb b/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/functional-tests.rb deleted file mode 100644 index 0ffeee6ea2316..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/functional-tests.rb +++ /dev/null @@ -1,244 +0,0 @@ -# -# Cookbook Name:: dd-security-agent-check -# Recipe:: functional-tests -# -# Copyright (C) 2020-present Datadog -# - -cookbook_file "#{node['common']['work_dir']}/tests/testsuite" do - source "tests/testsuite" - mode '755' -end - -if node[:platform] == "amazon" and node[:platform_version] == "2022" - execute "increase /tmp size" do - command "mount -o remount,size=10G /tmp/" - live_stream true - action :run - end -end - -file "#{node['common']['work_dir']}/cws_platform" do - content node[:cws_platform].to_s || "" - mode 644 -end - -remote_directory "#{node['common']['work_dir']}/ebpf_bytecode" do - source 'ebpf_bytecode' - sensitive true - files_owner 'root' - owner 'root' -end - -directory "/opt/datadog-agent/embedded/bin" do - recursive true -end - -cookbook_file "/opt/datadog-agent/embedded/bin/clang-bpf" do - source "clang-bpf" - mode '0744' - action :create -end - -cookbook_file "#{node['common']['work_dir']}/clang-bpf" do - source "clang-bpf" - mode '0744' - action :create -end - -cookbook_file "/opt/datadog-agent/embedded/bin/llc-bpf" do - source "llc-bpf" - mode '0744' - action :create -end - -cookbook_file "#{node['common']['work_dir']}/llc-bpf" do - source "llc-bpf" - mode '0744' - action :create -end - -# Resources for getting test output into the Datadog CI product - -directory "/go/bin" do - recursive true -end - -cookbook_file "/go/bin/gotestsum" do - source "gotestsum" - mode '0744' - action :create -end - -cookbook_file "/go/bin/test2json" do - source "test2json" - mode '0744' - action :create -end - -directory "/tmp/junit" do - recursive true -end - -cookbook_file "/tmp/junit/job_env.txt" do - source "job_env.txt" - mode '0444' - action :create - ignore_failure true -end - -directory "/tmp/testjson" do - recursive true -end - -directory "/tmp/pkgjson" do - recursive true -end - -# End resources for getting test output into the Datadog CI product - -# `/swapfile` doesn't work on Oracle Linux, so we use `/mnt/swapfile` -swap_file '/mnt/swapfile' do - size 2048 -end - -kernel_module 'loop' do - action :load -end - -kernel_module 'veth' do - action :load -end - -# Some functional tests, TestProcessIdentifyInterpreter for example, require python -# Re: the container tests: Python comes with the Dockerfile, Perl needs to be installed manually -if (not ['redhat', 'oracle', 'rocky'].include?(node[:platform])) or node[:platform_version].start_with?("7") - package 'python3' -end - -if not ['redhat', 'suse', 'opensuseleap', 'rocky'].include?(node[:platform]) - if ['ubuntu', 'debian'].include?(node[:platform]) - apt_update - - package 'gnupg' - - package 'unattended-upgrades' do - action :remove - end - end - - if ['ubuntu', 'debian', 'centos'].include?(node[:platform]) - package 'xfsprogs' - end - - if ['oracle'].include?(node[:platform]) - docker_installation_package 'default' do - action :create - setup_docker_repo false - package_name 'docker-engine' - package_options %q|-y| - end - - service 'docker' do - action [ :enable, :start ] - end - elsif ['amazon'].include?(node[:platform]) - docker_installation_package 'default' do - action :create - setup_docker_repo false - package_name 'docker' - package_options %q|-y| - end - - service 'docker' do - action [ :enable, :start ] - end - elsif ['ubuntu'].include?(node[:platform]) - docker_installation_package 'default' do - action :create - setup_docker_repo false - package_name 'docker.io' - end - else - docker_service 'default' do - action [:create, :start] - end - end - - if ['docker', 'docker-fentry'].include?(node[:cws_platform]) - file "#{node['common']['work_dir']}/Dockerfile" do - content <<-EOF - FROM ghcr.io/datadog/apps-cws-centos7:main - - COPY clang-bpf /opt/datadog-agent/embedded/bin/ - COPY llc-bpf /opt/datadog-agent/embedded/bin/ - - CMD sleep 7200 - EOF - action :create - end - - docker_image 'testsuite-img' do - tag 'latest' - source node['common']['work_dir'] - action :build - end - - docker_container 'docker-testsuite' do - repo 'testsuite-img' - tag 'latest' - cap_add ['SYS_ADMIN', 'SYS_RESOURCE', 'SYS_PTRACE', 'NET_ADMIN', 'IPC_LOCK', 'ALL'] - volumes [ - # security-agent misc - '/tmp/security-agent:/tmp/security-agent', - # HOST_* paths - '/proc:/host/proc', - '/etc:/host/etc', - '/sys:/host/sys', - # os-release - '/etc/os-release:/host/etc/os-release', - '/usr/lib/os-release:/host/usr/lib/os-release', - # passwd and groups - '/etc/passwd:/etc/passwd', - '/etc/group:/etc/group', - ] - env [ - 'HOST_PROC=/host/proc', - 'HOST_ETC=/host/etc', - 'HOST_SYS=/host/sys', - ] - privileged true - end - - docker_exec 'debug_fs' do - container 'docker-testsuite' - command ['mount', '-t', 'debugfs', 'none', '/sys/kernel/debug'] - end - - for i in 0..7 do - docker_exec 'create_loop' do - container 'docker-testsuite' - command ['bash', '-c', "mknod /dev/loop#{i} b 7 #{i} || true"] - end - end - end -end - -if platform_family?('centos', 'fedora', 'rhel') - selinux_state "SELinux Permissive" do - action :permissive - end -end - -if File.exists?('/sys/kernel/security/lockdown') - file '/sys/kernel/security/lockdown' do - action :create_if_missing - content "integrity" - end -end - -# system-probe common -file "/tmp/color_idx" do - content node[:color_idx].to_s - mode 644 -end diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/linux.rb b/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/linux.rb deleted file mode 100644 index 5040706abd055..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/linux.rb +++ /dev/null @@ -1,10 +0,0 @@ -# -# Cookbook Name:: dd-security-agent-check -# Recipe:: default -# -# Copyright (C) 2020-present Datadog -# -directory "#{node['common']['work_dir']}/tests" do - recursive true -end - \ No newline at end of file diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/stress-tests.rb b/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/stress-tests.rb deleted file mode 100644 index 5eda89ad1be5a..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/stress-tests.rb +++ /dev/null @@ -1,20 +0,0 @@ -# -# Cookbook Name:: dd-security-agent-check -# Recipe:: stress-tests -# -# Copyright (C) 2020-present Datadog -# - -if node['platform_family'] != 'windows' - cookbook_file "#{node['common']['work_dir']}/tests/stresssuite" do - source "tests/stresssuite" - mode '755' - end - - ['polkit', 'unattended-upgrades', 'snapd', 'cron', 'walinuxagent', - 'multipathd', 'rsyslog', 'atd', 'chronyd', 'hv-kvp-daemon'].each do |s| - service s do - action :stop - end - end -end diff --git a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/windows.rb b/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/windows.rb deleted file mode 100644 index 7b957d0e99c5a..0000000000000 --- a/test/kitchen/site-cookbooks/dd-security-agent-check/recipes/windows.rb +++ /dev/null @@ -1,85 +0,0 @@ -require 'json' - -rootdir = value_for_platform( - 'windows' => { 'default' => ::File.join(Chef::Config[:file_cache_path], 'security-agent') }, - 'default' => '/tmp/ci/system-probe' -) - -directory "#{rootdir}/tests" do - recursive true -end - -directory "#{rootdir}/tests/etw" do - recursive true -end - - -cookbook_file "#{rootdir}/tests/testsuite.exe" do - source "tests/testsuite.exe" - mode '755' -end - -cookbook_file "#{rootdir}/tests/etw/testsuite.exe" do - source "tests/etw/testsuite.exe" - mode '755' -end - -# manually install and start the procmon driver -tmp_dir = "#{ENV['USERPROFILE']}\\AppData\\Local\\Temp" -dna_json_path = "#{tmp_dir}\\kitchen\\dna.json" -agentvars = JSON.parse(IO.read(dna_json_path)).fetch('dd-agent-rspec') -driver_path = agentvars.fetch('driver_path') -driver_ver = agentvars.fetch('driver_ver') -driver_msmsha = agentvars.fetch('driver_msmsha') - -remote_path = "https://s3.amazonaws.com/dd-windowsfilter/builds/#{driver_path}/ddprocmoninstall-#{driver_ver}.msm" -remote_file "#{tmp_dir}\\ddprocmon.msm" do - source remote_path - checksum driver_msmsha -end - -remote_file "#{tmp_dir}\\wix311-binaries.zip" do - source "https://github.com/wixtoolset/wix3/releases/download/wix3112rtm/wix311-binaries.zip" -end - - -execute 'wix-extract' do - cwd tmp_dir - command "powershell -C \"Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('wix311-binaries.zip', 'wix');\"" - not_if { ::File.directory?(::File.join(tmp_dir, 'wix')) } -end - -cookbook_file "#{tmp_dir}\\decompress_merge_module.ps1" do - source 'decompress_merge_module.ps1' -end - -execute 'extract driver merge module' do - cwd tmp_dir - live_stream true - environment 'WIX' => "#{tmp_dir}\\wix" - command "powershell -C \".\\decompress_merge_module.ps1 -file ddprocmon.msm -targetDir .\\expanded\"" - not_if { ::File.exist?(::File.join(tmp_dir, 'expanded', 'ddprocmon.msm')) } -end - -if driver_path == "testsigned" - reboot 'now' do - action :nothing - reason 'Cannot continue Chef run without a reboot.' - end - - execute 'enable unsigned drivers' do - command "bcdedit.exe /set testsigning on" - notifies :reboot_now, 'reboot[now]', :immediately - not_if 'bcdedit.exe | findstr "testsigning" | findstr "Yes"' - end -end - -execute 'procmon-driver-install' do - command "powershell -C \"sc.exe create ddprocmon type= kernel binpath= #{tmp_dir}\\expanded\\ddprocmon.sys start= demand\"" - not_if 'sc.exe query ddprocmon' -end - -windows_service 'procmon-driver' do - service_name 'ddprocmon' - action :start -end diff --git a/test/kitchen/test/integration/security-agent-stress/rspec_datadog/security-agent-stress_spec.rb b/test/kitchen/test/integration/security-agent-stress/rspec_datadog/security-agent-stress_spec.rb deleted file mode 100644 index 3c091183b2aa0..0000000000000 --- a/test/kitchen/test/integration/security-agent-stress/rspec_datadog/security-agent-stress_spec.rb +++ /dev/null @@ -1,10 +0,0 @@ -print `cat /etc/os-release` -print `uname -a` - -describe 'successfully run stress test against main' do - it 'displays PASS and returns 0' do - output = `sudo /tmp/security-agent/tests/stresssuite -test.v -duration 120 1>&2` - retval = $? - expect(retval).to eq(0) - end -end diff --git a/test/kitchen/test/integration/security-agent-test/rspec_datadog/kernel_out_spec_helper.rb b/test/kitchen/test/integration/security-agent-test/rspec_datadog/kernel_out_spec_helper.rb deleted file mode 120000 index 08fdb900015b3..0000000000000 --- a/test/kitchen/test/integration/security-agent-test/rspec_datadog/kernel_out_spec_helper.rb +++ /dev/null @@ -1 +0,0 @@ -../../common/rspec_datadog/kernel_out_spec_helper.rb \ No newline at end of file diff --git a/test/kitchen/test/integration/security-agent-test/rspec_datadog/security-agent-test_spec.rb b/test/kitchen/test/integration/security-agent-test/rspec_datadog/security-agent-test_spec.rb deleted file mode 100644 index 6e6deec63c3e6..0000000000000 --- a/test/kitchen/test/integration/security-agent-test/rspec_datadog/security-agent-test_spec.rb +++ /dev/null @@ -1,167 +0,0 @@ -require 'csv' -require 'fileutils' -require 'kernel_out_spec_helper' -require 'open3' -require 'rexml/document' - -print KernelOut.format(`cat /etc/os-release`) -print KernelOut.format(`uname -a`) - -arch = `uname -m`.strip -release = `uname -r`.strip -osr = Hash[*CSV.read("/etc/os-release", col_sep: "=").flatten(1)] -platform = "#{osr["ID"]}-#{osr["VERSION_ID"]}" - -cws_platform = File.read('/tmp/security-agent/cws_platform').strip - -GOLANG_TEST_FAILURE = /FAIL:/ - -def check_output(output, wait_thr, tag="") - test_failures = [] - - puts "Begin Test Output" - output.each_line do |line| - stripped_line = line.strip - puts KernelOut.format(stripped_line, tag) - test_failures << KernelOut.format(stripped_line, tag) if line =~ GOLANG_TEST_FAILURE - end - puts "End Test Output" - - if test_failures.empty? && !wait_thr.value.success? - test_failures << KernelOut.format("Test command exited with status (#{wait_thr.value.exitstatus}) but no failures were captured.", tag) - end - - puts "Test Failures" - puts test_failures.join("\n") -end - -shared_examples "passes" do |bundle, env| - after :context do - # Combine all the /tmp/pkgjson/#{bundle}.json files into one /tmp/testjson/#{bundle}.json file, which is then used to print failed tests at the end of the functional test Gitlab job - print KernelOut.format(`find "/tmp/pkgjson/#{bundle}" -maxdepth 1 -type f -path "*.json" -exec cat >"/tmp/testjson/#{bundle}.json" {} +`) - end - - base_env = { - "CI"=>"true", - "DD_SYSTEM_PROBE_BPF_DIR"=>"/tmp/security-agent/ebpf_bytecode", - "GOVERSION"=>"unknown" - } - final_env = base_env.merge(env) - - testsuite_file_path = "/tmp/security-agent/tests/testsuite" - it "tests" do |ex| - Dir.chdir(File.dirname(testsuite_file_path)) do - output_file_name = "#{bundle}-#{platform}-version-#{release}" - - xmlpath = "/tmp/junit/#{bundle}/#{output_file_name}.xml" - jsonpath = "/tmp/pkgjson/#{bundle}/#{output_file_name}.json" - - # The package name has to be the real path in order to use agent-platform's CODEOWNER parsing downstream - # The junitfiles are uploaded to the Datadog CI Visibility product, and for downloading - # The json files are used to print failed tests at the end of the Gitlab job - # - # The tests are retried if they fail, but only if less than 5 failed - # so that we do not retry the whole testsuite in case of a global failure - gotestsum_test2json_cmd = ["sudo", "-E", - "/go/bin/gotestsum", - "--format", "testname", - "--junitfile", xmlpath, - "--jsonfile", jsonpath, - "--rerun-fails=2", - "--rerun-fails-max-failures=5", - "--raw-command", "--", - "/go/bin/test2json", "-t", "-p", "github.com/DataDog/datadog-agent/pkg/security/tests" - ] - - testsuite_args = ["-status-metrics", "-loglevel=debug", "-test.v", "-test.count=1"] - if bundle == "docker" - testsuite_args.concat(["-env", "docker"]) - gotestsum_test2json_cmd.concat(["docker", "exec", "-e", "DD_SYSTEM_PROBE_BPF_DIR=#{final_env["DD_SYSTEM_PROBE_BPF_DIR"]}", - "docker-testsuite"]) - output_line_tag = "d" - elsif bundle == "ad" - testsuite_args.concat(["-test.run", "(TestActivityDump|TestSecurityProfile)"]) - output_line_tag = "ad" - elsif bundle == "ebpfless" - testsuite_args.concat(["-trace"]) - output_line_tag = "el" - elsif bundle == "ebpfless-no-seccomp" - testsuite_args.concat(["-trace", "-disable-seccomp"]) - output_line_tag = "el" - else - output_line_tag = "h" - end - - gotestsum_test2json_cmd.concat([testsuite_file_path]) - gotestsum_test2json_cmd.concat(testsuite_args) - - Open3.popen2e(final_env, *gotestsum_test2json_cmd) do |_, output, wait_thr| - check_output(output, wait_thr, output_line_tag) - end - - xmldoc = REXML::Document.new(File.read(xmlpath)) - REXML::XPath.each(xmldoc, "//testsuites/testsuite/properties") do |props| - props.add_element("property", { "name" => "dd_tags[test.bundle]", "value" => bundle }) - props.add_element("property", { "name" => "dd_tags[os.platform]", "value" => platform }) - props.add_element("property", { "name" => "dd_tags[os.architecture]", "value" => arch }) - props.add_element("property", { "name" => "dd_tags[os.version]", "value" => release }) - end - File.open(xmlpath, "w") do |f| - xmldoc.write(:output => f, :indent => 4) - end - end - end -end - -describe "security-agent" do - after :all do - print KernelOut.format(`tar -C /tmp/junit -czf /tmp/junit.tar.gz .`) - print KernelOut.format(`tar -C /tmp/testjson -czf /tmp/testjson.tar.gz .`) - end - - case cws_platform - when "host" - context 'functional tests running directly on host' do - env = {} - include_examples "passes", "host", env - end - when "host-fentry" - context 'functional tests running directly on host (with fentry)' do - env = { - "DD_EVENT_MONITORING_CONFIG_EVENT_STREAM_USE_FENTRY" => "true" - } - include_examples "passes", "host", env - end - when "docker" - context 'functional test running inside a container' do - env = {} - include_examples "passes", "docker", env - end - when "docker-fentry" - context 'functional tests running directly on docker (with fentry)' do - env = { - "DD_EVENT_MONITORING_CONFIG_EVENT_STREAM_USE_FENTRY" => "true" - } - include_examples "passes", "docker", env - end - when "ad" - context 'activity dump functional test running on dedicated node' do - env = { - "DEDICATED_ACTIVITY_DUMP_NODE"=>"1", - } - include_examples "passes", "ad", env - end - when "ebpfless" - context 'ebpfless functional tests' do - env = {} - include_examples "passes", "ebpfless", env - end - when "ebpfless-no-seccomp" - context 'ebpfless functional tests without seccomp' do - env = {} - include_examples "passes", "ebpfless-no-seccomp", env - end - else - raise "no CWS platform provided" - end -end diff --git a/test/new-e2e/examples/ecs_test.go b/test/new-e2e/examples/ecs_test.go index 47015fa0a7c8d..155f53309ddd6 100644 --- a/test/new-e2e/examples/ecs_test.go +++ b/test/new-e2e/examples/ecs_test.go @@ -17,6 +17,7 @@ import ( "github.com/DataDog/test-infra-definitions/components/datadog/apps/redis" ecsComp "github.com/DataDog/test-infra-definitions/components/ecs" "github.com/DataDog/test-infra-definitions/resources/aws" + tifEcs "github.com/DataDog/test-infra-definitions/scenarios/aws/ecs" awsconfig "github.com/aws/aws-sdk-go-v2/config" awsecs "github.com/aws/aws-sdk-go-v2/service/ecs" @@ -28,7 +29,7 @@ type myECSSuite struct { } func TestMyECSSuite(t *testing.T) { - e2e.Run(t, &myECSSuite{}, e2e.WithProvisioner(ecs.Provisioner(ecs.WithECSLinuxECSOptimizedNodeGroup(), ecs.WithWorkloadApp(func(e aws.Environment, clusterArn pulumi.StringInput) (*ecsComp.Workload, error) { + e2e.Run(t, &myECSSuite{}, e2e.WithProvisioner(ecs.Provisioner(ecs.WithECSOptions(tifEcs.WithLinuxNodeGroup()), ecs.WithWorkloadApp(func(e aws.Environment, clusterArn pulumi.StringInput) (*ecsComp.Workload, error) { return redis.EcsAppDefinition(e, clusterArn) })))) } diff --git a/test/new-e2e/go.mod b/test/new-e2e/go.mod index f148d9e77085e..766f84e363a44 100644 --- a/test/new-e2e/go.mod +++ b/test/new-e2e/go.mod @@ -251,7 +251,7 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xlab/treeprint v1.2.0 // indirect github.com/zclconf/go-cty v1.14.4 // indirect - github.com/zorkian/go-datadog-api v2.30.0+incompatible + github.com/zorkian/go-datadog-api v2.30.0+incompatible // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.31.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0 // indirect diff --git a/test/new-e2e/pkg/components/ecs_cluster.go b/test/new-e2e/pkg/components/ecs_cluster.go new file mode 100644 index 0000000000000..688cb8ed545ea --- /dev/null +++ b/test/new-e2e/pkg/components/ecs_cluster.go @@ -0,0 +1,15 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package components + +import ( + "github.com/DataDog/test-infra-definitions/components/ecs" +) + +// ECSCluster is an ECS Cluster +type ECSCluster struct { + ecs.ClusterOutput +} diff --git a/test/new-e2e/pkg/e2e/suite.go b/test/new-e2e/pkg/e2e/suite.go index 7fa0495c5f061..e9963e0e8c9bd 100644 --- a/test/new-e2e/pkg/e2e/suite.go +++ b/test/new-e2e/pkg/e2e/suite.go @@ -152,6 +152,7 @@ import ( "github.com/DataDog/test-infra-definitions/common/utils" "github.com/DataDog/test-infra-definitions/components" + "gopkg.in/zorkian/go-datadog-api.v2" "github.com/DataDog/datadog-agent/test/new-e2e/pkg/runner" "github.com/DataDog/datadog-agent/test/new-e2e/pkg/runner/parameters" @@ -184,13 +185,16 @@ var _ Suite[any] = &BaseSuite[any]{} type BaseSuite[Env any] struct { suite.Suite - env *Env - params suiteParams + env *Env + datadogClient *datadog.Client + params suiteParams originalProvisioners ProvisionerMap currentProvisioners ProvisionerMap firstFailTest string + startTime time.Time + endTime time.Time initOnly bool testSessionOutputDir string @@ -229,6 +233,21 @@ func (bs *BaseSuite[Env]) IsDevMode() bool { return bs.params.devMode } +// StartTime returns the time when test suite started +func (bs *BaseSuite[Env]) StartTime() time.Time { + return bs.startTime +} + +// EndTime returns the time when test suite ended +func (bs *BaseSuite[Env]) EndTime() time.Time { + return bs.endTime +} + +// DatadogClient returns a Datadog client that can be used to send telemtry info to dddev during e2e tests +func (bs *BaseSuite[Env]) DatadogClient() *datadog.Client { + return bs.datadogClient +} + func (bs *BaseSuite[Env]) init(options []SuiteOption, self Suite[Env]) { for _, o := range options { o(&bs.params) @@ -461,6 +480,7 @@ func (bs *BaseSuite[Env]) providerContext(opTimeout time.Duration) (context.Cont // // [testify Suite]: https://pkg.go.dev/github.com/stretchr/testify/suite func (bs *BaseSuite[Env]) SetupSuite() { + bs.startTime = time.Now() // In `SetupSuite` we cannot fail as `TearDownSuite` will not be called otherwise. // Meaning that stack clean up may not be called. // We do implement an explicit recover to handle this manuallay. @@ -479,6 +499,13 @@ func (bs *BaseSuite[Env]) SetupSuite() { panic(fmt.Errorf("Forward panic in SetupSuite after TearDownSuite, err was: %v", err)) }() + // Setup Datadog Client to be used to send telemetry when writing e2e tests + apiKey, err := runner.GetProfile().SecretStore().Get(parameters.APIKey) + bs.Require().NoError(err) + appKey, err := runner.GetProfile().SecretStore().Get(parameters.APPKey) + bs.Require().NoError(err) + bs.datadogClient = datadog.NewClient(apiKey, appKey) + if err := bs.reconcileEnv(bs.originalProvisioners); err != nil { // `panic()` is required to stop the execution of the test suite. Otherwise `testify.Suite` will keep on running suite tests. panic(err) @@ -529,6 +556,8 @@ func (bs *BaseSuite[Env]) AfterTest(suiteName, testName string) { // // [testify Suite]: https://pkg.go.dev/github.com/stretchr/testify/suite func (bs *BaseSuite[Env]) TearDownSuite() { + bs.endTime = time.Now() + if bs.params.devMode { return } @@ -548,6 +577,21 @@ func (bs *BaseSuite[Env]) TearDownSuite() { defer cancel() for id, provisioner := range bs.originalProvisioners { + // Run provisioner Diagnose before tearing down the stack + if diagnosableProvisioner, ok := provisioner.(Diagnosable); ok { + stackName, err := infra.GetStackManager().GetPulumiStackName(bs.params.stackName) + if err != nil { + bs.T().Logf("unable to get stack name for diagnose, err: %v", err) + } else { + diagnoseResult, diagnoseErr := diagnosableProvisioner.Diagnose(ctx, stackName) + if diagnoseErr != nil { + bs.T().Logf("WARNING: Diagnose failed: %v", diagnoseErr) + } else if diagnoseResult != "" { + bs.T().Logf("Diagnose result: %s", diagnoseResult) + } + } + } + if err := provisioner.Destroy(ctx, bs.params.stackName, newTestLogger(bs.T())); err != nil { bs.T().Errorf("unable to delete stack: %s, provisioner %s, err: %v", bs.params.stackName, id, err) } diff --git a/test/new-e2e/pkg/environments/aws/docker/host.go b/test/new-e2e/pkg/environments/aws/docker/host.go index 6b60206130241..52d019a59e963 100644 --- a/test/new-e2e/pkg/environments/aws/docker/host.go +++ b/test/new-e2e/pkg/environments/aws/docker/host.go @@ -16,6 +16,7 @@ import ( "github.com/DataDog/test-infra-definitions/common/utils" "github.com/DataDog/test-infra-definitions/components/datadog/agent" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/dogstatsd" "github.com/DataDog/test-infra-definitions/components/datadog/dockeragentparams" "github.com/DataDog/test-infra-definitions/components/docker" "github.com/DataDog/test-infra-definitions/resources/aws" @@ -38,6 +39,7 @@ type ProvisionerParams struct { agentOptions []dockeragentparams.Option fakeintakeOptions []fakeintake.Option extraConfigParams runner.ConfigMap + testingWorkload bool } func newProvisionerParams() *ProvisionerParams { @@ -120,6 +122,14 @@ func WithoutAgent() ProvisionerOption { } } +// WithTestingWorkload enables testing workload +func WithTestingWorkload() ProvisionerOption { + return func(params *ProvisionerParams) error { + params.testingWorkload = true + return nil + } +} + // RunParams contains parameters for the run function type RunParams struct { Environment *aws.Environment @@ -190,6 +200,10 @@ func Run(ctx *pulumi.Context, env *environments.DockerHost, runParams RunParams) // Create Agent if required if params.agentOptions != nil { + if params.testingWorkload { + params.agentOptions = append(params.agentOptions, dockeragentparams.WithExtraComposeManifest(dogstatsd.DockerComposeManifest.Name, dogstatsd.DockerComposeManifest.Content)) + params.agentOptions = append(params.agentOptions, dockeragentparams.WithEnvironmentVariables(pulumi.StringMap{"HOST_IP": host.Address})) + } agent, err := agent.NewDockerAgent(&awsEnv, host, manager, params.agentOptions...) if err != nil { return err diff --git a/test/new-e2e/pkg/environments/aws/ecs/ecs.go b/test/new-e2e/pkg/environments/aws/ecs/ecs.go index 7511b6f7e58bc..426b8271f44b0 100644 --- a/test/new-e2e/pkg/environments/aws/ecs/ecs.go +++ b/test/new-e2e/pkg/environments/aws/ecs/ecs.go @@ -9,16 +9,23 @@ package ecs import ( "fmt" + "github.com/DataDog/test-infra-definitions/common/config" "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ssm" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" - "github.com/DataDog/test-infra-definitions/common/config" "github.com/DataDog/test-infra-definitions/components/datadog/agent" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/aspnetsample" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/cpustress" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/dogstatsd" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/nginx" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/prometheus" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/redis" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/tracegen" "github.com/DataDog/test-infra-definitions/components/datadog/ecsagentparams" fakeintakeComp "github.com/DataDog/test-infra-definitions/components/datadog/fakeintake" ecsComp "github.com/DataDog/test-infra-definitions/components/ecs" "github.com/DataDog/test-infra-definitions/resources/aws" - "github.com/DataDog/test-infra-definitions/resources/aws/ecs" + "github.com/DataDog/test-infra-definitions/scenarios/aws/ecs" "github.com/DataDog/test-infra-definitions/scenarios/aws/fakeintake" "github.com/DataDog/datadog-agent/test/new-e2e/pkg/e2e" @@ -37,14 +44,11 @@ type ProvisionerParams struct { name string agentOptions []ecsagentparams.Option fakeintakeOptions []fakeintake.Option + ecsOptions []ecs.Option extraConfigParams runner.ConfigMap - ecsFargate bool - ecsLinuxECSOptimizedNodeGroup bool - ecsLinuxECSOptimizedARMNodeGroup bool - ecsLinuxBottlerocketNodeGroup bool - ecsWindowsNodeGroup bool infraShouldDeployFakeintakeWithLB bool + testingWorkload bool workloadAppFuncs []WorkloadAppFunc fargateWorkloadAppFuncs []FargateWorkloadAppFunc awsEnv *aws.Environment @@ -56,13 +60,9 @@ func newProvisionerParams() *ProvisionerParams { name: defaultECS, agentOptions: []ecsagentparams.Option{}, fakeintakeOptions: []fakeintake.Option{}, + ecsOptions: []ecs.Option{}, extraConfigParams: runner.ConfigMap{}, - ecsFargate: false, - ecsLinuxECSOptimizedNodeGroup: false, - ecsLinuxECSOptimizedARMNodeGroup: false, - ecsLinuxBottlerocketNodeGroup: false, - ecsWindowsNodeGroup: false, infraShouldDeployFakeintakeWithLB: false, } } @@ -104,42 +104,18 @@ func WithFakeIntakeOptions(opts ...fakeintake.Option) ProvisionerOption { } } -// WithECSFargateCapacityProvider enable Fargate ECS -func WithECSFargateCapacityProvider() ProvisionerOption { +// WithECSOptions sets the options for ECS cluster +func WithECSOptions(opts ...ecs.Option) ProvisionerOption { return func(params *ProvisionerParams) error { - params.ecsFargate = true + params.ecsOptions = append(params.ecsOptions, opts...) return nil } } -// WithECSLinuxECSOptimizedNodeGroup enable aws/ecs/linuxECSOptimizedNodeGroup -func WithECSLinuxECSOptimizedNodeGroup() ProvisionerOption { +// WithTestingWorkload deploys testing workloads for nginx, redis, cpustress, dogstatsd, prometheus and tracegen +func WithTestingWorkload() ProvisionerOption { return func(params *ProvisionerParams) error { - params.ecsLinuxECSOptimizedNodeGroup = true - return nil - } -} - -// WithECSLinuxECSOptimizedARMNodeGroup enable aws/ecs/linuxECSOptimizedARMNodeGroup -func WithECSLinuxECSOptimizedARMNodeGroup() ProvisionerOption { - return func(params *ProvisionerParams) error { - params.ecsLinuxECSOptimizedARMNodeGroup = true - return nil - } -} - -// WithECSLinuxBottlerocketNodeGroup enable aws/ecs/linuxBottlerocketNodeGroup -func WithECSLinuxBottlerocketNodeGroup() ProvisionerOption { - return func(params *ProvisionerParams) error { - params.ecsLinuxBottlerocketNodeGroup = true - return nil - } -} - -// WithECSWindowsNodeGroup enable aws/ecs/windowsLTSCNodeGroup -func WithECSWindowsNodeGroup() ProvisionerOption { - return func(params *ProvisionerParams) error { - params.ecsWindowsNodeGroup = true + params.testingWorkload = true return nil } } @@ -210,70 +186,24 @@ func Run(ctx *pulumi.Context, env *environments.ECS, params *ProvisionerParams) return err } } - // Create cluster - ecsCluster, err := ecs.CreateEcsCluster(awsEnv, params.name) + clusterParams, err := ecs.NewParams(params.ecsOptions...) if err != nil { return err } - // Export cluster’s properties - ctx.Export("ecs-cluster-name", ecsCluster.Name) - ctx.Export("ecs-cluster-arn", ecsCluster.Arn) - - // Handle capacity providers - capacityProviders := pulumi.StringArray{} - if params.ecsFargate { - capacityProviders = append(capacityProviders, pulumi.String("FARGATE")) - } - - linuxNodeGroupPresent := false - if params.ecsLinuxECSOptimizedNodeGroup { - cpName, err := ecs.NewECSOptimizedNodeGroup(awsEnv, ecsCluster.Name, false) - if err != nil { - return err - } - - capacityProviders = append(capacityProviders, cpName) - linuxNodeGroupPresent = true - } - - if params.ecsLinuxECSOptimizedARMNodeGroup { - cpName, err := ecs.NewECSOptimizedNodeGroup(awsEnv, ecsCluster.Name, true) - if err != nil { - return err - } - - capacityProviders = append(capacityProviders, cpName) - linuxNodeGroupPresent = true - } - - if params.ecsLinuxBottlerocketNodeGroup { - cpName, err := ecs.NewBottlerocketNodeGroup(awsEnv, ecsCluster.Name) - if err != nil { - return err - } - - capacityProviders = append(capacityProviders, cpName) - linuxNodeGroupPresent = true - } - - if params.ecsWindowsNodeGroup { - cpName, err := ecs.NewWindowsNodeGroup(awsEnv, ecsCluster.Name) - if err != nil { - return err - } - - capacityProviders = append(capacityProviders, cpName) + // Create cluster + cluster, err := ecs.NewCluster(awsEnv, params.name, params.ecsOptions...) + if err != nil { + return err } - - // Associate capacity providers - _, err = ecs.NewClusterCapacityProvider(awsEnv, ctx.Stack(), ecsCluster.Name, capacityProviders) + err = cluster.Export(ctx, &env.ECSCluster.ClusterOutput) if err != nil { return err } var apiKeyParam *ssm.Parameter var fakeIntake *fakeintakeComp.Fakeintake + // Create task and service if params.agentOptions != nil { if params.fakeintakeOptions != nil { @@ -290,6 +220,7 @@ func Run(ctx *pulumi.Context, env *environments.ECS, params *ProvisionerParams) return err } } + apiKeyParam, err = ssm.NewParameter(ctx, awsEnv.Namer.ResourceName("agent-apikey"), &ssm.ParameterArgs{ Name: awsEnv.CommonNamer().DisplayName(1011, pulumi.String("agent-apikey")), Type: ssm.ParameterTypeSecureString, @@ -300,22 +231,15 @@ func Run(ctx *pulumi.Context, env *environments.ECS, params *ProvisionerParams) return err } - // Deploy EC2 Agent - if linuxNodeGroupPresent { - agentDaemon, err := agent.ECSLinuxDaemonDefinition(awsEnv, "ec2-linux-dd-agent", apiKeyParam.Name, fakeIntake, ecsCluster.Arn, params.agentOptions...) - if err != nil { - return err - } - - ctx.Export("agent-ec2-linux-task-arn", agentDaemon.TaskDefinition.Arn()) - ctx.Export("agent-ec2-linux-task-family", agentDaemon.TaskDefinition.Family()) - ctx.Export("agent-ec2-linux-task-version", agentDaemon.TaskDefinition.Revision()) + _, err := agent.ECSLinuxDaemonDefinition(awsEnv, "ec2-linux-dd-agent", apiKeyParam.Name, fakeIntake, cluster.ClusterArn, params.agentOptions...) + if err != nil { + return err } // Deploy Fargate Apps - if params.ecsFargate { + if clusterParams.FargateCapacityProvider { for _, fargateAppFunc := range params.fargateWorkloadAppFuncs { - _, err := fargateAppFunc(awsEnv, ecsCluster.Arn, apiKeyParam.Name, fakeIntake) + _, err := fargateAppFunc(awsEnv, cluster.ClusterArn, apiKeyParam.Name, fakeIntake) if err != nil { return err } @@ -323,8 +247,48 @@ func Run(ctx *pulumi.Context, env *environments.ECS, params *ProvisionerParams) } } + if params.testingWorkload { + if _, err := nginx.EcsAppDefinition(awsEnv, cluster.ClusterArn); err != nil { + return err + } + + if _, err := redis.EcsAppDefinition(awsEnv, cluster.ClusterArn); err != nil { + return err + } + + if _, err := cpustress.EcsAppDefinition(awsEnv, cluster.ClusterArn); err != nil { + return err + } + + if _, err := dogstatsd.EcsAppDefinition(awsEnv, cluster.ClusterArn); err != nil { + return err + } + + if _, err := prometheus.EcsAppDefinition(awsEnv, cluster.ClusterArn); err != nil { + return err + } + + if _, err := tracegen.EcsAppDefinition(awsEnv, cluster.ClusterArn); err != nil { + return err + } + } + + if clusterParams.FargateCapacityProvider && params.testingWorkload && params.agentOptions != nil { + + if _, err := redis.FargateAppDefinition(awsEnv, cluster.ClusterArn, apiKeyParam.Name, fakeIntake); err != nil { + return err + } + + if _, err = nginx.FargateAppDefinition(awsEnv, cluster.ClusterArn, apiKeyParam.Name, fakeIntake); err != nil { + return err + } + + if _, err = aspnetsample.FargateAppDefinition(awsEnv, cluster.ClusterArn, apiKeyParam.Name, fakeIntake); err != nil { + return err + } + } for _, appFunc := range params.workloadAppFuncs { - _, err := appFunc(awsEnv, ecsCluster.Arn) + _, err := appFunc(awsEnv, cluster.ClusterArn) if err != nil { return err } diff --git a/test/new-e2e/pkg/environments/aws/kubernetes/eks.go b/test/new-e2e/pkg/environments/aws/kubernetes/eks.go index fe5bac77b5748..eef9a51518011 100644 --- a/test/new-e2e/pkg/environments/aws/kubernetes/eks.go +++ b/test/new-e2e/pkg/environments/aws/kubernetes/eks.go @@ -12,6 +12,13 @@ import ( "github.com/DataDog/test-infra-definitions/common/utils" "github.com/DataDog/test-infra-definitions/components/datadog/agent/helm" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/cpustress" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/dogstatsd" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/mutatedbyadmissioncontroller" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/nginx" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/prometheus" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/redis" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/tracegen" dogstatsdstandalone "github.com/DataDog/test-infra-definitions/components/datadog/dogstatsd-standalone" fakeintakeComp "github.com/DataDog/test-infra-definitions/components/datadog/fakeintake" "github.com/DataDog/test-infra-definitions/components/datadog/kubernetesagentparams" @@ -101,10 +108,10 @@ func EKSRunFunc(ctx *pulumi.Context, env *environments.Kubernetes, params *Provi env.FakeIntake = nil } + workloadWithCRDDeps := []pulumi.Resource{cluster} // Deploy the agent - dependsOnSetup := utils.PulumiDependsOn(cluster) if params.agentOptions != nil { - params.agentOptions = append(params.agentOptions, kubernetesagentparams.WithPulumiResourceOptions(dependsOnSetup), kubernetesagentparams.WithFakeintake(fakeIntake)) + params.agentOptions = append(params.agentOptions, kubernetesagentparams.WithPulumiResourceOptions(utils.PulumiDependsOn(cluster)), kubernetesagentparams.WithFakeintake(fakeIntake)) kubernetesAgent, err := helm.NewKubernetesAgent(&awsEnv, "eks", cluster.KubeProvider, params.agentOptions...) if err != nil { return err @@ -113,10 +120,10 @@ func EKSRunFunc(ctx *pulumi.Context, env *environments.Kubernetes, params *Provi if err != nil { return err } + workloadWithCRDDeps = append(workloadWithCRDDeps, kubernetesAgent) } else { env.Agent = nil } - // Deploy standalone dogstatsd if params.deployDogstatsd { if _, err := dogstatsdstandalone.K8sAppDefinition(&awsEnv, cluster.KubeProvider, "dogstatsd-standalone", fakeIntake, true, ""); err != nil { @@ -124,6 +131,46 @@ func EKSRunFunc(ctx *pulumi.Context, env *environments.Kubernetes, params *Provi } } + if params.deployTestWorkload { + + if _, err := cpustress.K8sAppDefinition(&awsEnv, cluster.KubeProvider, "workload-cpustress", utils.PulumiDependsOn(cluster)); err != nil { + return err + } + + // dogstatsd clients that report to the Agent + if _, err := dogstatsd.K8sAppDefinition(&awsEnv, cluster.KubeProvider, "workload-dogstatsd", 8125, "/var/run/datadog/dsd.socket", utils.PulumiDependsOn(cluster)); err != nil { + return err + } + + // dogstatsd clients that report to the dogstatsd standalone deployment + if _, err := dogstatsd.K8sAppDefinition(&awsEnv, cluster.KubeProvider, "workload-dogstatsd-standalone", dogstatsdstandalone.HostPort, dogstatsdstandalone.Socket, utils.PulumiDependsOn(cluster)); err != nil { + return err + } + + if _, err := tracegen.K8sAppDefinition(&awsEnv, cluster.KubeProvider, "workload-tracegen", utils.PulumiDependsOn(cluster)); err != nil { + return err + } + + if _, err := prometheus.K8sAppDefinition(&awsEnv, cluster.KubeProvider, "workload-prometheus", utils.PulumiDependsOn(cluster)); err != nil { + return err + } + + if _, err := mutatedbyadmissioncontroller.K8sAppDefinition(&awsEnv, cluster.KubeProvider, "workload-mutated", "workload-mutated-lib-injection", utils.PulumiDependsOn(cluster)); err != nil { + return err + } + + // These resources cannot be deployed if the Agent is not installed, it requires some CRDs provided by the Helm chart + if params.agentOptions != nil { + if _, err := nginx.K8sAppDefinition(&awsEnv, cluster.KubeProvider, "workload-nginx", "", true, utils.PulumiDependsOn(workloadWithCRDDeps...)); err != nil { + return err + } + + if _, err := redis.K8sAppDefinition(&awsEnv, cluster.KubeProvider, "workload-redis", true, utils.PulumiDependsOn(workloadWithCRDDeps...)); err != nil { + return err + } + } + } + // Deploy workloads for _, appFunc := range params.workloadAppFuncs { _, err := appFunc(&awsEnv, cluster.KubeProvider) diff --git a/test/new-e2e/pkg/environments/aws/kubernetes/kind.go b/test/new-e2e/pkg/environments/aws/kubernetes/kind.go index 8df879ce259fd..58fce4c5a9132 100644 --- a/test/new-e2e/pkg/environments/aws/kubernetes/kind.go +++ b/test/new-e2e/pkg/environments/aws/kubernetes/kind.go @@ -17,6 +17,15 @@ import ( "github.com/DataDog/datadog-agent/test/new-e2e/pkg/utils/optional" "github.com/DataDog/test-infra-definitions/components/datadog/agent/helm" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/cpustress" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/dogstatsd" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/mutatedbyadmissioncontroller" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/nginx" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/prometheus" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/redis" + "github.com/DataDog/test-infra-definitions/components/datadog/apps/tracegen" + dogstatsdstandalone "github.com/DataDog/test-infra-definitions/components/datadog/dogstatsd-standalone" + fakeintakeComp "github.com/DataDog/test-infra-definitions/components/datadog/fakeintake" "github.com/DataDog/test-infra-definitions/components/datadog/kubernetesagentparams" kubeComp "github.com/DataDog/test-infra-definitions/components/kubernetes" "github.com/DataDog/test-infra-definitions/resources/aws" @@ -97,10 +106,11 @@ func KindRunFunc(ctx *pulumi.Context, env *environments.Kubernetes, params *Prov return err } + var fakeIntake *fakeintakeComp.Fakeintake if params.fakeintakeOptions != nil { fakeintakeOpts := []fakeintake.Option{fakeintake.WithLoadBalancer()} params.fakeintakeOptions = append(fakeintakeOpts, params.fakeintakeOptions...) - fakeIntake, err := fakeintake.NewECSFargateInstance(awsEnv, params.name, params.fakeintakeOptions...) + fakeIntake, err = fakeintake.NewECSFargateInstance(awsEnv, params.name, params.fakeintakeOptions...) if err != nil { return err } @@ -117,6 +127,7 @@ func KindRunFunc(ctx *pulumi.Context, env *environments.Kubernetes, params *Prov env.FakeIntake = nil } + var dependsOnCrd []pulumi.Resource if params.agentOptions != nil { kindClusterName := ctx.Stack() helmValues := fmt.Sprintf(` @@ -138,11 +149,56 @@ agents: if err != nil { return err } - + dependsOnCrd = append(dependsOnCrd, agent) } else { env.Agent = nil } + if params.deployDogstatsd { + if _, err := dogstatsdstandalone.K8sAppDefinition(&awsEnv, kubeProvider, "dogstatsd-standalone", fakeIntake, false, ctx.Stack()); err != nil { + return err + } + } + + // Deploy testing workload + if params.deployTestWorkload { + // dogstatsd clients that report to the Agent + if _, err := dogstatsd.K8sAppDefinition(&awsEnv, kubeProvider, "workload-dogstatsd", 8125, "/var/run/datadog/dsd.socket"); err != nil { + return err + } + + // dogstatsd clients that report to the dogstatsd standalone deployment + if _, err := dogstatsd.K8sAppDefinition(&awsEnv, kubeProvider, "workload-dogstatsd-standalone", dogstatsdstandalone.HostPort, dogstatsdstandalone.Socket); err != nil { + return err + } + + if _, err := tracegen.K8sAppDefinition(&awsEnv, kubeProvider, "workload-tracegen"); err != nil { + return err + } + + if _, err := prometheus.K8sAppDefinition(&awsEnv, kubeProvider, "workload-prometheus"); err != nil { + return err + } + + if _, err := mutatedbyadmissioncontroller.K8sAppDefinition(&awsEnv, kubeProvider, "workload-mutated", "workload-mutated-lib-injection"); err != nil { + return err + } + + // These workloads can be deployed only if the agent is installed, they rely on CRDs installed by Agent helm chart + if params.agentOptions != nil { + if _, err := nginx.K8sAppDefinition(&awsEnv, kubeProvider, "workload-nginx", "", true, utils.PulumiDependsOn(dependsOnCrd...)); err != nil { + return err + } + + if _, err := redis.K8sAppDefinition(&awsEnv, kubeProvider, "workload-redis", true, utils.PulumiDependsOn(dependsOnCrd...)); err != nil { + return err + } + + if _, err := cpustress.K8sAppDefinition(&awsEnv, kubeProvider, "workload-cpustress", utils.PulumiDependsOn(dependsOnCrd...)); err != nil { + return err + } + } + } for _, appFunc := range params.workloadAppFuncs { _, err := appFunc(&awsEnv, kubeProvider) if err != nil { diff --git a/test/new-e2e/pkg/environments/aws/kubernetes/params.go b/test/new-e2e/pkg/environments/aws/kubernetes/params.go index abc939d523bfb..9f7e9f1c394ff 100644 --- a/test/new-e2e/pkg/environments/aws/kubernetes/params.go +++ b/test/new-e2e/pkg/environments/aws/kubernetes/params.go @@ -39,6 +39,7 @@ type ProvisionerParams struct { eksWindowsNodeGroup bool awsEnv *aws.Environment deployDogstatsd bool + deployTestWorkload bool } func newProvisionerParams() *ProvisionerParams { @@ -120,6 +121,14 @@ func WithDeployDogstatsd() ProvisionerOption { } } +// WithDeployTestWorkload deploy a test workload +func WithDeployTestWorkload() ProvisionerOption { + return func(params *ProvisionerParams) error { + params.deployTestWorkload = true + return nil + } +} + // WithoutFakeIntake removes the fake intake func WithoutFakeIntake() ProvisionerOption { return func(params *ProvisionerParams) error { diff --git a/test/new-e2e/pkg/environments/ecs.go b/test/new-e2e/pkg/environments/ecs.go index b400ff25a756f..3610318ac66be 100644 --- a/test/new-e2e/pkg/environments/ecs.go +++ b/test/new-e2e/pkg/environments/ecs.go @@ -6,33 +6,12 @@ package environments import ( - "github.com/zorkian/go-datadog-api" - "github.com/DataDog/datadog-agent/test/new-e2e/pkg/components" - "github.com/DataDog/datadog-agent/test/new-e2e/pkg/e2e" - "github.com/DataDog/datadog-agent/test/new-e2e/pkg/runner" - "github.com/DataDog/datadog-agent/test/new-e2e/pkg/runner/parameters" ) // ECS is an environment that contains a ECS deployed in a cluster, FakeIntake and Agent configured to talk to each other. type ECS struct { // Components - FakeIntake *components.FakeIntake - DatadogClient *datadog.Client -} - -var _ e2e.Initializable = &ECS{} - -// Init initializes the environment -func (e *ECS) Init(_ e2e.Context) error { - apiKey, err := runner.GetProfile().SecretStore().Get(parameters.APIKey) - if err != nil { - return err - } - appKey, err := runner.GetProfile().SecretStore().Get(parameters.APPKey) - if err != nil { - return err - } - e.DatadogClient = datadog.NewClient(apiKey, appKey) - return nil + ECSCluster *components.ECSCluster + FakeIntake *components.FakeIntake } diff --git a/test/new-e2e/pkg/utils/infra/retriable_errors.go b/test/new-e2e/pkg/utils/infra/retriable_errors.go index 1c2ee5f3b1812..b940cbcd2e064 100644 --- a/test/new-e2e/pkg/utils/infra/retriable_errors.go +++ b/test/new-e2e/pkg/utils/infra/retriable_errors.go @@ -39,7 +39,8 @@ func getKnownErrors() []knownError { }, { // https://datadoghq.atlassian.net/browse/ADXT-558 - errorMessage: `Process exited with status 2: running " sudo cloud-init status --wait"`, + // https://datadoghq.atlassian.net/browse/ADXT-713 + errorMessage: `Process exited with status \d+: running " sudo cloud-init status --wait"`, retryType: ReCreate, }, { diff --git a/test/new-e2e/pkg/utils/infra/stack_manager_test.go b/test/new-e2e/pkg/utils/infra/stack_manager_test.go index 56de15ce98455..3dd9fa81c5380 100644 --- a/test/new-e2e/pkg/utils/infra/stack_manager_test.go +++ b/test/new-e2e/pkg/utils/infra/stack_manager_test.go @@ -258,6 +258,11 @@ func TestStackManager(t *testing.T) { errMessage: "Process exited with status 2: running \" sudo cloud-init status --wait\"", expectedRetryType: ReCreate, }, + { + name: "cloud-init-timeout", + errMessage: "Process exited with status 6: running \" sudo cloud-init status --wait\"", + expectedRetryType: ReCreate, + }, { name: "ecs-fakeintake-timeout", errMessage: "waiting for ECS Service (arn:aws:ecs:us-east-1:669783387624:service/fakeintake-ecs/ci-633219896-4670-e2e-dockersuite-80f62edf7bcc6194-aws-fakeintake-dockervm-srv) create: timeout while waiting for state to become 'tfSTABLE' (last state: 'tfPENDING', timeout: 20m0s)", diff --git a/test/new-e2e/system-probe/config/platforms.json b/test/new-e2e/system-probe/config/platforms.json index b7a95fb5f7e26..9249144d9ded9 100644 --- a/test/new-e2e/system-probe/config/platforms.json +++ b/test/new-e2e/system-probe/config/platforms.json @@ -246,6 +246,17 @@ "os_version": "40", "image": "Fedora-Cloud-Base-40.x86_64.qcow2.xz", "image_version": "20241003_a9a46356" + }, + "ubuntu_24.10": { + "os_name": "Ubuntu", + "os_id": "ubuntu", + "kernel": "6.11.0-8-generic", + "os_version": "24.10", + "image": "ubuntu-24.10-x86_64.qcow2.xz", + "image_version": "20241028_31340374", + "alt_version_names": [ + "oracular" + ] } }, "arm64": { @@ -464,6 +475,17 @@ "os_version": "40", "image": "Fedora-Cloud-Base-40.arm64.qcow2.xz", "image_version": "20241003_a9a46356" + }, + "ubuntu_24.10": { + "os_name": "Ubuntu", + "os_id": "ubuntu", + "kernel": "6.11.0-8-generic", + "os_version": "24.10", + "image": "ubuntu-24.10-arm64.qcow2.xz", + "image_version": "20241028_31340374", + "alt_version_names": [ + "oracular" + ] } } } \ No newline at end of file diff --git a/test/new-e2e/tests/apm/docker_test.go b/test/new-e2e/tests/apm/docker_test.go index e3a597a0dc184..04cdf2045e79f 100644 --- a/test/new-e2e/tests/apm/docker_test.go +++ b/test/new-e2e/tests/apm/docker_test.go @@ -146,10 +146,12 @@ func (s *DockerFakeintakeSuite) TestStatsForService() { s.Require().NoError(err) service := fmt.Sprintf("tracegen-stats-%s", s.transport) + addSpanTags := "peer.hostname:foo,span.kind:client" + expectPeerTag := "peer.hostname:foo" defer waitTracegenShutdown(&s.Suite, s.Env().FakeIntake) - defer runTracegenDocker(s.Env().RemoteHost, service, tracegenCfg{transport: s.transport})() + defer runTracegenDocker(s.Env().RemoteHost, service, tracegenCfg{transport: s.transport, addSpanTags: addSpanTags})() s.EventuallyWithTf(func(c *assert.CollectT) { - testStatsForService(s.T(), c, service, s.Env().FakeIntake) + testStatsForService(s.T(), c, service, expectPeerTag, s.Env().FakeIntake) }, 2*time.Minute, 10*time.Second, "Failed finding stats") } diff --git a/test/new-e2e/tests/apm/tests.go b/test/new-e2e/tests/apm/tests.go index 5fd21118fe791..4df55acb512bc 100644 --- a/test/new-e2e/tests/apm/tests.go +++ b/test/new-e2e/tests/apm/tests.go @@ -7,6 +7,7 @@ package apm import ( "fmt" + "slices" "strings" "testing" "time" @@ -68,13 +69,16 @@ func testTPS(c *assert.CollectT, intake *components.FakeIntake, tps float64) { } } -func testStatsForService(t *testing.T, c *assert.CollectT, service string, intake *components.FakeIntake) { +func testStatsForService(t *testing.T, c *assert.CollectT, service string, expectedPeerTag string, intake *components.FakeIntake) { t.Helper() stats, err := intake.Client().GetAPMStats() assert.NoError(c, err) assert.NotEmpty(c, stats) t.Logf("Got %d apm stats", len(stats)) assert.True(c, hasStatsForService(stats, service), "got stats: %v", stats) + if expectedPeerTag != "" { + assert.True(c, hasPeerTagsStats(stats, expectedPeerTag), "got stats: %v", stats) + } } func testTracesHaveContainerTag(t *testing.T, c *assert.CollectT, service string, intake *components.FakeIntake) { @@ -194,6 +198,21 @@ func hasStatsForService(payloads []*aggregator.APMStatsPayload, service string) return false } +func hasPeerTagsStats(payloads []*aggregator.APMStatsPayload, fullTag string) bool { + for _, p := range payloads { + for _, s := range p.StatsPayload.Stats { + for _, bucket := range s.Stats { + for _, ss := range bucket.Stats { + if slices.Contains(ss.GetPeerTags(), fullTag) { + return true + } + } + } + } + } + return false +} + func hasContainerTag(payloads []*aggregator.TracePayload, tag string) bool { for _, p := range payloads { for _, t := range p.AgentPayload.TracerPayloads { diff --git a/test/new-e2e/tests/apm/tracegen.go b/test/new-e2e/tests/apm/tracegen.go index 00492505ea500..1b53743adb890 100644 --- a/test/new-e2e/tests/apm/tracegen.go +++ b/test/new-e2e/tests/apm/tracegen.go @@ -31,38 +31,41 @@ func (t transport) String() string { } type tracegenCfg struct { - transport transport + transport transport + addSpanTags string } func runTracegenDocker(h *components.RemoteHost, service string, cfg tracegenCfg) (shutdown func()) { var run, rm string if cfg.transport == uds { - run, rm = tracegenUDSCommands(service) + run, rm = tracegenUDSCommands(service, cfg.addSpanTags) } else if cfg.transport == tcp { - run, rm = tracegenTCPCommands(service) + run, rm = tracegenTCPCommands(service, cfg.addSpanTags) } h.MustExecute(rm) // kill any existing leftover container h.MustExecute(run) return func() { h.MustExecute(rm) } } -func tracegenUDSCommands(service string) (string, string) { +func tracegenUDSCommands(service string, peerTags string) (string, string) { // TODO: use a proper docker-compose definition for tracegen run := "docker run -d --rm --name " + service + " -v /var/run/datadog/:/var/run/datadog/ " + " -e DD_TRACE_AGENT_URL=unix:///var/run/datadog/apm.socket " + " -e DD_SERVICE=" + service + " -e DD_GIT_COMMIT_SHA=abcd1234 " + + " -e TRACEGEN_ADDSPANTAGS=" + peerTags + " ghcr.io/datadog/apps-tracegen:main" rm := "docker rm -f " + service return run, rm } -func tracegenTCPCommands(service string) (string, string) { +func tracegenTCPCommands(service string, peerTags string) (string, string) { // TODO: use a proper docker-compose definition for tracegen run := "docker run -d --network host --rm --name " + service + " -e DD_SERVICE=" + service + " -e DD_GIT_COMMIT_SHA=abcd1234 " + + " -e TRACEGEN_ADDSPANTAGS=" + peerTags + " ghcr.io/datadog/apps-tracegen:main" rm := "docker rm -f " + service return run, rm diff --git a/test/new-e2e/tests/apm/vm_test.go b/test/new-e2e/tests/apm/vm_test.go index c84fd40d2b8d6..90f78554db9e2 100644 --- a/test/new-e2e/tests/apm/vm_test.go +++ b/test/new-e2e/tests/apm/vm_test.go @@ -21,13 +21,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/DataDog/test-infra-definitions/components/datadog/agentparams" + "github.com/DataDog/test-infra-definitions/scenarios/aws/ec2" + "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" "github.com/DataDog/datadog-agent/test/new-e2e/pkg/utils/e2e/client/agentclient" "github.com/DataDog/datadog-agent/test/new-e2e/tests/agent-shared-components/secretsutils" - "github.com/DataDog/test-infra-definitions/components/datadog/agentparams" - "github.com/DataDog/test-infra-definitions/scenarios/aws/ec2" ) type VMFakeintakeSuite struct { @@ -176,6 +177,8 @@ func (s *VMFakeintakeSuite) TestStatsForService() { s.Require().NoError(err) service := fmt.Sprintf("tracegen-stats-%s", s.transport) + addSpanTags := "peer.hostname:foo,span.kind:producer" + expectPeerTag := "peer.hostname:foo" // Wait for agent to be live s.T().Log("Waiting for Trace Agent to be live.") @@ -184,12 +187,12 @@ func (s *VMFakeintakeSuite) TestStatsForService() { // Run Trace Generator s.T().Log("Starting Trace Generator.") defer waitTracegenShutdown(&s.Suite, s.Env().FakeIntake) - shutdown := runTracegenDocker(s.Env().RemoteHost, service, tracegenCfg{transport: s.transport}) + shutdown := runTracegenDocker(s.Env().RemoteHost, service, tracegenCfg{transport: s.transport, addSpanTags: addSpanTags}) defer shutdown() s.EventuallyWithTf(func(c *assert.CollectT) { s.logStatus() - testStatsForService(s.T(), c, service, s.Env().FakeIntake) + testStatsForService(s.T(), c, service, expectPeerTag, s.Env().FakeIntake) s.logJournal(false) }, 3*time.Minute, 10*time.Second, "Failed finding stats") } diff --git a/test/new-e2e/tests/discovery/linux_test.go b/test/new-e2e/tests/discovery/linux_test.go index 9238137beed99..ec7d0aa339be3 100644 --- a/test/new-e2e/tests/discovery/linux_test.go +++ b/test/new-e2e/tests/discovery/linux_test.go @@ -91,54 +91,51 @@ func (s *linuxTestSuite) TestServiceDiscoveryCheck() { } } - found := foundMap["json-server"] - if assert.NotNil(c, found) { - assert.Equal(c, "none", found.Payload.APMInstrumentation) - assert.Equal(c, "json-server", found.Payload.ServiceName) - assert.Equal(c, "json-server", found.Payload.GeneratedServiceName) - assert.Empty(c, found.Payload.DDService) - assert.Empty(c, found.Payload.ServiceNameSource) - assert.NotZero(c, found.Payload.RSSMemory) - } - - found = foundMap["node-instrumented"] - if assert.NotNil(c, found) { - assert.Equal(c, "provided", found.Payload.APMInstrumentation) - assert.Equal(c, "node-instrumented", found.Payload.ServiceName) - assert.Equal(c, "node-instrumented", found.Payload.GeneratedServiceName) - assert.Empty(c, found.Payload.DDService) - assert.Empty(c, found.Payload.ServiceNameSource) - assert.NotZero(c, found.Payload.RSSMemory) - } - - found = foundMap["python-svc-dd"] - if assert.NotNil(c, found) { - assert.Equal(c, "none", found.Payload.APMInstrumentation) - assert.Equal(c, "python-svc-dd", found.Payload.ServiceName) - assert.Equal(c, "python.server", found.Payload.GeneratedServiceName) - assert.Equal(c, "python-svc-dd", found.Payload.DDService) - assert.Equal(c, "provided", found.Payload.ServiceNameSource) - assert.NotZero(c, found.Payload.RSSMemory) - } - - found = foundMap["python.instrumented"] - if assert.NotNil(c, found) { - assert.Equal(c, "provided", found.Payload.APMInstrumentation) - assert.Equal(c, "python.instrumented", found.Payload.ServiceName) - assert.Equal(c, "python.instrumented", found.Payload.GeneratedServiceName) - assert.Empty(c, found.Payload.DDService) - assert.Empty(c, found.Payload.ServiceNameSource) - assert.NotZero(c, found.Payload.RSSMemory) - } - - found = foundMap["rails_hello"] - if assert.NotNil(c, found) { - assert.Equal(c, "rails_hello", found.Payload.ServiceName) - assert.Equal(c, "rails_hello", found.Payload.GeneratedServiceName) - assert.Empty(c, found.Payload.DDService) - assert.Empty(c, found.Payload.ServiceNameSource) - assert.NotZero(c, found.Payload.RSSMemory) - } + s.assertService(t, c, foundMap, serviceExpectedPayload{ + name: "json-server", + systemdServiceName: "node-json-server", + instrumentation: "none", + serviceName: "json-server", + generatedServiceName: "json-server", + ddService: "", + serviceNameSource: "", + }) + s.assertService(t, c, foundMap, serviceExpectedPayload{ + name: "node-instrumented", + systemdServiceName: "node-instrumented", + instrumentation: "provided", + serviceName: "node-instrumented", + generatedServiceName: "node-instrumented", + ddService: "", + serviceNameSource: "", + }) + s.assertService(t, c, foundMap, serviceExpectedPayload{ + name: "python-svc-dd", + systemdServiceName: "python-svc", + instrumentation: "none", + serviceName: "python-svc-dd", + generatedServiceName: "python.server", + ddService: "python-svc-dd", + serviceNameSource: "provided", + }) + s.assertService(t, c, foundMap, serviceExpectedPayload{ + name: "python.instrumented", + systemdServiceName: "python-instrumented", + instrumentation: "provided", + serviceName: "python.instrumented", + generatedServiceName: "python.instrumented", + ddService: "", + serviceNameSource: "", + }) + s.assertService(t, c, foundMap, serviceExpectedPayload{ + name: "rails_hello", + systemdServiceName: "rails-svc", + instrumentation: "none", + serviceName: "rails_hello", + generatedServiceName: "rails_hello", + ddService: "", + serviceNameSource: "", + }) assert.Contains(c, foundMap, "json-server") }, 3*time.Minute, 10*time.Second) @@ -188,3 +185,33 @@ func (s *linuxTestSuite) stopServices() { s.Env().RemoteHost.MustExecute("sudo systemctl stop " + service) } } + +type serviceExpectedPayload struct { + name string + systemdServiceName string + instrumentation string + serviceName string + generatedServiceName string + ddService string + serviceNameSource string +} + +func (s *linuxTestSuite) assertService(t *testing.T, c *assert.CollectT, foundMap map[string]*aggregator.ServiceDiscoveryPayload, expected serviceExpectedPayload) { + t.Helper() + + found := foundMap[expected.name] + if assert.NotNil(c, found, "could not find service %q", expected.name) { + assert.Equal(c, expected.instrumentation, found.Payload.APMInstrumentation, "service %q: APM instrumentation", expected.name) + assert.Equal(c, expected.serviceName, found.Payload.ServiceName, "service %q: service name", expected.name) + assert.Equal(c, expected.generatedServiceName, found.Payload.GeneratedServiceName, "service %q: generated service name", expected.name) + assert.Equal(c, expected.ddService, found.Payload.DDService, "service %q: DD service", expected.name) + assert.Equal(c, expected.serviceNameSource, found.Payload.ServiceNameSource, "service %q: service name source", expected.name) + assert.NotZero(c, found.Payload.RSSMemory, "service %q: expected non-zero memory usage", expected.name) + } else { + status := s.Env().RemoteHost.MustExecute("sudo systemctl status " + expected.systemdServiceName) + logs := s.Env().RemoteHost.MustExecute("sudo journalctl -u " + expected.systemdServiceName) + + t.Logf("Service %q status:\n:%s", expected.systemdServiceName, status) + t.Logf("Service %q logs:\n:%s", expected.systemdServiceName, logs) + } +} diff --git a/test/new-e2e/tests/gpu/gpu_test.go b/test/new-e2e/tests/gpu/gpu_test.go index c1a483ff0209b..9e3803062b982 100644 --- a/test/new-e2e/tests/gpu/gpu_test.go +++ b/test/new-e2e/tests/gpu/gpu_test.go @@ -20,7 +20,6 @@ import ( "github.com/DataDog/test-infra-definitions/components/datadog/agentparams" "github.com/DataDog/test-infra-definitions/components/os" - "github.com/DataDog/datadog-agent/pkg/util/testutil/flake" "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" @@ -28,9 +27,11 @@ import ( ) var devMode = flag.Bool("devmode", false, "enable dev mode") +var imageTag = flag.String("image-tag", "main", "Docker image tag to use") type gpuSuite struct { e2e.BaseSuite[environments.Host] + imageTag string } const defaultGpuCheckConfig = ` @@ -46,14 +47,12 @@ gpu_monitoring: enabled: true ` -const vectorAddDockerImg = "nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2" +const vectorAddDockerImg = "ghcr.io/datadog/apps-cuda-basic" const gpuEnabledAMI = "ami-0f71e237bb2ba34be" // Ubuntu 22.04 with GPU drivers // TestGPUSuite runs tests for the VM interface to ensure its implementation is correct. +// Not to be run in parallel, as some tests wait until the checks are available. func TestGPUSuite(t *testing.T) { - // Marked as flaky pending removal of unattended-upgrades in the AMI - flake.Mark(t) - provisioner := awshost.Provisioner( awshost.WithEC2InstanceOptions( ec2.WithInstanceType("g4dn.xlarge"), @@ -71,13 +70,21 @@ func TestGPUSuite(t *testing.T) { suiteParams = append(suiteParams, e2e.WithDevMode()) } - e2e.Run(t, &gpuSuite{}, suiteParams...) + suite := &gpuSuite{ + imageTag: *imageTag, + } + + e2e.Run(t, suite, suiteParams...) } func (v *gpuSuite) SetupSuite() { v.BaseSuite.SetupSuite() - v.Env().RemoteHost.MustExecute(fmt.Sprintf("docker pull %s", vectorAddDockerImg)) + v.Env().RemoteHost.MustExecute(fmt.Sprintf("docker pull %s", v.dockerImageName())) +} + +func (v *gpuSuite) dockerImageName() string { + return fmt.Sprintf("%s:%s", vectorAddDockerImg, v.imageTag) } // TODO: Extract this to common package? service_discovery uses it too @@ -97,6 +104,19 @@ type collectorStatus struct { RunnerStats runnerStats `json:"runnerStats"` } +func (v *gpuSuite) runCudaDockerWorkload() { + // Configure some defaults + vectorSize := 50000 + numLoops := 100 // Loop extra times to ensure the kernel runs for a bit + waitTimeSeconds := 5 // Give enough time to our monitor to hook the probes + binary := "/usr/local/bin/cuda-basic" + + cmd := fmt.Sprintf("docker run --rm --gpus all %s %s %d %d %d", v.dockerImageName(), binary, vectorSize, numLoops, waitTimeSeconds) + out, err := v.Env().RemoteHost.Execute(cmd) + v.Require().NoError(err) + v.Require().NotEmpty(out) +} + func (v *gpuSuite) TestGPUCheckIsEnabled() { statusOutput := v.Env().Agent.Client.Status(agentclient.WithArgs([]string{"collector", "--json"})) @@ -109,15 +129,21 @@ func (v *gpuSuite) TestGPUCheckIsEnabled() { v.Require().Equal(gpuCheckStatus.LastError, "") } -func (v *gpuSuite) TestVectorAddProgramDetected() { - vm := v.Env().RemoteHost +func (v *gpuSuite) TestGPUSysprobeEndpointIsResponding() { + v.EventuallyWithT(func(c *assert.CollectT) { + out, err := v.Env().RemoteHost.Execute("sudo curl -s --unix /opt/datadog-agent/run/sysprobe.sock http://unix/gpu/check") + assert.NoError(c, err) + assert.NotEmpty(c, out) + }, 2*time.Minute, 10*time.Second) +} - out, err := vm.Execute(fmt.Sprintf("docker run --rm --gpus all %s", vectorAddDockerImg)) - v.Require().NoError(err) - v.Require().NotEmpty(out) +func (v *gpuSuite) TestVectorAddProgramDetected() { + v.runCudaDockerWorkload() v.EventuallyWithT(func(c *assert.CollectT) { - metricNames := []string{"gpu.memory", "gpu.utilization", "gpu.memory.max"} + // We are not including "gpu.memory", as that represents the "current + // memory usage" and that might be zero at the time it's checked + metricNames := []string{"gpu.utilization", "gpu.memory.max"} for _, metricName := range metricNames { metrics, err := v.Env().FakeIntake.Client().FilterMetrics(metricName, client.WithMetricValueHigherThan(0)) assert.NoError(c, err) diff --git a/test/new-e2e/tests/npm/ecs_1host_test.go b/test/new-e2e/tests/npm/ecs_1host_test.go index a3183dac8dba3..ae617ac4040ae 100644 --- a/test/new-e2e/tests/npm/ecs_1host_test.go +++ b/test/new-e2e/tests/npm/ecs_1host_test.go @@ -10,17 +10,20 @@ import ( "github.com/pulumi/pulumi/sdk/v3/go/pulumi" + tifEcs "github.com/DataDog/test-infra-definitions/scenarios/aws/ecs" + "github.com/DataDog/datadog-agent/test/new-e2e/pkg/components" "github.com/DataDog/datadog-agent/test/new-e2e/pkg/e2e" "github.com/DataDog/datadog-agent/test/new-e2e/pkg/environments" envecs "github.com/DataDog/datadog-agent/test/new-e2e/pkg/environments/aws/ecs" - "github.com/DataDog/datadog-agent/pkg/util/testutil/flake" npmtools "github.com/DataDog/test-infra-definitions/components/datadog/apps/npm-tools" "github.com/DataDog/test-infra-definitions/components/datadog/ecsagentparams" "github.com/DataDog/test-infra-definitions/components/docker" ecsComp "github.com/DataDog/test-infra-definitions/components/ecs" + "github.com/DataDog/datadog-agent/pkg/util/testutil/flake" + "github.com/DataDog/test-infra-definitions/resources/aws" "github.com/DataDog/test-infra-definitions/scenarios/aws/ec2" ) @@ -67,7 +70,7 @@ func ecsHttpbinEnvProvisioner() e2e.PulumiEnvRunFunc[ecsHttpbinEnv] { params := envecs.GetProvisionerParams( envecs.WithAwsEnv(&awsEnv), - envecs.WithECSLinuxECSOptimizedNodeGroup(), + envecs.WithECSOptions(tifEcs.WithLinuxNodeGroup()), envecs.WithAgentOptions(ecsagentparams.WithAgentServiceEnvVariable("DD_SYSTEM_PROBE_NETWORK_ENABLED", "true")), envecs.WithWorkloadApp(func(e aws.Environment, clusterArn pulumi.StringInput) (*ecsComp.Workload, error) { testURL := "http://" + env.HTTPBinHost.Address + "/" diff --git a/test/new-e2e/tests/otel/otel-agent/sampling_test.go b/test/new-e2e/tests/otel/otel-agent/sampling_test.go index 7e4c50166ada1..98133826ee708 100644 --- a/test/new-e2e/tests/otel/otel-agent/sampling_test.go +++ b/test/new-e2e/tests/otel/otel-agent/sampling_test.go @@ -31,5 +31,5 @@ func TestOTelAgentSampling(t *testing.T) { } func (s *samplingTestSuite) TestSampling() { - utils.TestSampling(s) + utils.TestSampling(s, true) } diff --git a/test/new-e2e/tests/otel/otlp-ingest/pipelines_sampling_test.go b/test/new-e2e/tests/otel/otlp-ingest/pipelines_sampling_test.go index 861dcb7132a81..0db1211c09749 100644 --- a/test/new-e2e/tests/otel/otlp-ingest/pipelines_sampling_test.go +++ b/test/new-e2e/tests/otel/otlp-ingest/pipelines_sampling_test.go @@ -50,5 +50,5 @@ agents: } func (s *otlpIngestSamplingTestSuite) TestSampling() { - utils.TestSampling(s) + utils.TestSampling(s, false) } diff --git a/test/new-e2e/tests/otel/utils/config_utils.go b/test/new-e2e/tests/otel/utils/config_utils.go index 8f69ace313d17..3c1a80ab2aa18 100644 --- a/test/new-e2e/tests/otel/utils/config_utils.go +++ b/test/new-e2e/tests/otel/utils/config_utils.go @@ -9,8 +9,10 @@ package utils import ( "context" "encoding/json" + "github.com/DataDog/datadog-agent/pkg/util/testutil/flake" "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -20,6 +22,7 @@ import ( "k8s.io/apimachinery/pkg/fields" extension "github.com/DataDog/datadog-agent/comp/otelcol/ddflareextension/def" + "github.com/DataDog/datadog-agent/test/fakeintake/client/flare" ) // TestOTelAgentInstalled checks that the OTel Agent is installed in the test suite @@ -28,52 +31,75 @@ func TestOTelAgentInstalled(s OTelTestSuite) { assert.Contains(s.T(), agent.ObjectMeta.String(), "otel-agent") } +var otelFlareFiles = []string{ + "otel/otel-response.json", + "otel/otel-flare/customer.cfg", + "otel/otel-flare/env.cfg", + "otel/otel-flare/environment.json", + "otel/otel-flare/runtime.cfg", + "otel/otel-flare/runtime_override.cfg", + "otel/otel-flare/health_check/dd-autoconfigured.dat", + "otel/otel-flare/pprof/dd-autoconfigured_debug_pprof_heap.dat", + "otel/otel-flare/pprof/dd-autoconfigured_debug_pprof_allocs.dat", + // "otel/otel-flare/pprof/dd-autoconfigured_debug_pprof_profile.dat", + "otel/otel-flare/zpages/dd-autoconfigured_debug_tracez.dat", + "otel/otel-flare/zpages/dd-autoconfigured_debug_pipelinez.dat", + "otel/otel-flare/zpages/dd-autoconfigured_debug_extensionz.dat", + "otel/otel-flare/zpages/dd-autoconfigured_debug_featurez.dat", + "otel/otel-flare/zpages/dd-autoconfigured_debug_servicez.dat", + "otel/otel-flare/command.txt", + "otel/otel-flare/ext.txt", +} + // TestOTelFlare tests that the OTel Agent flare functionality works as expected func TestOTelFlare(s OTelTestSuite, providedCfg string, fullCfg string, sources string) { + flake.Mark(s.T()) err := s.Env().FakeIntake.Client().FlushServerAndResetAggregators() require.NoError(s.T(), err) - - s.T().Log("Starting flare") agent := getAgentPod(s) - stdout, stderr, err := s.Env().KubernetesCluster.KubernetesClient.PodExec("datadog", agent.Name, "agent", []string{"agent", "flare", "--email", "e2e@test.com", "--send"}) - require.NoError(s.T(), err, "Failed to execute flare") - require.Empty(s.T(), stderr) - require.NotNil(s.T(), stdout) - - s.T().Log("Getting latest flare") - flare, err := s.Env().FakeIntake.Client().GetLatestFlare() - require.NoError(s.T(), err, "Failed to get latest flare") - otelFolder, otelFlareFolder := false, false - var otelResponse string - for _, filename := range flare.GetFilenames() { - if strings.Contains(filename, "/otel/") { - otelFolder = true - } - if strings.Contains(filename, "/otel/otel-flare/") { - otelFlareFolder = true + + timeout := time.Now().Add(20 * time.Minute) + for i := 1; time.Now().Before(timeout); i++ { + s.T().Log("Starting flare") + stdout, stderr, err := s.Env().KubernetesCluster.KubernetesClient.PodExec("datadog", agent.Name, "agent", []string{"agent", "flare", "--email", "e2e@test.com", "--send"}) + require.NoError(s.T(), err, "Failed to execute flare") + require.Empty(s.T(), stderr) + require.NotNil(s.T(), stdout) + + s.T().Log("Getting latest flare") + flare, err := s.Env().FakeIntake.Client().GetLatestFlare() + require.NoError(s.T(), err) + otelflares := fetchFromFlare(s.T(), flare) + + if len(otelflares) < len(otelFlareFiles) { + s.T().Logf("Did not receive expected amount of OTel flares, expected %d, got %d, attempt %d", len(otelFlareFiles), len(otelflares), i) + time.Sleep(time.Minute) + continue } - if strings.Contains(filename, "otel/otel-response.json") { - otelResponse = filename + + for _, otelFlareFile := range otelFlareFiles { + assert.Contains(s.T(), otelflares, otelFlareFile) } - } - assert.True(s.T(), otelFolder) - assert.True(s.T(), otelFlareFolder) - otelResponseContent, err := flare.GetFileContent(otelResponse) - s.T().Log("Got flare otel-response.json", otelResponseContent) - require.NoError(s.T(), err) - var resp extension.Response - require.NoError(s.T(), json.Unmarshal([]byte(otelResponseContent), &resp)) + var resp extension.Response + require.NoError(s.T(), json.Unmarshal([]byte(otelflares["otel/otel-response.json"]), &resp)) - assert.Equal(s.T(), "otel-agent", resp.AgentCommand) - assert.Equal(s.T(), "Datadog Agent OpenTelemetry Collector", resp.AgentDesc) - assert.Equal(s.T(), "", resp.RuntimeOverrideConfig) + assert.Equal(s.T(), "otel-agent", resp.AgentCommand) + assert.Equal(s.T(), "Datadog Agent OpenTelemetry Collector", resp.AgentDesc) + assert.Equal(s.T(), "", resp.RuntimeOverrideConfig) - validateConfigs(s.T(), providedCfg, resp.CustomerConfig) - validateConfigs(s.T(), fullCfg, resp.RuntimeConfig) + validateConfigs(s.T(), providedCfg, resp.CustomerConfig) + validateConfigs(s.T(), fullCfg, resp.RuntimeConfig) - srcJSONStr, err := json.Marshal(resp.Sources) - require.NoError(s.T(), err) - assert.JSONEq(s.T(), sources, string(srcJSONStr)) + srcJSONStr, err := json.Marshal(resp.Sources) + require.NoError(s.T(), err) + assert.JSONEq(s.T(), sources, string(srcJSONStr)) + + assert.Contains(s.T(), otelflares["otel/otel-flare/health_check/dd-autoconfigured.dat"], `"status":"Server available"`) + return + } + + s.T().Error("Failed to collect all OTel flares after 20 minutes") + s.T().Fail() } func getAgentPod(s OTelTestSuite) corev1.Pod { @@ -85,6 +111,25 @@ func getAgentPod(s OTelTestSuite) corev1.Pod { return res.Items[0] } +func fetchFromFlare(t *testing.T, flare flare.Flare) map[string]string { + otelflares := make(map[string]string) + for _, filename := range flare.GetFilenames() { + if !strings.Contains(filename, "/otel/") { + continue + } + + if strings.HasSuffix(filename, ".json") || strings.HasSuffix(filename, ".dat") || strings.HasSuffix(filename, ".txt") || strings.HasSuffix(filename, ".cfg") { + cnt, err := flare.GetFileContent(filename) + require.NoError(t, err) + t.Log("Got otel flare: ", filename) + parts := strings.SplitN(filename, "/", 2) + require.Len(t, parts, 2) + otelflares[parts[1]] = cnt + } + } + return otelflares +} + func validateConfigs(t *testing.T, expectedCfg string, actualCfg string) { var actualConfRaw map[string]any require.NoError(t, yaml.Unmarshal([]byte(actualCfg), &actualConfRaw)) diff --git a/test/new-e2e/tests/otel/utils/pipelines_utils.go b/test/new-e2e/tests/otel/utils/pipelines_utils.go index 332137d5566de..fe1eeff147054 100644 --- a/test/new-e2e/tests/otel/utils/pipelines_utils.go +++ b/test/new-e2e/tests/otel/utils/pipelines_utils.go @@ -31,13 +31,14 @@ import ( ) const ( - calendarService = "calendar-rest-go" - telemetrygenService = "telemetrygen-job" - env = "e2e" - version = "1.0" - customAttribute = "custom.attribute" - customAttributeValue = "true" - logBody = "random date" + calendarService = "calendar-rest-go" + telemetrygenService = "telemetrygen-job" + telemetrygenTopLevelResource = "lets-go" + env = "e2e" + version = "1.0" + customAttribute = "custom.attribute" + customAttributeValue = "true" + logBody = "random date" ) // OTelTestSuite is an interface for the OTel e2e test suite. @@ -255,7 +256,7 @@ func TestHosts(s OTelTestSuite) { } // TestSampling tests that APM stats are correct when using probabilistic sampling -func TestSampling(s OTelTestSuite) { +func TestSampling(s OTelTestSuite, computeTopLevelBySpanKind bool) { ctx := context.Background() err := s.Env().FakeIntake.Client().FlushServerAndResetAggregators() require.NoError(s.T(), err) @@ -264,11 +265,11 @@ func TestSampling(s OTelTestSuite) { s.T().Log("Starting telemetrygen") createTelemetrygenJob(ctx, s, "traces", []string{"--traces", fmt.Sprint(numTraces)}) - TestAPMStats(s, numTraces) + TestAPMStats(s, numTraces, computeTopLevelBySpanKind) } // TestAPMStats checks that APM stats are received with the correct number of hits per traces given -func TestAPMStats(s OTelTestSuite, numTraces int) { +func TestAPMStats(s OTelTestSuite, numTraces int, computeTopLevelBySpanKind bool) { s.T().Log("Waiting for APM stats") var stats []*aggregator.APMStatsPayload var err error @@ -284,7 +285,9 @@ func TestAPMStats(s OTelTestSuite, numTraces int) { if cgs.Service == telemetrygenService { hasStatsForService = true assert.EqualValues(c, cgs.Hits, numTraces) - assert.EqualValues(c, cgs.TopLevelHits, numTraces) + if computeTopLevelBySpanKind || cgs.Resource == telemetrygenTopLevelResource { + assert.EqualValues(c, cgs.TopLevelHits, numTraces) + } } } } diff --git a/test/new-e2e/tests/process/ecs_test.go b/test/new-e2e/tests/process/ecs_test.go index 10c42d696a512..3e279decddbb2 100644 --- a/test/new-e2e/tests/process/ecs_test.go +++ b/test/new-e2e/tests/process/ecs_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" ecsComp "github.com/DataDog/test-infra-definitions/components/ecs" + tifEcs "github.com/DataDog/test-infra-definitions/scenarios/aws/ecs" "github.com/DataDog/datadog-agent/pkg/util/testutil/flake" "github.com/DataDog/datadog-agent/test/fakeintake/aggregator" @@ -43,7 +44,7 @@ func ecsEC2CPUStressProvisioner(runInCoreAgent bool) e2e.PulumiEnvRunFunc[ecsCPU params := ecs.GetProvisionerParams( ecs.WithAwsEnv(&awsEnv), - ecs.WithECSLinuxECSOptimizedNodeGroup(), + ecs.WithECSOptions(tifEcs.WithLinuxNodeGroup()), ecs.WithAgentOptions( ecsagentparams.WithAgentServiceEnvVariable("DD_PROCESS_CONFIG_PROCESS_COLLECTION_ENABLED", "true"), ecsagentparams.WithAgentServiceEnvVariable("DD_PROCESS_CONFIG_RUN_IN_CORE_AGENT_ENABLED", fmt.Sprintf("%t", runInCoreAgent)), diff --git a/test/new-e2e/tests/process/fargate_test.go b/test/new-e2e/tests/process/fargate_test.go index 61f90e618c1f4..4ead72974cc04 100644 --- a/test/new-e2e/tests/process/fargate_test.go +++ b/test/new-e2e/tests/process/fargate_test.go @@ -9,15 +9,17 @@ import ( "testing" "time" - "github.com/DataDog/datadog-agent/test/new-e2e/pkg/runner" "github.com/DataDog/test-infra-definitions/components/datadog/apps/cpustress" "github.com/DataDog/test-infra-definitions/resources/aws" "github.com/pulumi/pulumi/sdk/v3/go/auto" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/test/new-e2e/pkg/runner" + fakeintakeComp "github.com/DataDog/test-infra-definitions/components/datadog/fakeintake" ecsComp "github.com/DataDog/test-infra-definitions/components/ecs" + tifEcs "github.com/DataDog/test-infra-definitions/scenarios/aws/ecs" "github.com/DataDog/datadog-agent/pkg/util/testutil/flake" "github.com/DataDog/datadog-agent/test/fakeintake/aggregator" @@ -33,7 +35,7 @@ type ECSFargateSuite struct { func getFargateProvisioner(configMap runner.ConfigMap) e2e.TypedProvisioner[environments.ECS] { return ecs.Provisioner( - ecs.WithECSFargateCapacityProvider(), + ecs.WithECSOptions(tifEcs.WithFargateCapacityProvider()), ecs.WithFargateWorkloadApp(func(e aws.Environment, clusterArn pulumi.StringInput, apiKeySSMParamName pulumi.StringInput, fakeIntake *fakeintakeComp.Fakeintake) (*ecsComp.Workload, error) { return cpustress.FargateAppDefinition(e, clusterArn, apiKeySSMParamName, fakeIntake) }), diff --git a/test/new-e2e/tests/process/k8s_test.go b/test/new-e2e/tests/process/k8s_test.go index 16bfacf9d976e..1533bea01cb36 100644 --- a/test/new-e2e/tests/process/k8s_test.go +++ b/test/new-e2e/tests/process/k8s_test.go @@ -26,7 +26,6 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeClient "k8s.io/client-go/kubernetes" - "github.com/DataDog/datadog-agent/pkg/util/testutil/flake" "github.com/DataDog/datadog-agent/test/fakeintake/aggregator" "github.com/DataDog/datadog-agent/test/new-e2e/pkg/components" "github.com/DataDog/datadog-agent/test/new-e2e/pkg/e2e" @@ -86,10 +85,10 @@ func TestK8sTestSuite(t *testing.T) { func (s *K8sSuite) TestProcessCheck() { t := s.T() - assert.EventuallyWithT(t, func(*assert.CollectT) { - status := k8sAgentStatus(t, s.Env().KubernetesCluster) - assert.ElementsMatch(t, []string{"process", "rtprocess"}, status.ProcessAgentStatus.Expvars.Map.EnabledChecks) - }, 4*time.Minute, 10*time.Second) + assert.EventuallyWithT(t, func(c *assert.CollectT) { + status := k8sAgentStatus(c, s.Env().KubernetesCluster) + assert.ElementsMatch(c, []string{"process", "rtprocess"}, status.ProcessAgentStatus.Expvars.Map.EnabledChecks) + }, 5*time.Minute, 10*time.Second) var payloads []*aggregator.ProcessPayload assert.EventuallyWithT(t, func(c *assert.CollectT) { @@ -99,7 +98,7 @@ func (s *K8sSuite) TestProcessCheck() { // Wait for two payloads, as processes must be detected in two check runs to be returned assert.GreaterOrEqual(c, len(payloads), 2, "fewer than 2 payloads returned") - }, 2*time.Minute, 10*time.Second) + }, 5*time.Minute, 10*time.Second) assertProcessCollected(t, payloads, false, "stress-ng-cpu [run]") assertContainersCollected(t, payloads, []string{"stress-ng"}) @@ -122,8 +121,7 @@ func (s *K8sSuite) TestManualContainerCheck() { func (s *K8sSuite) TestProcessDiscoveryCheck() { t := s.T() - // PROCS-4327: Unexpected errors trying to get agent status - flake.Mark(t) + helmValues, err := createHelmValues(helmConfig{ ProcessDiscoveryCollection: true, }) @@ -142,13 +140,10 @@ func (s *K8sSuite) TestProcessDiscoveryCheck() { t.Logf("status: %+v\n", status) } }() - assert.EventuallyWithT(t, func(*assert.CollectT) { - status = k8sAgentStatus(t, s.Env().KubernetesCluster) - assert.ElementsMatch(t, []string{"process_discovery"}, status.ProcessAgentStatus.Expvars.Map.EnabledChecks) - }, 4*time.Minute, 10*time.Second) - - // Flush fake intake to remove any payloads which may have - s.Env().FakeIntake.Client().FlushServerAndResetAggregators() + assert.EventuallyWithT(t, func(c *assert.CollectT) { + status = k8sAgentStatus(c, s.Env().KubernetesCluster) + assert.ElementsMatch(c, []string{"process_discovery"}, status.ProcessAgentStatus.Expvars.Map.EnabledChecks) + }, 5*time.Minute, 10*time.Second) var payloads []*aggregator.ProcessDiscoveryPayload assert.EventuallyWithT(t, func(c *assert.CollectT) { @@ -156,15 +151,14 @@ func (s *K8sSuite) TestProcessDiscoveryCheck() { payloads, err = s.Env().FakeIntake.Client().GetProcessDiscoveries() assert.NoError(c, err, "failed to get process discovery payloads from fakeintake") assert.NotEmpty(c, payloads, "no process discovery payloads returned") - }, 2*time.Minute, 10*time.Second) + }, 5*time.Minute, 10*time.Second) assertProcessDiscoveryCollected(t, payloads, "stress-ng-cpu [run]") } func (s *K8sSuite) TestProcessCheckInCoreAgent() { t := s.T() - // PROCS-4327: Unexpected errors trying to get agent status - flake.Mark(t) + helmValues, err := createHelmValues(helmConfig{ ProcessCollection: true, RunInCoreAgent: true, @@ -184,16 +178,16 @@ func (s *K8sSuite) TestProcessCheckInCoreAgent() { t.Logf("status: %+v\n", status) } }() - assert.EventuallyWithT(t, func(*assert.CollectT) { - status = k8sAgentStatus(t, s.Env().KubernetesCluster) + assert.EventuallyWithT(t, func(c *assert.CollectT) { + status = k8sAgentStatus(c, s.Env().KubernetesCluster) // verify the standalone process-agent is not running - assert.NotEmpty(t, status.ProcessAgentStatus.Error, "status: %+v", status) - assert.Empty(t, status.ProcessAgentStatus.Expvars.Map.EnabledChecks) + assert.NotEmpty(c, status.ProcessAgentStatus.Error, "status: %+v", status) + assert.Empty(c, status.ProcessAgentStatus.Expvars.Map.EnabledChecks) // Verify the process component is running in the core agent - assert.ElementsMatch(t, []string{"process", "rtprocess"}, status.ProcessComponentStatus.Expvars.Map.EnabledChecks) - }, 4*time.Minute, 10*time.Second) + assert.ElementsMatch(c, []string{"process", "rtprocess"}, status.ProcessComponentStatus.Expvars.Map.EnabledChecks) + }, 5*time.Minute, 10*time.Second) // Flush fake intake to remove any payloads which may have s.Env().FakeIntake.Client().FlushServerAndResetAggregators() @@ -205,7 +199,7 @@ func (s *K8sSuite) TestProcessCheckInCoreAgent() { assert.NoError(c, err, "failed to get process payloads from fakeintake") // Wait for two payloads, as processes must be detected in two check runs to be returned assert.GreaterOrEqual(c, len(payloads), 2, "fewer than 2 payloads returned") - }, 2*time.Minute, 10*time.Second) + }, 5*time.Minute, 10*time.Second) assertProcessCollected(t, payloads, false, "stress-ng-cpu [run]") assertContainersCollected(t, payloads, []string{"stress-ng"}) @@ -215,9 +209,6 @@ func (s *K8sSuite) TestProcessCheckInCoreAgent() { func (s *K8sSuite) TestProcessCheckInCoreAgentWithNPM() { t := s.T() - // PROCS-4327: The process-agent container either fails to start or - // does not seem to run the connections check as expected. - flake.Mark(t) helmValues, err := createHelmValues(helmConfig{ ProcessCollection: true, @@ -239,11 +230,11 @@ func (s *K8sSuite) TestProcessCheckInCoreAgentWithNPM() { t.Logf("status: %+v\n", status) } }() - assert.EventuallyWithT(t, func(*assert.CollectT) { - status = k8sAgentStatus(t, s.Env().KubernetesCluster) - assert.ElementsMatch(t, []string{"process", "rtprocess"}, status.ProcessComponentStatus.Expvars.Map.EnabledChecks) - assert.ElementsMatch(t, []string{"connections"}, status.ProcessAgentStatus.Expvars.Map.EnabledChecks) - }, 4*time.Minute, 10*time.Second) + assert.EventuallyWithT(t, func(c *assert.CollectT) { + status = k8sAgentStatus(c, s.Env().KubernetesCluster) + assert.ElementsMatch(c, []string{"process", "rtprocess"}, status.ProcessComponentStatus.Expvars.Map.EnabledChecks) + assert.ElementsMatch(c, []string{"connections"}, status.ProcessAgentStatus.Expvars.Map.EnabledChecks) + }, 5*time.Minute, 10*time.Second) // Flush fake intake to remove any payloads which may have s.Env().FakeIntake.Client().FlushServerAndResetAggregators() @@ -256,7 +247,7 @@ func (s *K8sSuite) TestProcessCheckInCoreAgentWithNPM() { // Wait for two payloads, as processes must be detected in two check runs to be returned assert.GreaterOrEqual(c, len(payloads), 2, "fewer than 2 payloads returned") - }, 2*time.Minute, 10*time.Second) + }, 5*time.Minute, 10*time.Second) assertProcessCollected(t, payloads, false, "stress-ng-cpu [run]") assertProcessCollected(t, payloads, false, "process-agent") @@ -279,13 +270,13 @@ func execProcessAgentCheck(t *testing.T, cluster *components.KubernetesCluster, return stdout } -func k8sAgentStatus(t *testing.T, cluster *components.KubernetesCluster) AgentStatus { +func k8sAgentStatus(t assert.TestingT, cluster *components.KubernetesCluster) AgentStatus { agent := getAgentPod(t, cluster.Client()) stdout, stderr, err := cluster.KubernetesClient. PodExec(agent.Namespace, agent.Name, "agent", []string{"bash", "-c", "DD_LOG_LEVEL=OFF agent status --json"}) - require.NoError(t, err) + assert.NoError(t, err) assert.Empty(t, stderr) assert.NotNil(t, stdout, "failed to get agent status") @@ -296,11 +287,11 @@ func k8sAgentStatus(t *testing.T, cluster *components.KubernetesCluster) AgentSt return statusMap } -func getAgentPod(t *testing.T, client kubeClient.Interface) corev1.Pod { +func getAgentPod(t assert.TestingT, client kubeClient.Interface) corev1.Pod { res, err := client.CoreV1().Pods("datadog"). List(context.Background(), v1.ListOptions{LabelSelector: "app=dda-linux-datadog"}) - require.NoError(t, err) - require.NotEmpty(t, res.Items) + assert.NoError(t, err) + assert.NotEmpty(t, res.Items) return res.Items[0] } diff --git a/test/new-e2e/tests/process/linux_test.go b/test/new-e2e/tests/process/linux_test.go index 3c6c9f15784c0..7b5e093d5bf83 100644 --- a/test/new-e2e/tests/process/linux_test.go +++ b/test/new-e2e/tests/process/linux_test.go @@ -116,9 +116,9 @@ func (s *linuxTestSuite) TestProcessChecksInCoreAgent() { }, 1*time.Minute, 5*time.Second) // Verify that the process agent is not running - assert.EventuallyWithT(t, func(*assert.CollectT) { + assert.EventuallyWithT(t, func(c *assert.CollectT) { status := s.Env().RemoteHost.MustExecute("/opt/datadog-agent/embedded/bin/process-agent status") - assert.Contains(t, status, "The Process Agent is not running") + assert.Contains(c, status, "The Process Agent is not running") }, 1*time.Minute, 5*time.Second) // Flush fake intake to remove any payloads which may have diff --git a/test/new-e2e/tests/security-agent-functional/security_agent_test.go b/test/new-e2e/tests/security-agent-functional/security_agent_test.go index 94da861eb7fa6..545f11529f00e 100644 --- a/test/new-e2e/tests/security-agent-functional/security_agent_test.go +++ b/test/new-e2e/tests/security-agent-functional/security_agent_test.go @@ -51,9 +51,7 @@ func (v *vmSuite) SetupSuite() { currDir, err := os.Getwd() require.NoError(t, err) - reporoot, _ := filepath.Abs(filepath.Join(currDir, "..", "..", "..", "..")) - kitchenDir := filepath.Join(reporoot, "test", "kitchen", "site-cookbooks") - v.testspath = filepath.Join(kitchenDir, "dd-security-agent-check", "files", "tests") + v.testspath = filepath.Join(currDir, "artifacts") } func (v *vmSuite) TestSystemProbeCWSSuite() { diff --git a/test/new-e2e/tests/windows/install-test/upgrade_test.go b/test/new-e2e/tests/windows/install-test/upgrade_test.go index e4c5677cf7198..851b6a739f376 100644 --- a/test/new-e2e/tests/windows/install-test/upgrade_test.go +++ b/test/new-e2e/tests/windows/install-test/upgrade_test.go @@ -10,6 +10,7 @@ import ( "path/filepath" "slices" "strings" + "time" windowsCommon "github.com/DataDog/datadog-agent/test/new-e2e/tests/windows/common" windowsAgent "github.com/DataDog/datadog-agent/test/new-e2e/tests/windows/common/agent" @@ -17,6 +18,7 @@ import ( "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) @@ -331,14 +333,18 @@ func (s *testUpgradeFromV5Suite) installAgent5() { s.Require().NoError(err, "should install agent 5") // get agent info + // in loop because the agent may not be ready immediately after install/start installPath := windowsAgent.DefaultInstallPath - cmd := fmt.Sprintf(`& "%s\embedded\python.exe" "%s\agent\agent.py" info`, installPath, installPath) - out, err := host.Execute(cmd) - s.Require().NoError(err, "should get agent info") - s.T().Logf("Agent 5 info:\n%s", out) + s.Assert().EventuallyWithT(func(t *assert.CollectT) { + cmd := fmt.Sprintf(`& "%s\embedded\python.exe" "%s\agent\agent.py" info`, installPath, installPath) + out, err := host.Execute(cmd) + if !assert.NoError(t, err, "should get agent info") { + return + } + s.T().Logf("Agent 5 info:\n%s", out) + assert.Contains(t, out, agentPackage.AgentVersion(), "info should have agent 5 version") + }, 5*time.Minute, 5*time.Second, "should get agent 5 info") - // basic checks to ensure agent is functioning - s.Assert().Contains(out, agentPackage.AgentVersion(), "info should have agent 5 version") confPath := `C:\ProgramData\Datadog\datadog.conf` exists, err := host.FileExists(confPath) s.Require().NoError(err, "should check if datadog.conf exists") diff --git a/test/otel/go.mod b/test/otel/go.mod index 76543d05d11fe..8797c2aaccd70 100644 --- a/test/otel/go.mod +++ b/test/otel/go.mod @@ -31,6 +31,7 @@ replace ( github.com/DataDog/datadog-agent/comp/trace/compression/impl-gzip => ./../../comp/trace/compression/impl-gzip github.com/DataDog/datadog-agent/comp/trace/compression/impl-zstd => ./../../comp/trace/compression/impl-zstd github.com/DataDog/datadog-agent/pkg/aggregator/ckey => ../../pkg/aggregator/ckey + github.com/DataDog/datadog-agent/pkg/api => ../../pkg/api github.com/DataDog/datadog-agent/pkg/collector/check/defaults => ./../../pkg/collector/check/defaults github.com/DataDog/datadog-agent/pkg/config/env => ./../../pkg/config/env github.com/DataDog/datadog-agent/pkg/config/mock => ./../../pkg/config/mock @@ -92,7 +93,7 @@ replace ( ) require ( - github.com/DataDog/datadog-agent/comp/core/config v0.56.0-rc.3 + github.com/DataDog/datadog-agent/comp/core/config v0.57.1 github.com/DataDog/datadog-agent/comp/core/hostname/hostnameinterface v0.56.0-rc.3 github.com/DataDog/datadog-agent/comp/core/log/def v0.56.0-rc.1 github.com/DataDog/datadog-agent/comp/otelcol/logsagentpipeline v0.56.0-rc.3 @@ -109,8 +110,8 @@ require ( require ( github.com/DataDog/agent-payload/v5 v5.0.119 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/builder v0.56.0-rc.3 // indirect - github.com/DataDog/datadog-agent/comp/core/flare/types v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/builder v0.57.1 // indirect + github.com/DataDog/datadog-agent/comp/core/flare/types v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/secrets v0.57.1 // indirect github.com/DataDog/datadog-agent/comp/core/status v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/comp/core/telemetry v0.57.1 // indirect @@ -124,13 +125,14 @@ require ( github.com/DataDog/datadog-agent/comp/trace/compression/def v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/comp/trace/compression/impl-gzip v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/aggregator/ckey v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/api v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/collector/check/defaults v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/env v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/config/mock v0.58.0-devel // indirect github.com/DataDog/datadog-agent/pkg/config/nodetreemodel v0.60.0-devel // indirect github.com/DataDog/datadog-agent/pkg/config/structure v0.0.0-00010101000000-000000000000 // indirect github.com/DataDog/datadog-agent/pkg/config/teeconfig v0.60.0-devel // indirect - github.com/DataDog/datadog-agent/pkg/config/utils v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/config/utils v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/logs/auditor v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/logs/client v0.56.0-rc.3 // indirect github.com/DataDog/datadog-agent/pkg/logs/diagnostic v0.56.0-rc.3 // indirect @@ -173,7 +175,7 @@ require ( github.com/DataDog/datadog-agent/pkg/util/system v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/system/socket v0.57.1 // indirect github.com/DataDog/datadog-agent/pkg/util/winutil v0.57.1 // indirect - github.com/DataDog/datadog-agent/pkg/version v0.56.0-rc.3 // indirect + github.com/DataDog/datadog-agent/pkg/version v0.57.1 // indirect github.com/DataDog/datadog-api-client-go/v2 v2.26.0 // indirect github.com/DataDog/datadog-go/v5 v5.5.0 // indirect github.com/DataDog/dd-sensitive-data-scanner/sds-go/go v0.0.0-20240816154533-f7f9beb53a42 // indirect diff --git a/test/regression/README.md b/test/regression/README.md index fca1b33bce783..f4b51e3a4f87f 100644 --- a/test/regression/README.md +++ b/test/regression/README.md @@ -7,6 +7,12 @@ contains the experiments for Agent. A similar one exists in [Vector]. Please do add your own experiments, instructions below. If you have any questions do contact #single-machine-performance; we'll be glad to help. +## Quality Gate Experiments +Experiments prefixed with `quality_gate_` represent the strongest claims made +about the Agent and its performance. These are discussed in more detail on +[this +page](https://datadoghq.atlassian.net/wiki/spaces/agent/pages/4294836779/Performance+Quality+Gates) + ## Adding an Experiment In order for SMP's tooling to properly read a experiment directory please diff --git a/test/regression/cases/idle/experiment.yaml b/test/regression/cases/idle/experiment.yaml index 6ff80775cb802..dd57048f28f5d 100644 --- a/test/regression/cases/idle/experiment.yaml +++ b/test/regression/cases/idle/experiment.yaml @@ -1,5 +1,7 @@ # Agent 'out of the box' idle experiment. Represents an agent install with the # default configuration and no active workload. +# Further documentation: +# https://datadoghq.atlassian.net/wiki/spaces/agent/pages/4294836779/Performance+Quality+Gates#idle optimization_goal: memory erratic: false diff --git a/test/regression/cases/idle_all_features/experiment.yaml b/test/regression/cases/idle_all_features/experiment.yaml index b1cb6e02c0d62..ae7fad777485c 100644 --- a/test/regression/cases/idle_all_features/experiment.yaml +++ b/test/regression/cases/idle_all_features/experiment.yaml @@ -1,5 +1,7 @@ # Agent 'all features enabled' idle experiment. Represents an agent install with # all sub-agents enabled in configuration and no active workload. +# Further documentation: +# https://datadoghq.atlassian.net/wiki/spaces/agent/pages/4294836779/Performance+Quality+Gates#idle_all_features optimization_goal: memory erratic: false diff --git a/test/regression/cases/quality_gate_idle/experiment.yaml b/test/regression/cases/quality_gate_idle/experiment.yaml index f0cd01ba86e3b..2b1734aee788a 100644 --- a/test/regression/cases/quality_gate_idle/experiment.yaml +++ b/test/regression/cases/quality_gate_idle/experiment.yaml @@ -1,5 +1,7 @@ # Agent 'out of the box' idle experiment. Represents an agent install with the # default configuration and no active workload. +# Further documentation: +# https://datadoghq.atlassian.net/wiki/spaces/agent/pages/4294836779/Performance+Quality+Gates#idle optimization_goal: memory erratic: false diff --git a/test/regression/cases/quality_gate_idle_all_features/experiment.yaml b/test/regression/cases/quality_gate_idle_all_features/experiment.yaml index aec1d9bf04f22..273abeb153f25 100644 --- a/test/regression/cases/quality_gate_idle_all_features/experiment.yaml +++ b/test/regression/cases/quality_gate_idle_all_features/experiment.yaml @@ -1,5 +1,7 @@ # Agent 'all features enabled' idle experiment. Represents an agent install with # all sub-agents enabled in configuration and no active workload. +# Further documentation: +# https://datadoghq.atlassian.net/wiki/spaces/agent/pages/4294836779/Performance+Quality+Gates#idle_all_features optimization_goal: memory erratic: false diff --git a/tools/windows/DatadogAgentInstaller/CustomActions/PythonDistributionCustomAction.cs b/tools/windows/DatadogAgentInstaller/CustomActions/PythonDistributionCustomAction.cs index 4b293b50dee93..85fd1569703ab 100644 --- a/tools/windows/DatadogAgentInstaller/CustomActions/PythonDistributionCustomAction.cs +++ b/tools/windows/DatadogAgentInstaller/CustomActions/PythonDistributionCustomAction.cs @@ -37,7 +37,6 @@ private static ActionResult DecompressPythonDistribution( ISession session, string outputDirectoryName, string compressedDistributionFile, - string pythonDistributionName, int pythonDistributionSize) { var projectLocation = session.Property("PROJECTLOCATION"); @@ -64,7 +63,7 @@ private static ActionResult DecompressPythonDistribution( { using var actionRecord = new Record( "Decompress Python distribution", - $"Decompressing {pythonDistributionName} distribution", + "Decompressing distribution", "" ); session.Message(InstallMessage.ActionStart, actionRecord); @@ -133,7 +132,7 @@ private static ActionResult DecompressPythonDistributions(ISession session) { size = int.Parse(embedded3Size); } - return DecompressPythonDistribution(session, "embedded3", "embedded3.COMPRESSED", "Python 3", size); + return DecompressPythonDistribution(session, "embedded3", "embedded3.COMPRESSED", size); } public static ActionResult DecompressPythonDistributions(Session session)