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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 91 additions & 32 deletions .azure-pipelines/docker-sonic-mgmt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,25 @@ schedules:
- cron: "0 8 * * *"
branches:
include:
- master
- 202511
always: true

trigger: none
pr:
branches:
include:
- master
- 202511
paths:
include:
- dockers/docker-sonic-mgmt
- .azure-pipelines/docker-sonic-mgmt.yml

resources:
repositories:
- repository: sonic-mgmt
type: github
name: sonic-net/sonic-mgmt
ref: master
ref: 202511
endpoint: sonic-net

parameters:
Expand Down Expand Up @@ -57,9 +58,7 @@ stages:

make NOBUSTER=1 NOBULLSEYE=1 SONIC_BUILD_JOBS=$(nproc) DEFAULT_CONTAINER_REGISTRY=publicmirror.azurecr.io ENABLE_DOCKER_BASE_PULL=y configure PLATFORM=generic DOCKER_BUILDKIT=0
make -f Makefile.work BLDENV=bookworm SONIC_BUILD_JOBS=$(nproc) DEFAULT_CONTAINER_REGISTRY=publicmirror.azurecr.io ENABLE_DOCKER_BASE_PULL=y target/docker-sonic-mgmt.gz
cp target -r $(Build.ArtifactStagingDirectory)/target
docker load -i target/docker-sonic-mgmt.gz
docker tag docker-sonic-mgmt $REGISTRY_SERVER/docker-sonic-mgmt:latest
cp -r target $(Build.ArtifactStagingDirectory)/target
env:
REGISTRY_SERVER: ${{ parameters.registry_url }}
displayName: Build docker-sonic-mgmt.gz
Expand All @@ -68,48 +67,108 @@ stages:
artifact: 'docker-sonic-mgmt'
displayName: "Archive docker image sonic-mgmt"

- job: validate_docker_image_and_upload
- bash: |
set -ex
docker load -i $(Build.ArtifactStagingDirectory)/target/docker-sonic-mgmt.gz
docker tag docker-sonic-mgmt:latest $REGISTRY_SERVER/docker-sonic-mgmt:202511-lastbuild
docker images
env:
REGISTRY_SERVER: ${{ parameters.registry_url }}
displayName: 'Load and tag docker-sonic-mgmt as 202511-lastbuild'

- task: Docker@2
displayName: 'Push docker-sonic-mgmt:202511-lastbuild to registry'
condition: succeeded()
inputs:
containerRegistry: ${{ parameters.registry_conn }}
repository: docker-sonic-mgmt
command: push
tags: 202511-lastbuild

- stage: SecurityScan
dependsOn: Build
condition: and(succeeded(), in(dependencies.Build.result, 'Succeeded'))
jobs:
- job: trivy_scan
displayName: "[OPTIONAL] Trivy vulnerability scan (docker-sonic-mgmt)"
pool: sonicso1ES-amd64
timeoutInMinutes: 360
dependsOn: Build
continueOnError: true
timeoutInMinutes: 60
steps:
- checkout: sonic-mgmt
clean: true
fetchDepth: 0
displayName: 'Checkout sonic-mgmt'

- download: current
artifact: 'docker-sonic-mgmt'
displayName: "Download docker image sonic-mgmt"

- script: |
set -ex

docker load -i $(Pipeline.Workspace)/docker-sonic-mgmt/target/docker-sonic-mgmt.gz

cd ansible
sudo ./setup-management-network.sh -d
cd ../
docker rm -f sonic-mgmt

./setup-container.sh -n sonic-mgmt -d /data -i docker-sonic-mgmt -v

