From 53a586f58ba28b3a96b3374685757b4f1a0e89e5 Mon Sep 17 00:00:00 2001 From: ajasnosz <139114006+ajasnosz@users.noreply.github.com> Date: Thu, 19 Sep 2024 09:40:55 +0200 Subject: [PATCH] feat: support ipv6 (#1071) --- CHANGELOG.md | 1 + .../templates/traps/deployment.yaml | 11 ++ .../templates/traps/service.yaml | 13 +- .../values.schema.json | 12 ++ charts/splunk-connect-for-snmp/values.yaml | 6 + docs/configuration/trap-configuration.md | 7 + .../values-params-description.md | 8 +- docs/gettingstarted/enable-ipv6.md | 65 ++++++++++ docs/gettingstarted/mk8s/k8s-microk8s.md | 5 + mkdocs.yml | 1 + .../templates/traps/deployment.yaml | 4 + .../templates/traps/service.yaml | 5 +- .../templates/traps/deployment.yaml | 4 + .../templates/traps/service.yaml | 5 +- .../templates/traps/deployment.yaml | 4 + .../templates/traps/service.yaml | 5 +- .../templates/traps/deployment.yaml | 4 + .../templates/traps/service.yaml | 5 +- .../templates/traps/deployment.yaml | 4 + .../templates/traps/service.yaml | 5 +- .../templates/traps/deployment.yaml | 4 + .../templates/traps/service.yaml | 5 +- .../common/inventory_processor.py | 4 +- splunk_connect_for_snmp/snmp/auth.py | 17 ++- splunk_connect_for_snmp/snmp/manager.py | 10 +- splunk_connect_for_snmp/traps.py | 14 +- test/common/test_inventory_processor.py | 121 +++++++++++++++--- test/inventory/test_loader.py | 36 +++--- test/snmp/test_auth.py | 33 ++++- test/snmp/test_do_work.py | 8 +- 30 files changed, 362 insertions(+), 64 deletions(-) create mode 100644 docs/gettingstarted/enable-ipv6.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cedc195a..83720d5a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - add metrics dashboard ### Changed +- add support for IPv6 polling and traps for kubernetes deployment ### Fixed diff --git a/charts/splunk-connect-for-snmp/templates/traps/deployment.yaml b/charts/splunk-connect-for-snmp/templates/traps/deployment.yaml index a1ad20a37..8bd34ded8 100644 --- a/charts/splunk-connect-for-snmp/templates/traps/deployment.yaml +++ b/charts/splunk-connect-for-snmp/templates/traps/deployment.yaml @@ -84,10 +84,21 @@ spec: secretKeyRef: name: {{ include "splunk-connect-for-snmp.name" . }}-splunk key: hec_token + - name: IPv6_ENABLED + {{- if has "IPv6" .Values.traps.ipFamilies}} + value: "true" + {{ else }} + value: "false" + {{- end }} ports: - name: snmp-udp containerPort: 2162 protocol: UDP + {{- if has "IPv6" .Values.traps.ipFamilies}} + - name: snmp-udp6 + containerPort: 2163 + protocol: UDP + {{- end }} volumeMounts: - name: config mountPath: "/app/config" diff --git a/charts/splunk-connect-for-snmp/templates/traps/service.yaml b/charts/splunk-connect-for-snmp/templates/traps/service.yaml index b51fd48d5..967e0c646 100644 --- a/charts/splunk-connect-for-snmp/templates/traps/service.yaml +++ b/charts/splunk-connect-for-snmp/templates/traps/service.yaml @@ -8,6 +8,7 @@ metadata: annotations: {{- if .Values.traps.service.usemetallb }} metallb.universe.tf/allow-shared-ip: {{ .Values.traps.service.metallbsharingkey | default "splunk-connect" | quote }} + metallb.universe.tf/loadBalancerIPs: {{ .Values.traps.loadBalancerIP }} {{- end }} {{- if .Values.traps.service.annotations }} {{ toYaml .Values.traps.service.annotations | indent 4 }} @@ -20,7 +21,8 @@ spec: type: {{ .Values.traps.service.type }} externalTrafficPolicy: {{ .Values.traps.service.externalTrafficPolicy | default "Local" }} {{- if .Values.traps.loadBalancerIP }} - loadBalancerIP: {{ .Values.traps.loadBalancerIP }} + ipFamilyPolicy: {{ .Values.traps.ipFamilyPolicy }} + ipFamilies: {{ .Values.traps.ipFamilies | toYaml | nindent 2 }} {{- end }} ports: - port: {{ .Values.traps.service.port }} @@ -30,6 +32,15 @@ spec: targetPort: 2162 protocol: UDP name: snmp-udp + {{- if has "IPv6" .Values.traps.ipFamilies}} + - port: {{ .Values.traps.service.ipv6Port | default 2163}} + {{- if and .Values.traps.service.nodePort (eq .Values.traps.service.type "NodePort")}} + nodePort: {{ .Values.traps.service.ipv6NodePort | default 30003 }} + {{- end }} + targetPort: 2163 + protocol: UDP + name: snmp-udp6 + {{- end }} selector: {{- include "splunk-connect-for-snmp.traps.selectorLabels" . | nindent 4 }} {{- end -}} \ No newline at end of file diff --git a/charts/splunk-connect-for-snmp/values.schema.json b/charts/splunk-connect-for-snmp/values.schema.json index 6ac7bedda..db9dbe124 100644 --- a/charts/splunk-connect-for-snmp/values.schema.json +++ b/charts/splunk-connect-for-snmp/values.schema.json @@ -719,12 +719,24 @@ }, "nodePort": { "type": "integer" + }, + "ipv6Port": { + "type": "integer" + }, + "ipv6NodePort": { + "type": "integer" } } }, "loadBalancerIP": { "type": "string" }, + "ipFamilyPolicy": { + "type": "string" + }, + "ipFamilies": { + "type": "array" + }, "resources": { "type": "object", "additionalProperties": false, diff --git a/charts/splunk-connect-for-snmp/values.yaml b/charts/splunk-connect-for-snmp/values.yaml index f600042c5..d6b6c65f4 100644 --- a/charts/splunk-connect-for-snmp/values.yaml +++ b/charts/splunk-connect-for-snmp/values.yaml @@ -425,13 +425,19 @@ traps: # on a multi-node it's better to set this as NodePort and configure traps.service.nodePort type: LoadBalancer port: 162 + # ipv6Port: 2163 + # nodePort will be set only when type of service is a NodePort #nodePort: 30000 + #ipv6NodePort: 30003 #loadBalancerIP must be set to the IP address in the metallb pool. #It is required when service type is set to LoadBalancer. #loadBalancerIP: 18.117.100.37 loadBalancerIP: "" + ipFamilyPolicy: SingleStack + ipFamilies: + - IPv4 resources: {} # limits: diff --git a/docs/configuration/trap-configuration.md b/docs/configuration/trap-configuration.md index e321615fa..3f5eb2e58 100644 --- a/docs/configuration/trap-configuration.md +++ b/docs/configuration/trap-configuration.md @@ -94,6 +94,13 @@ See the following example: traps: loadBalancerIP: 10.202.4.202 ``` +If you have enabled the Ipv6 you need to pass IP addresses for both IPv4 and IPv6. +See the following example: + +```yaml +traps: + loadBalancerIP: 10.202.4.202,2001:0DB8:AC10:FE01:0000:0000:0000:0001 +``` If you want to use the SC4SNMP trap receiver in K8S cluster, configure `NodePort` instead. Use the following configuration: diff --git a/docs/configuration/values-params-description.md b/docs/configuration/values-params-description.md index 8d06ba782..0672b80af 100644 --- a/docs/configuration/values-params-description.md +++ b/docs/configuration/values-params-description.md @@ -161,10 +161,14 @@ Detailed documentation about configuring traps can be found in [Traps](../config | `service.usemetallb` | Enables using metallb | `true` | | `service.metallbsharingkey` | Sets metallb.universe.tf/allow-shared-ip annotation in trap service | `splunk-connect` | | `service.type` | [Kubernetes documentation](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) | `LoadBalancer` | -| `service.port` | Port of the service to use | `162` | +| `service.port` | Port of the service to use for IPv4 | `162` | | `service.nodePort` | Port when the `service.type` is `nodePort` | `30000` | | `service.externalTrafficPolicy` | Controls how Kubernetes routes traffic | `Local` | -| `loadBalancerIP` | Sets loadBalancer IP address in the metallb pool | | +| `service.ipv6Port` | Port of the service to use for IPv6 | `162` | +| `service.ipv6NodePort` | Port when the `service.type` is `nodePort` and IPv6 is enabled | `2163` | +| `loadBalancerIP` | Sets loadBalancer IP address in the metallb pool | `30001` | +| `ipFamilyPolicy` | Specifies if the service is dual stack or single stack | `SingleStack` | +| `ipFamilies` | Defines the address families used for chosen `ipFamilyPolicy` | `IPv4` | | `resources` | CPU and memory limits and requests for pod | | | `autoscaling.enabled` | Enables autoscaling for pods | `false` | | `autoscaling.minReplicas` | Minimum number of running pods when autoscaling is enabled | `1` | diff --git a/docs/gettingstarted/enable-ipv6.md b/docs/gettingstarted/enable-ipv6.md new file mode 100644 index 000000000..954f7bb41 --- /dev/null +++ b/docs/gettingstarted/enable-ipv6.md @@ -0,0 +1,65 @@ +# Enabling IPv6 for SC4SNMP + +Default installation of SC4SNMP does not support polling or receiving trap notifications from IPv6 addresses. To enable IPv6, follow instruction below. + +## Microk8s +To configure dual-stack network on microk8s follow instructions at [Microk8s page](https://microk8s.io/docs/how-to-dual-stack). +After completing the steps, you can follow the instruction at [Microk8s installation on Ubuntu](mk8s/k8s-microk8s.md#microk8s-installation-on-ubuntu) +to install microk8s. + +## Calico +The default CNI used for microk8s is Calico. For pods to be able to reach internet over IPv6, you need to enable +the `natOutgoing` parameter in ipv6 ip pool configuration from calico. +To set it create the yaml file with the following content: +``` +# calico-ippool.yaml +--- +apiVersion: crd.projectcalico.org/v1 +kind: IPPool +metadata: + name: default-ipv6-ippool +spec: + natOutgoing: true +``` +You can check with command `microk8s kubectl get ippools -n kube-system` the default name of the ip pool for IPv6. If it differs from `default-ipv6-ippool` you need to change the name in the yaml file. +Then apply the configuration with the following command: +``` +microk8s kubectl apply -f calico-ippool.yaml +``` + +After those changes you can restart the microk8s fot the changes to be applied with the following commands: +``` +microk8s stop +microk8s start +``` + +## Metallb +As of version `1.30` of microk8s, Metallb add-on does not support passing the IPv6 addresses in enable command. To +add the IPv6 addresses to your Metallb configuration, you can prepare the yaml file with configuration like below: +``` +# addresspool.yaml +--- +apiVersion: metallb.io/v1beta1 +kind: IPAddressPool +metadata: + name: default-addresspool + namespace: metallb-system +spec: + addresses: + - 1.1.1.1/32 + - 2001:0db8:ac10:fe01:0000:0000:0000:0001/128 +``` +You can check with command `microk8s kubectl get ipaddresspool -n metallb-system` the default name of the ip address pool created in metallb. If it differs from `default-addresspool` you need to change the name in the yaml file. +You can add the single ip or subnets for both IPv4 and IPv6 under `spec.addresses` section. After preparing the yaml file, apply the configuration with the following command: +``` +microk8s kubectl apply -f addresspool.yaml +``` + +## SC4SNMP +To configure traps to receive notification from IPv4 and IPv6 addresses, you need to add the following configuration to the `values.yaml` file: +``` +traps: + ipFamilyPolicy: RequireDualStack + ipFamilies: ["IPv4", "IPv6"] +``` +Default trap port for notifications for IPv6 is `2163`. You can change it to any other port if needed with `traps.service.ipv6Port` parameter. \ No newline at end of file diff --git a/docs/gettingstarted/mk8s/k8s-microk8s.md b/docs/gettingstarted/mk8s/k8s-microk8s.md index ba87eddd7..23adcef02 100644 --- a/docs/gettingstarted/mk8s/k8s-microk8s.md +++ b/docs/gettingstarted/mk8s/k8s-microk8s.md @@ -19,6 +19,11 @@ Three node minimum per node: The following quick start guidance is based on Ubuntu 20.04LTS with MicroK8s and internet access. See other deployment options in the MicroK8s [documentation](https://microk8s.io/docs), including offline and with proxy. +## Enabling IPv6 + +If you plan to poll or receive trap notifications from IPv6 addresses, firstly check the instructions for [enabling +IPv6](../enable-ipv6.md). + ## Install MicroK8s using Snap ```bash diff --git a/mkdocs.yml b/mkdocs.yml index 90be6fede..d63b669f7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -41,6 +41,7 @@ nav: - Platform Microk8s: "gettingstarted/mk8s/k8s-microk8s.md" - Install Splunk OpenTelemetry Collector for Kubernetes: "gettingstarted/sck-installation.md" - Install SC4SNMP: "gettingstarted/sc4snmp-installation.md" + - Enable IPv6: "gettingstarted/enable-ipv6.md" - Configuration: - Deployment: "configuration/deployment-configuration.md" - Configurable values: "configuration/values-params-description.md" diff --git a/rendered/manifests/tests/splunk-connect-for-snmp/templates/traps/deployment.yaml b/rendered/manifests/tests/splunk-connect-for-snmp/templates/traps/deployment.yaml index e405f5f39..2126ed8ad 100644 --- a/rendered/manifests/tests/splunk-connect-for-snmp/templates/traps/deployment.yaml +++ b/rendered/manifests/tests/splunk-connect-for-snmp/templates/traps/deployment.yaml @@ -56,6 +56,8 @@ spec: value: "http://release-name-mibserver/standard.txt" - name: LOG_LEVEL value: INFO + - name: PYSNMP_DEBUG + value: "" - name: SPLUNK_HEC_SCHEME value: "https" - name: SPLUNK_HEC_HOST @@ -71,6 +73,8 @@ spec: secretKeyRef: name: splunk-connect-for-snmp-splunk key: hec_token + - name: IPv6_ENABLED + value: "false" ports: - name: snmp-udp containerPort: 2162 diff --git a/rendered/manifests/tests/splunk-connect-for-snmp/templates/traps/service.yaml b/rendered/manifests/tests/splunk-connect-for-snmp/templates/traps/service.yaml index d65075ff0..399b57e52 100644 --- a/rendered/manifests/tests/splunk-connect-for-snmp/templates/traps/service.yaml +++ b/rendered/manifests/tests/splunk-connect-for-snmp/templates/traps/service.yaml @@ -12,11 +12,14 @@ metadata: app.kubernetes.io/managed-by: Helm annotations: metallb.universe.tf/allow-shared-ip: "splunk-connect" + metallb.universe.tf/loadBalancerIPs: 10.202.6.213 spec: type: LoadBalancer externalTrafficPolicy: Local - loadBalancerIP: 10.202.6.213 + ipFamilyPolicy: SingleStack + ipFamilies: + - IPv4 ports: - port: 162 targetPort: 2162 diff --git a/rendered/manifests/tests_autoscaling_enabled/splunk-connect-for-snmp/templates/traps/deployment.yaml b/rendered/manifests/tests_autoscaling_enabled/splunk-connect-for-snmp/templates/traps/deployment.yaml index 213f7f6bb..75437ab27 100644 --- a/rendered/manifests/tests_autoscaling_enabled/splunk-connect-for-snmp/templates/traps/deployment.yaml +++ b/rendered/manifests/tests_autoscaling_enabled/splunk-connect-for-snmp/templates/traps/deployment.yaml @@ -55,6 +55,8 @@ spec: value: "http://release-name-mibserver/standard.txt" - name: LOG_LEVEL value: INFO + - name: PYSNMP_DEBUG + value: "" - name: SPLUNK_HEC_SCHEME value: "https" - name: SPLUNK_HEC_HOST @@ -70,6 +72,8 @@ spec: secretKeyRef: name: splunk-connect-for-snmp-splunk key: hec_token + - name: IPv6_ENABLED + value: "false" ports: - name: snmp-udp containerPort: 2162 diff --git a/rendered/manifests/tests_autoscaling_enabled/splunk-connect-for-snmp/templates/traps/service.yaml b/rendered/manifests/tests_autoscaling_enabled/splunk-connect-for-snmp/templates/traps/service.yaml index d65075ff0..399b57e52 100644 --- a/rendered/manifests/tests_autoscaling_enabled/splunk-connect-for-snmp/templates/traps/service.yaml +++ b/rendered/manifests/tests_autoscaling_enabled/splunk-connect-for-snmp/templates/traps/service.yaml @@ -12,11 +12,14 @@ metadata: app.kubernetes.io/managed-by: Helm annotations: metallb.universe.tf/allow-shared-ip: "splunk-connect" + metallb.universe.tf/loadBalancerIPs: 10.202.6.213 spec: type: LoadBalancer externalTrafficPolicy: Local - loadBalancerIP: 10.202.6.213 + ipFamilyPolicy: SingleStack + ipFamilies: + - IPv4 ports: - port: 162 targetPort: 2162 diff --git a/rendered/manifests/tests_autoscaling_enabled_deprecated/splunk-connect-for-snmp/templates/traps/deployment.yaml b/rendered/manifests/tests_autoscaling_enabled_deprecated/splunk-connect-for-snmp/templates/traps/deployment.yaml index 213f7f6bb..75437ab27 100644 --- a/rendered/manifests/tests_autoscaling_enabled_deprecated/splunk-connect-for-snmp/templates/traps/deployment.yaml +++ b/rendered/manifests/tests_autoscaling_enabled_deprecated/splunk-connect-for-snmp/templates/traps/deployment.yaml @@ -55,6 +55,8 @@ spec: value: "http://release-name-mibserver/standard.txt" - name: LOG_LEVEL value: INFO + - name: PYSNMP_DEBUG + value: "" - name: SPLUNK_HEC_SCHEME value: "https" - name: SPLUNK_HEC_HOST @@ -70,6 +72,8 @@ spec: secretKeyRef: name: splunk-connect-for-snmp-splunk key: hec_token + - name: IPv6_ENABLED + value: "false" ports: - name: snmp-udp containerPort: 2162 diff --git a/rendered/manifests/tests_autoscaling_enabled_deprecated/splunk-connect-for-snmp/templates/traps/service.yaml b/rendered/manifests/tests_autoscaling_enabled_deprecated/splunk-connect-for-snmp/templates/traps/service.yaml index d65075ff0..399b57e52 100644 --- a/rendered/manifests/tests_autoscaling_enabled_deprecated/splunk-connect-for-snmp/templates/traps/service.yaml +++ b/rendered/manifests/tests_autoscaling_enabled_deprecated/splunk-connect-for-snmp/templates/traps/service.yaml @@ -12,11 +12,14 @@ metadata: app.kubernetes.io/managed-by: Helm annotations: metallb.universe.tf/allow-shared-ip: "splunk-connect" + metallb.universe.tf/loadBalancerIPs: 10.202.6.213 spec: type: LoadBalancer externalTrafficPolicy: Local - loadBalancerIP: 10.202.6.213 + ipFamilyPolicy: SingleStack + ipFamilies: + - IPv4 ports: - port: 162 targetPort: 2162 diff --git a/rendered/manifests/tests_enable_ui/splunk-connect-for-snmp/templates/traps/deployment.yaml b/rendered/manifests/tests_enable_ui/splunk-connect-for-snmp/templates/traps/deployment.yaml index e405f5f39..2126ed8ad 100644 --- a/rendered/manifests/tests_enable_ui/splunk-connect-for-snmp/templates/traps/deployment.yaml +++ b/rendered/manifests/tests_enable_ui/splunk-connect-for-snmp/templates/traps/deployment.yaml @@ -56,6 +56,8 @@ spec: value: "http://release-name-mibserver/standard.txt" - name: LOG_LEVEL value: INFO + - name: PYSNMP_DEBUG + value: "" - name: SPLUNK_HEC_SCHEME value: "https" - name: SPLUNK_HEC_HOST @@ -71,6 +73,8 @@ spec: secretKeyRef: name: splunk-connect-for-snmp-splunk key: hec_token + - name: IPv6_ENABLED + value: "false" ports: - name: snmp-udp containerPort: 2162 diff --git a/rendered/manifests/tests_enable_ui/splunk-connect-for-snmp/templates/traps/service.yaml b/rendered/manifests/tests_enable_ui/splunk-connect-for-snmp/templates/traps/service.yaml index d65075ff0..399b57e52 100644 --- a/rendered/manifests/tests_enable_ui/splunk-connect-for-snmp/templates/traps/service.yaml +++ b/rendered/manifests/tests_enable_ui/splunk-connect-for-snmp/templates/traps/service.yaml @@ -12,11 +12,14 @@ metadata: app.kubernetes.io/managed-by: Helm annotations: metallb.universe.tf/allow-shared-ip: "splunk-connect" + metallb.universe.tf/loadBalancerIPs: 10.202.6.213 spec: type: LoadBalancer externalTrafficPolicy: Local - loadBalancerIP: 10.202.6.213 + ipFamilyPolicy: SingleStack + ipFamilies: + - IPv4 ports: - port: 162 targetPort: 2162 diff --git a/rendered/manifests/tests_only_traps/splunk-connect-for-snmp/templates/traps/deployment.yaml b/rendered/manifests/tests_only_traps/splunk-connect-for-snmp/templates/traps/deployment.yaml index e405f5f39..2126ed8ad 100644 --- a/rendered/manifests/tests_only_traps/splunk-connect-for-snmp/templates/traps/deployment.yaml +++ b/rendered/manifests/tests_only_traps/splunk-connect-for-snmp/templates/traps/deployment.yaml @@ -56,6 +56,8 @@ spec: value: "http://release-name-mibserver/standard.txt" - name: LOG_LEVEL value: INFO + - name: PYSNMP_DEBUG + value: "" - name: SPLUNK_HEC_SCHEME value: "https" - name: SPLUNK_HEC_HOST @@ -71,6 +73,8 @@ spec: secretKeyRef: name: splunk-connect-for-snmp-splunk key: hec_token + - name: IPv6_ENABLED + value: "false" ports: - name: snmp-udp containerPort: 2162 diff --git a/rendered/manifests/tests_only_traps/splunk-connect-for-snmp/templates/traps/service.yaml b/rendered/manifests/tests_only_traps/splunk-connect-for-snmp/templates/traps/service.yaml index d65075ff0..399b57e52 100644 --- a/rendered/manifests/tests_only_traps/splunk-connect-for-snmp/templates/traps/service.yaml +++ b/rendered/manifests/tests_only_traps/splunk-connect-for-snmp/templates/traps/service.yaml @@ -12,11 +12,14 @@ metadata: app.kubernetes.io/managed-by: Helm annotations: metallb.universe.tf/allow-shared-ip: "splunk-connect" + metallb.universe.tf/loadBalancerIPs: 10.202.6.213 spec: type: LoadBalancer externalTrafficPolicy: Local - loadBalancerIP: 10.202.6.213 + ipFamilyPolicy: SingleStack + ipFamilies: + - IPv4 ports: - port: 162 targetPort: 2162 diff --git a/rendered/manifests/tests_probes_enabled/splunk-connect-for-snmp/templates/traps/deployment.yaml b/rendered/manifests/tests_probes_enabled/splunk-connect-for-snmp/templates/traps/deployment.yaml index e405f5f39..2126ed8ad 100644 --- a/rendered/manifests/tests_probes_enabled/splunk-connect-for-snmp/templates/traps/deployment.yaml +++ b/rendered/manifests/tests_probes_enabled/splunk-connect-for-snmp/templates/traps/deployment.yaml @@ -56,6 +56,8 @@ spec: value: "http://release-name-mibserver/standard.txt" - name: LOG_LEVEL value: INFO + - name: PYSNMP_DEBUG + value: "" - name: SPLUNK_HEC_SCHEME value: "https" - name: SPLUNK_HEC_HOST @@ -71,6 +73,8 @@ spec: secretKeyRef: name: splunk-connect-for-snmp-splunk key: hec_token + - name: IPv6_ENABLED + value: "false" ports: - name: snmp-udp containerPort: 2162 diff --git a/rendered/manifests/tests_probes_enabled/splunk-connect-for-snmp/templates/traps/service.yaml b/rendered/manifests/tests_probes_enabled/splunk-connect-for-snmp/templates/traps/service.yaml index d65075ff0..399b57e52 100644 --- a/rendered/manifests/tests_probes_enabled/splunk-connect-for-snmp/templates/traps/service.yaml +++ b/rendered/manifests/tests_probes_enabled/splunk-connect-for-snmp/templates/traps/service.yaml @@ -12,11 +12,14 @@ metadata: app.kubernetes.io/managed-by: Helm annotations: metallb.universe.tf/allow-shared-ip: "splunk-connect" + metallb.universe.tf/loadBalancerIPs: 10.202.6.213 spec: type: LoadBalancer externalTrafficPolicy: Local - loadBalancerIP: 10.202.6.213 + ipFamilyPolicy: SingleStack + ipFamilies: + - IPv4 ports: - port: 162 targetPort: 2162 diff --git a/splunk_connect_for_snmp/common/inventory_processor.py b/splunk_connect_for_snmp/common/inventory_processor.py index 5e8c3a4c2..0a87cb599 100644 --- a/splunk_connect_for_snmp/common/inventory_processor.py +++ b/splunk_connect_for_snmp/common/inventory_processor.py @@ -33,7 +33,7 @@ def transform_key_to_address(target): if ":" in target: - address, port = target.split(":") + address, port = target.rsplit(":", 1) else: return target, 161 return address, int(port) @@ -41,7 +41,7 @@ def transform_key_to_address(target): def transform_address_to_key(address, port): if not port or int(port) == 161: - return address + return f"{address}:161" else: return f"{address}:{port}" diff --git a/splunk_connect_for_snmp/snmp/auth.py b/splunk_connect_for_snmp/snmp/auth.py index f53e62f55..bb762d4fb 100644 --- a/splunk_connect_for_snmp/snmp/auth.py +++ b/splunk_connect_for_snmp/snmp/auth.py @@ -20,6 +20,7 @@ CommunityData, ContextData, SnmpEngine, + Udp6TransportTarget, UdpTransportTarget, UsmUserData, getCmd, @@ -54,9 +55,7 @@ def get_secret_value( def get_security_engine_id(logger, ir: InventoryRecord, snmp_engine: SnmpEngine): observer_context: Dict[Any, Any] = {} - transport_target = UdpTransportTarget( - (ir.address, ir.port), timeout=UDP_CONNECTION_TIMEOUT - ) + transport_target = setup_transport_target(ir) # Register a callback to be invoked at specified execution point of # SNMP Engine and passed local variables at execution point's local scope @@ -87,6 +86,18 @@ def get_security_engine_id(logger, ir: InventoryRecord, snmp_engine: SnmpEngine) return security_engine_id +def setup_transport_target(ir): + if ":" in ir.address: + transport = Udp6TransportTarget( + (ir.address, ir.port), timeout=UDP_CONNECTION_TIMEOUT + ) + else: + transport = UdpTransportTarget( + (ir.address, ir.port), timeout=UDP_CONNECTION_TIMEOUT + ) + return transport + + def fetch_security_engine_id(observer_context, error_indication, ipaddress): if "securityEngineId" in observer_context: return observer_context["securityEngineId"] diff --git a/splunk_connect_for_snmp/snmp/manager.py b/splunk_connect_for_snmp/snmp/manager.py index 5f2445cf7..264738f84 100644 --- a/splunk_connect_for_snmp/snmp/manager.py +++ b/splunk_connect_for_snmp/snmp/manager.py @@ -38,7 +38,7 @@ import pymongo from celery import Task from celery.utils.log import get_task_logger -from pysnmp.hlapi import SnmpEngine, UdpTransportTarget, bulkCmd, getCmd +from pysnmp.hlapi import SnmpEngine, bulkCmd, getCmd from pysnmp.smi import compiler, view from pysnmp.smi.rfc1902 import ObjectIdentity, ObjectType from requests_cache import MongoCache @@ -46,7 +46,7 @@ from splunk_connect_for_snmp.common.hummanbool import human_bool from splunk_connect_for_snmp.common.inventory_record import InventoryRecord from splunk_connect_for_snmp.common.requests import CachedLimiterSession -from splunk_connect_for_snmp.snmp.auth import get_auth +from splunk_connect_for_snmp.snmp.auth import get_auth, setup_transport_target from splunk_connect_for_snmp.snmp.context import get_context_data from splunk_connect_for_snmp.snmp.exceptions import SnmpActionError @@ -99,7 +99,7 @@ def return_address_and_port(target): if ":" in target: - address_tuple = target.split(":") + address_tuple = target.rsplit(":", 1) return address_tuple[0], int(address_tuple[1]) else: return target, 161 @@ -335,9 +335,7 @@ def do_work( auth_data = get_auth(logger, ir, self.snmpEngine) context_data = get_context_data() - transport = UdpTransportTarget( - (ir.address, ir.port), timeout=UDP_CONNECTION_TIMEOUT - ) + transport = setup_transport_target(ir) metrics: Dict[str, Any] = {} if not varbinds_get and not varbinds_bulk: diff --git a/splunk_connect_for_snmp/traps.py b/splunk_connect_for_snmp/traps.py index 5222cf8e4..1b567d0de 100644 --- a/splunk_connect_for_snmp/traps.py +++ b/splunk_connect_for_snmp/traps.py @@ -18,6 +18,7 @@ from pysnmp.proto.api import v2c +from splunk_connect_for_snmp.common.hummanbool import human_bool from splunk_connect_for_snmp.snmp.auth import get_secret_value with suppress(ImportError, OSError): @@ -34,7 +35,7 @@ from celery import Celery, chain from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider -from pysnmp.carrier.asyncio.dgram import udp +from pysnmp.carrier.asyncio.dgram import udp, udp6 from pysnmp.entity import config, engine from pysnmp.entity.rfc3413 import ntfrcv @@ -49,7 +50,7 @@ SECURITY_ENGINE_ID_LIST = os.getenv("SNMP_V3_SECURITY_ENGINE_ID", "80003a8c04").split( "," ) - +IPv6_ENABLED = human_bool(os.getenv("IPv6_ENABLED", "false").lower()) LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") PYSNMP_DEBUG = os.getenv("PYSNMP_DEBUG", "") @@ -83,6 +84,7 @@ debug.Debug(*enabled_debug_flags, options={"loggerName": logger}) ) + # //using rabbitmq as the message broker app = Celery("sc4snmp_traps") app.config_from_object("splunk_connect_for_snmp.celery_config") @@ -164,6 +166,14 @@ def main(): udp.domainName, udp.UdpTransport().openServerMode(("0.0.0.0", 2162)), ) + + if IPv6_ENABLED: + config.addTransport( + snmp_engine, + udp6.domainName, + udp6.Udp6Transport().openServerMode(("::", 2163)), + ) + with open(CONFIG_PATH, encoding="utf-8") as file: config_base = yaml.safe_load(file) idx = 0 diff --git a/test/common/test_inventory_processor.py b/test/common/test_inventory_processor.py index e4b337191..24cf83bf9 100644 --- a/test/common/test_inventory_processor.py +++ b/test/common/test_inventory_processor.py @@ -13,10 +13,16 @@ mock_inventory_only_address = """address 54.234.85.76""" +mock_inventory_only_address_ipv6 = """address +2001:0db8:ac10:fe01::0001""" + mock_inventory_host_same_as_in_group = """address,port,version,community,secret,security_engine,walk_interval,profiles,smart_profiles,delete group1,,2c,public,,,1805,group_profile,False,False 0.0.0.0,,2c,public,,,1805,solo_profile1,False,False -0.0.0.0,1161,2c,public,,,1805,solo_profile2,False,False""" +0.0.0.0,1161,2c,public,,,1805,solo_profile2,False,False +2001:0db8:ac10:fe01::0001,,2c,public,,,1805,solo_profile3,False,False +2001:0db8:ac10:fe01:0000:0000:0000:0001,1166,2c,public,,,1805,solo_profile4,False,False +""" class TestInventoryProcessor(TestCase): @@ -47,10 +53,30 @@ def test_transform_key_to_address(self): self.assertEqual(("123.0.0.1", 777), transform_key_to_address("123.0.0.1:777")) self.assertEqual(("123.0.0.1", 161), transform_key_to_address("123.0.0.1:161")) self.assertEqual(("123.0.0.1", 161), transform_key_to_address("123.0.0.1")) + self.assertEqual( + ("2001:0db8:ac10:fe01:0000:0000:0000:0001", 161), + transform_key_to_address("2001:0db8:ac10:fe01:0000:0000:0000:0001:161"), + ) + self.assertEqual( + ("2001:0db8:ac10:fe01:0000:0000:0000:0001", 333), + transform_key_to_address("2001:0db8:ac10:fe01:0000:0000:0000:0001:333"), + ) + self.assertEqual( + ("2001:0db8:ac10:fe01::0001", 161), + transform_key_to_address("2001:0db8:ac10:fe01::0001:161"), + ) def test_transform_address_to_key(self): self.assertEqual(transform_address_to_key("127.0.0.1", 333), "127.0.0.1:333") - self.assertEqual(transform_address_to_key("127.0.0.1", 161), "127.0.0.1") + self.assertEqual(transform_address_to_key("127.0.0.1", 161), "127.0.0.1:161") + self.assertEqual( + transform_address_to_key("2001:0db8:ac10:fe01::0001", 161), + "2001:0db8:ac10:fe01::0001:161", + ) + self.assertEqual( + transform_address_to_key("2001:0db8:ac10:fe01:0000:0000:0000:0001", 333), + "2001:0db8:ac10:fe01:0000:0000:0000:0001:333", + ) def test_return_hosts_from_deleted_groups_one_host(self): previous_groups = { @@ -80,6 +106,34 @@ def test_return_hosts_from_deleted_groups_one_host(self): ["1.1.1.1:162"], ) + def test_return_hosts_from_deleted_groups_one_host_ipv6(self): + previous_groups = { + "group1": [ + {"address": "2001:0db8:ac10:fe01::0001", "port": 161}, + {"address": "2001:0db8:bc10:fe03:0000:0000:0000:0001", "port": 999}, + ], + "switches": [ + {"address": "fd02::ae84:454f:3e03:4c80", "port": 161}, + {"address": "fd01::bc60:000f:4e02:3c70", "port": 162}, + ], + } + new_groups = { + "group1": [ + {"address": "2001:0db8:ac10:fe01::0001", "port": 161}, + {"address": "2001:0db8:bc10:fe03:0000:0000:0000:0001", "port": 999}, + ], + "switches": [{"address": "fd02::ae84:454f:3e03:4c80", "port": 161}], + } + + self.assertEqual( + return_hosts_from_deleted_groups( + previous_groups, + new_groups, + {"group1": {"port": 161}, "switches": {"port": 161}}, + ), + ["fd01::bc60:000f:4e02:3c70:162"], + ) + def test_return_hosts_from_deleted_groups_whole_group(self): previous_groups = { "group1": [ @@ -104,7 +158,7 @@ def test_return_hosts_from_deleted_groups_whole_group(self): new_groups, {"group1": 161, "switches": 161}, ), - ["12.22.23.33", "1.1.1.1:162"], + ["12.22.23.33:161", "1.1.1.1:162"], ) def test_return_hosts_from_deleted_groups_one_host_and_group(self): @@ -128,7 +182,7 @@ def test_return_hosts_from_deleted_groups_one_host_and_group(self): new_groups, {"group1": 161, "switches": 161}, ), - ["123.0.0.1", "178.8.8.1:999", "1.1.1.1:162"], + ["123.0.0.1:161", "178.8.8.1:999", "1.1.1.1:162"], ) def test_return_hosts_empty(self): @@ -283,6 +337,17 @@ def test_process_line_group(self): inventory_processor.process_line(source_record) inventory_processor.get_group_hosts.assert_called_with(source_record, "group1") + @patch( + "builtins.open", + new_callable=mock_open, + read_data=mock_inventory_only_address_ipv6, + ) + def test_process_line_host_ipv6(self, m_inventory): + source_record = {"address": "2001:0db8:ac10:fe01::0001"} + inventory_processor = InventoryProcessor(Mock(), Mock(), Mock()) + inventory_processor.get_all_hosts() + self.assertEqual(inventory_processor.inventory_records, [source_record]) + @mock.patch( "splunk_connect_for_snmp.common.collection_manager.CONFIG_FROM_MONGO", False, @@ -302,6 +367,7 @@ def test_ignore_line_host_configured_in_group(self, m_load_element): "group1": [ {"address": "0.0.0.0", "port": "161"}, {"address": "127.0.0.1", "port": "161"}, + {"address": "2001:0db8:ac10:fe01::0001", "port": "161"}, ] } ] @@ -335,6 +401,19 @@ def test_ignore_line_host_configured_in_group(self, m_load_element): "delete": "False", "group": "group1", }, + { + "address": "2001:0db8:ac10:fe01::0001", + "port": "161", + "version": "2c", + "community": "public", + "secret": "", + "security_engine": "", + "walk_interval": "1805", + "profiles": "group_profile", + "smart_profiles": "False", + "delete": "False", + "group": "group1", + }, { "address": "0.0.0.0", "port": "1161", @@ -347,6 +426,18 @@ def test_ignore_line_host_configured_in_group(self, m_load_element): "smart_profiles": "False", "delete": "False", }, + { + "address": "2001:0db8:ac10:fe01:0000:0000:0000:0001", + "port": "1166", + "version": "2c", + "community": "public", + "secret": "", + "security_engine": "", + "walk_interval": "1805", + "profiles": "solo_profile4", + "smart_profiles": "False", + "delete": "False", + }, ] inventory_processor.get_all_hosts() self.assertEqual(expected, inventory_processor.inventory_records) @@ -374,39 +465,37 @@ def test_return_walk_profile_more_than_one(self): def test_return_walk_profile_no_walk_in_inventory(self): inventory_profiles = ["generic_switch"] inventory_record_manager = InventoryRecordManager(Mock(), Mock(), Mock()) - self.assertEqual( + self.assertIsNone( inventory_record_manager.return_walk_profile( self.profiles, inventory_profiles - ), - None, + ) ) def test_return_walk_profile_no_walk_in_config(self): inventory_profiles = ["generic_switch", "walk2"] inventory_record_manager = InventoryRecordManager(Mock(), Mock(), Mock()) - self.assertEqual( + self.assertIsNone( inventory_record_manager.return_walk_profile( self.profiles, inventory_profiles - ), - None, + ) ) def test_return_walk_profile_no_config(self): inventory_profiles = ["generic_switch", "walk2"] inventory_record_manager = InventoryRecordManager(Mock(), Mock(), Mock()) - self.assertEqual( - inventory_record_manager.return_walk_profile({}, inventory_profiles), None + self.assertIsNone( + inventory_record_manager.return_walk_profile({}, inventory_profiles) ) def test_return_walk_profile_no_config_no_inventory(self): inventory_profiles = [] inventory_record_manager = InventoryRecordManager(Mock(), Mock(), Mock()) - self.assertEqual( - inventory_record_manager.return_walk_profile({}, inventory_profiles), None + self.assertIsNone( + inventory_record_manager.return_walk_profile({}, inventory_profiles) ) def test_return_walk_profile_no_inventory(self): inventory_record_manager = InventoryRecordManager(Mock(), Mock(), Mock()) - self.assertEqual( - inventory_record_manager.return_walk_profile(self.profiles, []), None + self.assertIsNone( + inventory_record_manager.return_walk_profile(self.profiles, []) ) diff --git a/test/inventory/test_loader.py b/test/inventory/test_loader.py index a31c013ab..c970626e7 100644 --- a/test/inventory/test_loader.py +++ b/test/inventory/test_loader.py @@ -152,13 +152,13 @@ def test_walk_task_for_port_161(self): result = gen_walk_task(inventory_record) - self.assertEqual("sc4snmp;192.68.0.1;walk", result["name"]) + self.assertEqual("sc4snmp;192.68.0.1:161;walk", result["name"]) self.assertEqual("splunk_connect_for_snmp.snmp.tasks.walk", result["task"]) - self.assertEqual("192.68.0.1", result["target"]) + self.assertEqual("192.68.0.1:161", result["target"]) self.assertEqual([], result["args"]) self.assertEqual( { - "address": "192.68.0.1", + "address": "192.68.0.1:161", "profile": None, "chain_of_tasks_expiry_time": chain_of_tasks_expiry_time, }, @@ -250,10 +250,10 @@ def test_load_new_record_small_walk( periodic_obj_mock = Mock() m_taskManager.return_value = periodic_obj_mock m_load_profiles.return_value = profiles - self.assertEqual(False, load()) + self.assertFalse(load()) self.assertEqual( { - "address": "192.168.0.1", + "address": "192.168.0.1:161", "profile": "walk2", "chain_of_tasks_expiry_time": 120, }, @@ -305,7 +305,7 @@ def test_load_new_record( periodic_obj_mock = Mock() m_taskManager.return_value = periodic_obj_mock m_load_profiles.return_value = default_profiles - self.assertEqual(False, load()) + self.assertFalse(load()) periodic_obj_mock.manage_task.assert_called_with(**expected_managed_task) @@ -354,7 +354,7 @@ def test_load_modified_record( periodic_obj_mock = Mock() m_taskManager.return_value = periodic_obj_mock m_load_profiles.return_value = default_profiles - self.assertEqual(False, load()) + self.assertFalse(load()) periodic_obj_mock.manage_task.assert_called_with(**expected_managed_task) @@ -405,7 +405,7 @@ def test_load_unchanged_record( periodic_obj_mock.did_expiry_time_change.return_value = False m_migrate.return_value = False m_load_profiles.return_value = default_profiles - self.assertEqual(False, load()) + self.assertFalse(load()) periodic_obj_mock.manage_task.assert_not_called() @@ -458,7 +458,7 @@ def test_load_unchanged_record_with_new_expiry_time( m_taskManager.return_value = periodic_obj_mock periodic_obj_mock.did_expiry_time_change.return_value = True m_load_profiles.return_value = default_profiles - self.assertEqual(False, load()) + self.assertFalse(load()) periodic_obj_mock.manage_task.assert_called_with(**expected_managed_task) @@ -504,7 +504,7 @@ def test_ignoring_comment( m_taskManager.return_value = periodic_obj_mock m_taskManager.get_chain_of_task_expiry.return_value = 180 m_load_profiles.return_value = default_profiles - self.assertEqual(False, load()) + self.assertFalse(load()) m_mongo_collection.assert_not_called() periodic_obj_mock.manage_task.assert_not_called() @@ -550,16 +550,16 @@ def test_deleting_record( periodic_obj_mock = Mock() m_taskManager.return_value = periodic_obj_mock m_load_profiles.return_value = default_profiles - self.assertEqual(False, load()) + self.assertFalse(load()) - periodic_obj_mock.delete_all_tasks_of_host.assert_called_with("192.168.0.1") + periodic_obj_mock.delete_all_tasks_of_host.assert_called_with("192.168.0.1:161") m_delete.assert_called_with({"address": "192.168.0.1", "port": 161}) calls = m_remove.call_args_list self.assertEqual(2, len(calls)) - self.assertEqual(({"address": "192.168.0.1"},), calls[0].args) - self.assertEqual(({"address": "192.168.0.1"},), calls[1].args) + self.assertEqual(({"address": "192.168.0.1:161"},), calls[0].args) + self.assertEqual(({"address": "192.168.0.1:161"},), calls[1].args) @mock.patch( "splunk_connect_for_snmp.common.inventory_processor.CONFIG_FROM_MONGO", False @@ -606,7 +606,7 @@ def test_deleting_record_non_default_port( periodic_obj_mock = Mock() m_taskManager.return_value = periodic_obj_mock m_load_profiles.return_value = default_profiles - self.assertEqual(False, load()) + self.assertFalse(load()) periodic_obj_mock.delete_all_tasks_of_host.assert_called_with("192.168.0.1:345") m_delete.assert_called_with({"address": "192.168.0.1", "port": 345}) @@ -669,11 +669,11 @@ def test_inventory_errors( m_manage_task.side_effect = Exception("Boom!") m_load_profiles.return_value = default_profiles - self.assertEqual(True, load()) + self.assertTrue(load()) def test_transform_address_to_key_161(self): - self.assertEqual(transform_address_to_key("127.0.0.1", 161), "127.0.0.1") - self.assertEqual(transform_address_to_key("127.0.0.1", "161"), "127.0.0.1") + self.assertEqual(transform_address_to_key("127.0.0.1", 161), "127.0.0.1:161") + self.assertEqual(transform_address_to_key("127.0.0.1", "161"), "127.0.0.1:161") def test_transform_address_to_key(self): self.assertEqual(transform_address_to_key("127.0.0.1", 32), "127.0.0.1:32") diff --git a/test/snmp/test_auth.py b/test/snmp/test_auth.py index 771b78292..fe21be8e2 100644 --- a/test/snmp/test_auth.py +++ b/test/snmp/test_auth.py @@ -1,5 +1,5 @@ from unittest import TestCase -from unittest.mock import Mock, mock_open, patch +from unittest.mock import MagicMock, Mock, mock_open, patch from pysnmp.entity.config import ( usmAesBlumenthalCfb192Protocol, @@ -18,6 +18,7 @@ get_auth_v3, get_secret_value, get_security_engine_id, + setup_transport_target, ) from splunk_connect_for_snmp.snmp.exceptions import SnmpActionError @@ -269,8 +270,8 @@ def test_get_auth_v3_noauthnopriv(self, m_get_secret_value, m_exists): result = get_auth_v3(logger, ir, snmpEngine) security_engine_result = OctetString(hexValue="80003a8c04") self.assertEqual("secret1", result.userName) - self.assertEqual(None, result.authKey) - self.assertEqual(None, result.privKey) + self.assertIsNone(result.authKey) + self.assertIsNone(result.privKey) self.assertEqual("noAuthNoPriv", result.securityLevel) self.assertEqual(usmNoAuthProtocol, result.authProtocol) self.assertEqual(usmNoPrivProtocol, result.privProtocol) @@ -299,7 +300,7 @@ def test_get_auth_v3_authnopriv(self, m_get_secret_value, m_exists): security_engine_result = OctetString(hexValue="80003a8c04") self.assertEqual("secret1", result.userName) self.assertEqual("secret2", result.authKey) - self.assertEqual(None, result.privKey) + self.assertIsNone(result.privKey) self.assertEqual("authNoPriv", result.securityLevel) self.assertEqual(usmHMAC128SHA224AuthProtocol, result.authProtocol) self.assertEqual(usmNoPrivProtocol, result.privProtocol) @@ -335,3 +336,27 @@ def test_get_auth_3(self, m_get_auth): ir.version = "3" get_auth(Mock(), ir, Mock()) m_get_auth.assert_called() + + @patch("splunk_connect_for_snmp.snmp.auth.Udp6TransportTarget") + @patch("splunk_connect_for_snmp.snmp.auth.UdpTransportTarget") + def test_setup_transport_target_ipv4( + self, m_setup_udp_transport_target, m_setup_udp6_transport_target + ): + ir.address = "127.0.0.1" + ir.port = 161 + m_setup_udp_transport_target.return_value = "UDP4" + m_setup_udp6_transport_target.return_value = "UDP6" + transport = setup_transport_target(ir) + self.assertEqual("UDP4", transport) + + @patch("splunk_connect_for_snmp.snmp.auth.Udp6TransportTarget") + @patch("splunk_connect_for_snmp.snmp.auth.UdpTransportTarget") + def test_setup_transport_target_ipv6( + self, m_setup_udp_transport_target, m_setup_udp6_transport_target + ): + ir.address = "2001:0db8:ac10:fe01::0001" + ir.port = 161 + m_setup_udp_transport_target.return_value = "UDP4" + m_setup_udp6_transport_target.return_value = "UDP6" + transport = setup_transport_target(ir) + self.assertEqual("UDP6", transport) diff --git a/test/snmp/test_do_work.py b/test/snmp/test_do_work.py index f3cb03cf6..92c9132d4 100644 --- a/test/snmp/test_do_work.py +++ b/test/snmp/test_do_work.py @@ -29,7 +29,7 @@ class TestDoWork(TestCase): @patch("mongolock.MongoLock.release", MagicMock()) @patch("splunk_connect_for_snmp.snmp.auth.get_auth", None) @patch("splunk_connect_for_snmp.snmp.manager.get_context_data", MagicMock()) - @patch("splunk_connect_for_snmp.snmp.manager.UdpTransportTarget", MagicMock()) + @patch("splunk_connect_for_snmp.snmp.manager.setup_transport_target", MagicMock()) def test_do_work_no_work_to_do(self): poller = Poller.__new__(Poller) poller.last_modified = 1609675634 @@ -57,7 +57,7 @@ def test_do_work_no_work_to_do(self): @patch("mongolock.MongoLock.release", MagicMock()) @patch("splunk_connect_for_snmp.snmp.auth.get_auth", None) @patch("splunk_connect_for_snmp.snmp.manager.get_context_data", MagicMock()) - @patch("splunk_connect_for_snmp.snmp.manager.UdpTransportTarget", MagicMock()) + @patch("splunk_connect_for_snmp.snmp.manager.setup_transport_target", MagicMock()) @patch("splunk_connect_for_snmp.snmp.manager.bulkCmd") @patch("splunk_connect_for_snmp.snmp.manager.getCmd") @patch("splunk_connect_for_snmp.common.collection_manager.ProfilesManager") @@ -93,7 +93,7 @@ def test_do_work_bulk(self, load_profiles, getCmd, bulkCmd): @patch("mongolock.MongoLock.release", MagicMock()) @patch("splunk_connect_for_snmp.snmp.auth.get_auth", None) @patch("splunk_connect_for_snmp.snmp.manager.get_context_data", MagicMock()) - @patch("splunk_connect_for_snmp.snmp.manager.UdpTransportTarget", MagicMock()) + @patch("splunk_connect_for_snmp.snmp.manager.setup_transport_target", MagicMock()) @patch("splunk_connect_for_snmp.snmp.manager.bulkCmd") @patch("splunk_connect_for_snmp.snmp.manager.getCmd") @patch( @@ -136,7 +136,7 @@ def test_do_work_get(self, load_profiles, getCmd, bulkCmd): @patch("mongolock.MongoLock.release", MagicMock()) @patch("splunk_connect_for_snmp.snmp.auth.get_auth", None) @patch("splunk_connect_for_snmp.snmp.manager.get_context_data", MagicMock()) - @patch("splunk_connect_for_snmp.snmp.manager.UdpTransportTarget", MagicMock()) + @patch("splunk_connect_for_snmp.snmp.manager.setup_transport_target", MagicMock()) @patch("splunk_connect_for_snmp.snmp.manager.bulkCmd") @patch("splunk_connect_for_snmp.snmp.manager.getCmd") @patch(