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
7 changes: 5 additions & 2 deletions sonic_package_manager/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class PackageEntry:
built_in: Boolean flag whether the package is built in.
image_id: Image ID for this package or None if package
is not installed.
tag: Tag for this package or None if package is not installed.
"""

name: str
Expand All @@ -41,6 +42,7 @@ class PackageEntry:
installed: bool = False
built_in: bool = False
image_id: Optional[str] = None
tag: Optional[str] = None


def package_from_dict(name: str, package_info: Dict) -> PackageEntry:
Expand All @@ -55,10 +57,10 @@ def package_from_dict(name: str, package_info: Dict) -> PackageEntry:
installed = package_info.get('installed', False)
built_in = package_info.get('built-in', False)
image_id = package_info.get('image-id')

tag = package_info.get('tag')
return PackageEntry(name, repository, description,
default_reference, version, installed,
built_in, image_id)
built_in, image_id, tag)


def package_to_dict(package: PackageEntry) -> Dict:
Expand All @@ -72,6 +74,7 @@ def package_to_dict(package: PackageEntry) -> Dict:
'installed': package.installed,
'built-in': package.built_in,
'image-id': package.image_id,
'tag': package.tag,
}


Expand Down
1 change: 1 addition & 0 deletions sonic_package_manager/service_creator/creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ def generate_container_mgmt(self, package: Package):
'docker_container_name': name,
'docker_image_id': image_id,
'docker_image_name': package.entry.repository,
'docker_image_tag': package.entry.tag,
'docker_image_run_opt': run_opt,
'sonic_asic_platform': sonic_asic_platform
}
Expand Down
5 changes: 5 additions & 0 deletions sonic_package_manager/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ def install(self, package: Package):

image = self.install_image(package)
package.entry.image_id = image.id
if image.tags:
package.entry.tag = image.tags[0]
else:
package.entry.tag = image.id

# if no repository is defined for this package
# get repository from image
if not package.repository:
Expand Down
5 changes: 3 additions & 2 deletions tests/sonic_package_manager/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,17 @@ def mock_docker_api():
@dataclass
class Image:
id: str
tags: list[str]

@property
def attrs(self):
return {'RepoTags': [self.id]}

def pull(repo, ref):
return Image(f'{repo}:{ref}')
return Image(f'{repo}:{ref}', [ref])

def load(filename):
return Image(filename)
return Image(filename, ["latest"])

docker.pull = MagicMock(side_effect=pull)
docker.load = MagicMock(side_effect=load)
Expand Down
47 changes: 46 additions & 1 deletion tests/sonic_package_manager/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from sonic_package_manager.database import PackageEntry
from sonic_package_manager.database import PackageEntry, package_from_dict
from sonic_package_manager.errors import (
PackageNotFoundError,
PackageAlreadyExistsError,
Expand Down Expand Up @@ -87,3 +87,48 @@ def test_database_remove_package_built_in(fake_db):
match='Package swss is built-in, '
'cannot remove it'):
fake_db.remove_package('swss')


def test_package_from_dict():
"""Test converting dictionary to PackageEntry object."""
package_info = {
'repository': 'test-repo',
'description': 'Test package description',
'default-reference': '1.0.0',
'installed-version': '1.0.0',
'installed': True,
'built-in': False,
'image-id': 'abc123',
'tag': 'latest'
}

package = package_from_dict('test-package', package_info)

assert package.name == 'test-package'
assert package.repository == 'test-repo'
assert package.description == 'Test package description'
assert package.default_reference == '1.0.0'
assert package.version == Version.parse('1.0.0')
assert package.installed is True
assert package.built_in is False
assert package.image_id == 'abc123'
assert package.tag == 'latest'


def test_package_from_dict_minimal():
"""Test converting minimal dictionary to PackageEntry object."""
package_info = {
'repository': 'test-repo'
}

package = package_from_dict('test-package', package_info)

assert package.name == 'test-package'
assert package.repository == 'test-repo'
assert package.description is None
assert package.default_reference is None
assert package.version is None
assert package.installed is False
assert package.built_in is False
assert package.image_id is None
assert package.tag is None
29 changes: 28 additions & 1 deletion tests/sonic_package_manager/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import re
import unittest
from unittest.mock import Mock, call, patch, mock_open
from unittest.mock import Mock, call, patch, mock_open, MagicMock
import pytest

import sonic_package_manager
Expand Down Expand Up @@ -600,3 +600,30 @@ def test_download_file_sftp(package_manager):
username="admin",
password="test_password"
)


def test_installation_from_file_no_tags(package_manager, mock_docker_api, sonic_fs):
# Override the load function to return an image without tags
def load_no_tags(filename):
class Image:
def __init__(self, id):
self.id = id
self.tags = []

@property
def attrs(self):
return {'RepoTags': []}

return Image(filename)

mock_docker_api.load = MagicMock(side_effect=load_no_tags)

sonic_fs.create_file('Azure/docker-test:1.6.0')
package_manager.install(tarball='Azure/docker-test:1.6.0')

# Verify the image was loaded
mock_docker_api.load.assert_called_once_with('Azure/docker-test:1.6.0')

# Get the package from the database and verify the tag was set to the image ID
package = package_manager.database.get_package('test-package')
assert package.tag == 'Azure/docker-test:1.6.0'
Loading