docker exec sonic-mgmt bash -c "echo 'Container is running' && ps aux"
displayName: 'Setup sonic-mgmt docker container and verify'
TRIVY_VERSION="0.70.0"
curl -fLO https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.deb
sudo apt install -y ./trivy_${TRIVY_VERSION}_Linux-64bit.deb
trivy --version
displayName: "Install Trivy"
- script: |
set -x
trivy image \
--input $(Pipeline.Workspace)/docker-sonic-mgmt/target/docker-sonic-mgmt.gz \
--scanners vuln \
--severity MEDIUM,HIGH,CRITICAL \
--ignore-unfixed \
--exit-code 1 \
--format table \
--no-progress \
--timeout 30m \
--output $(Build.ArtifactStagingDirectory)/trivy-docker-sonic-mgmt.txt
TRIVY_EXIT=$?
echo ""
echo "=== Trivy Scan Results (docker-sonic-mgmt) ==="
cat $(Build.ArtifactStagingDirectory)/trivy-docker-sonic-mgmt.txt
exit $TRIVY_EXIT
displayName: "Trivy scan docker-sonic-mgmt"
- publish: $(Build.ArtifactStagingDirectory)/trivy-docker-sonic-mgmt.txt
artifact: trivy-scan-results
displayName: "Publish Trivy scan results"
condition: always()

- stage: Test
dependsOn: Build
condition: and(succeeded(), in(dependencies.Build.result, 'Succeeded'))
variables:
- group: SONiC-Elastictest
- name: BUILD_BRANCH
value: $(Build.SourceBranchName)
jobs:
- template: .azure-pipelines/pr_test_template.yml@sonic-mgmt
parameters:
CHECKOUT_SONIC_MGMT: true
OVERRIDE_PARAMS:
REPO_NAME: "sonic-mgmt"
SETUP_CONTAINER_PARAMS: "-i ${{ parameters.registry_url }}/docker-sonic-mgmt:202511-lastbuild"

- stage: Publish
dependsOn: Test
condition: and(not(canceled()), in(dependencies.Test.result, 'Succeeded', 'SucceededWithIssues'))
jobs:
- job: PublishAsLatest
pool: sonicso1ES-amd64
timeoutInMinutes: 60
steps:
- download: current
artifact: 'docker-sonic-mgmt'
displayName: "Download docker-sonic-mgmt image"

- bash: |
set -ex

docker tag docker-sonic-mgmt:latest $REGISTRY_SERVER/docker-sonic-mgmt:latest
docker load -i $(Pipeline.Workspace)/docker-sonic-mgmt/target/docker-sonic-mgmt.gz
docker tag docker-sonic-mgmt:latest $REGISTRY_SERVER/docker-sonic-mgmt:202511
docker images
env:
REGISTRY_SERVER: ${{ parameters.registry_url }}
displayName: 'Tag docker-sonic-mgmt'
displayName: 'Load and tag docker-sonic-mgmt as 202511'

- task: Docker@2
displayName: Upload image
displayName: 'Push docker-sonic-mgmt:202511 to registry'
condition: succeeded()
inputs:
containerRegistry: ${{ parameters.registry_conn }}
repository: docker-sonic-mgmt
command: push
tags: latest
tags: 202511
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
From e323263795a0af4c9c61992bd7a3347d8928db39 Mon Sep 17 00:00:00 2001
From: Xin Wang <xiwang5@microsoft.com>
Date: Thu, 14 Sep 2023 16:52:54 +0800
Subject: [PATCH] Fix getattr AttributeError in multi-thread scenario

When multi-thread is used, the plugin loader may raise AttributeError
while getting "ActionModule" from an action plugin.
From 94dd505c5e54341414dcb3b02bd50acef302b4eb Mon Sep 17 00:00:00 2001
From: Sai Kiran <110003254+opcoder0@users.noreply.github.com>
Date: Fri, 15 May 2026 14:40:48 +1000
Subject: [PATCH] When multi-thread is used, the plugin loader may raise
AttributeError while getting "ActionModule" from an action plugin.

The reason is that cache is used while loading module. Before a module
is fully loaded, it is already put into the sys.modules cache. When another
Expand All @@ -13,34 +11,35 @@ module from the sys.modules cache. Then while getting "ActionModule"
attribute from this module, exception AttributeError could be raised.

