Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

implement promote API #386

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 4 additions & 4 deletions onedocker/repository/onedocker_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ def __init__(self, storage_svc: StorageService, repository_path: str) -> None:
self.storage_svc = storage_svc
self.repository_path = repository_path

def _build_package_path(self, package_name: str, version: str) -> str:
def build_package_path(self, package_name: str, version: str) -> str:
return f"{self.repository_path}{package_name}/{version}/{package_name.split('/')[-1]}"

def upload(self, package_name: str, version: str, source: str) -> None:
package_path = self._build_package_path(package_name, version)
package_path = self.build_package_path(package_name, version)
self.storage_svc.copy(source, package_path)

def download(self, package_name: str, version: str, destination: str) -> None:
package_path = self._build_package_path(package_name, version)
package_path = self.build_package_path(package_name, version)
self.storage_svc.copy(package_path, destination)

def get_package_versions(
Expand All @@ -35,7 +35,7 @@ def get_package_versions(
return self.storage_svc.list_folders(package_parent_path)

def get_package_info(self, package_name: str, version: str) -> PackageInfo:
package_path = self._build_package_path(package_name, version)
package_path = self.build_package_path(package_name, version)

if not self.storage_svc.file_exists(package_path):
raise ValueError(
Expand Down
26 changes: 23 additions & 3 deletions onedocker/repository/onedocker_repository_service.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
#!/usr/bin/env python3
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

from datetime import datetime
from typing import Optional

from fbpcp.service.storage import StorageService
from onedocker.repository.onedocker_checksum import OneDockerChecksumRepository
from onedocker.repository.onedocker_package import OneDockerPackageRepository


class OnedockerRepositoryService:
class OneDockerRepositoryService:
def __init__(
self,
storage_svc: StorageService,
Expand All @@ -32,10 +34,28 @@ def upload(
source: str,
metadata: Optional[dict] = None,
) -> None:
raise NotImplementedError
# TODO: T127441856 handle storing metadata
self.package_repo.upload(package_name, version, source)

def download(self, package_name: str, version: str, destination: str) -> None:
raise NotImplementedError

def promote(self, package_name: str, old_version: str, new_version: str) -> None:
raise NotImplementedError
# Build the target path to promote the package to.
target_path = self.package_repo.build_package_path(package_name, new_version)
if new_version == "latest":
# Archive the existing files in the target path.
last_modified_date = self.package_repo.get_package_info(
package_name, new_version
).last_modified
formatted_date = datetime.strftime(
datetime.strptime(last_modified_date, "%a %b %d %H:%M:%S %Y"),
"%Y-%m-%d",
)

archive_path = self.package_repo.build_package_path(
package_name, formatted_date
)
self.storage_svc.copy(target_path, archive_path)
current_path = self.package_repo.build_package_path(package_name, old_version)
self.storage_svc.copy(current_path, target_path)
96 changes: 96 additions & 0 deletions onedocker/tests/repository/test_onedocker_repository_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env python3
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

import unittest
from datetime import datetime
from unittest.mock import call, MagicMock, patch

from onedocker.entity.package_info import PackageInfo

from onedocker.repository.onedocker_repository_service import OneDockerRepositoryService


class TestOneDockerRepositoryService(unittest.TestCase):
TEST_PACKAGE_PATH = "private_lift/lift"
TEST_PACKAGE_NAME = TEST_PACKAGE_PATH.split("/")[-1]
TEST_PACKAGE_VERSION = "test_version"

@patch(
"onedocker.repository.onedocker_repository_service.OneDockerChecksumRepository"
)
@patch(
"onedocker.repository.onedocker_repository_service.OneDockerPackageRepository"
)
@patch("fbpcp.service.storage_s3.S3StorageService")
def setUp(
self, mockStorageService, mockPackageRepoCall, mockChecksumRepoCall
) -> None:
self.package_repo_path = "/package_repo_path/"
checksum_repo_path = "/checksum_repo_path/"
self.package_repo = MagicMock()
mockPackageRepoCall.return_value = self.package_repo
self.repo_service = OneDockerRepositoryService(
mockStorageService, self.package_repo_path, checksum_repo_path
)
self.storage_svc = mockStorageService
self.package_repo.build_package_path = MagicMock(
side_effect=self._build_package_path
)

def test_onedocker_repo_service_upload(self) -> None:
# Arrange
source_path = "test_source_path"

# Act
self.repo_service.upload(
self.TEST_PACKAGE_PATH, self.TEST_PACKAGE_VERSION, source_path
)

# Assert
self.package_repo.upload.assert_called_with(
self.TEST_PACKAGE_PATH, self.TEST_PACKAGE_VERSION, source_path
)

def _build_package_path(self, package_name: str, version: str) -> str:
return f"{self.package_repo_path}{self.TEST_PACKAGE_NAME}/{version}/{package_name.split('/')[-1]}"

def test_onedocker_repo_service_promote_to_latest(self) -> None:
# Arrange
old_version = self.TEST_PACKAGE_VERSION
new_version = "latest"
date = datetime.today().ctime()
formatted_date = datetime.strftime(
datetime.strptime(date, "%a %b %d %H:%M:%S %Y"),
"%Y-%m-%d",
)
self.package_repo.get_package_info.return_value = PackageInfo(
package_name=self.TEST_PACKAGE_NAME,
version=old_version,
last_modified=date,
package_size=1,
)
target_path = self._build_package_path(self.TEST_PACKAGE_NAME, new_version)
current_path = self._build_package_path(self.TEST_PACKAGE_NAME, old_version)
archive_path = self._build_package_path(self.TEST_PACKAGE_NAME, formatted_date)
# Act
self.repo_service.promote(self.TEST_PACKAGE_PATH, old_version, new_version)

# Assert
self.storage_svc.copy.assert_has_calls(
[call(target_path, archive_path), call(current_path, target_path)]
)

def test_onedocker_repo_service_promote(self) -> None:
# Arrange
old_version = self.TEST_PACKAGE_VERSION
new_version = "rc"
target_path = self._build_package_path(self.TEST_PACKAGE_NAME, new_version)
current_path = self._build_package_path(self.TEST_PACKAGE_NAME, old_version)
# Act
self.repo_service.promote(self.TEST_PACKAGE_PATH, old_version, new_version)

# Assert
self.storage_svc.copy.assert_called_once_with(current_path, target_path)