Signed-off-by: Xin Wang <xiwang5@microsoft.com>
Signed-off-by: Sai Kiran <110003254+opcoder0@users.noreply.github.com>
---
lib/ansible/plugins/loader.py | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
lib/ansible/plugins/loader.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lib/ansible/plugins/loader.py b/lib/ansible/plugins/loader.py
index 74bdeb5719..251531b62e 100644
index e12ec1b9ea..fe7dc25443 100644
--- a/lib/ansible/plugins/loader.py
+++ b/lib/ansible/plugins/loader.py
@@ -801,15 +801,14 @@ class PluginLoader:
warnings.simplefilter("ignore", RuntimeWarning)
spec = importlib.util.spec_from_file_location(to_native(full_name), to_native(path))
@@ -934,14 +934,15 @@ class PluginLoader:
spec = importlib.util.spec_from_file_location(to_native(python_module_name), to_native(path))
module = importlib.util.module_from_spec(spec)
-
- # mimic import machinery; make the module-being-loaded available in sys.modules during import
- # and remove if there's a failure...
- sys.modules[full_name] = module
-
- sys.modules[python_module_name] = module
try:
spec.loader.exec_module(module)
+ # mimic import machinery; make the module-being-loaded available in sys.modules during import
+ # and remove if there's a failure...
+ sys.modules[full_name] = module
+ sys.modules[python_module_name] = module
except Exception:
- del sys.modules[full_name]
+ if full_name in sys.modules:
+ del sys.modules[full_name]
- del sys.modules[python_module_name]
+ if python_module_name in sys.modules:
+ del sys.modules[python_module_name]
raise

return module
--
2.25.1
--
2.54.0.windows.1

27 changes: 20 additions & 7 deletions dockers/docker-sonic-mgmt/Dockerfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ FROM {{ prefix }}ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y \
apt-transport-https \
apt-utils \
bats \
Expand Down Expand Up @@ -39,7 +41,10 @@ RUN apt-get update && apt-get install -y \
sudo \
tcpdump \
telnet \
vim
vim \
&& apt-get autoremove -y \
&& apt-get autoclean \
&& rm -rf /var/lib/apt/lists/*

# Install uv - a fast Python package manager that replaces pip/venv/wheel.
# This eliminates the need for python3-pip, python3-venv, and python3-wheel
Expand All @@ -58,15 +63,15 @@ RUN sed -i 's|^PATH="|PATH="/opt/venv/bin:|' /etc/environment \
RUN uv pip install --no-cache \
aiohttp \
allure-pytest \
ansible==11.10.0 \
ansible==13.6.0 \
azure-storage-blob \
azure-kusto-data \
azure-kusto-ingest \
defusedxml \
celery[redis] \
cffi \
contextlib2 \
cryptography \
"cryptography>=48.0.1" \
ctypesgen \
debugpy \
dpkt \
Expand All @@ -89,14 +94,16 @@ RUN uv pip install --no-cache \
ncclient \
netaddr \
netmiko \
opentelemetry-api==1.27.0 \
opentelemetry-sdk==1.27.0 \
opentelemetry-exporter-otlp==1.27.0 \
opentelemetry-api==1.41.0 \
opentelemetry-sdk==1.41.0 \
opentelemetry-exporter-otlp==1.41.0 \
pandas \
paramiko \
passlib \
pexpect \
prettytable \
"protobuf>=5.29.6,<6" \
"pygnmi==0.8.15" \
psutil \
ptf==0.10.0 \
pyasn1 \
Expand Down Expand Up @@ -129,6 +136,7 @@ RUN uv pip install --no-cache \
tabulate \
textfsm \
thrift \
kubernetes \
&& wget https://github.com/nanomsg/nanomsg/archive/refs/tags/1.2.1.tar.gz \
&& tar xvfz 1.2.1.tar.gz \
&& cd nanomsg-1.2.1 \
Expand All @@ -154,6 +162,11 @@ RUN install -m 0755 -d /etc/apt/keyrings \
&& apt-get install -y docker-ce-cli \
&& curl -sL https://aka.ms/InstallAzureCLIDeb | bash

# Patch Azure CLI's bundled cryptography for CVE-2026-39892 and GHSA-537c-gmf6-5ccf (bundled OpenSSL)
RUN az_site_packages=$(/opt/az/bin/python -c "import site; print(site.getsitepackages()[0])") \
&& /opt/az/bin/python -m pip install --no-cache-dir --target "$az_site_packages" 'cryptography>=48.0.1' \
&& find "$az_site_packages" -name 'cryptography-4[0-7].*' -type d -exec rm -rf {} + 2>/dev/null; true

# Install dash-api
RUN tmpdir=$(mktemp -d) \
&& python_site_packages=$(python3 -c "import site; print(site.getsitepackages()[0])") \
Expand Down
Loading