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

Merge up release-v0.6.x to release-v0.7.x #188

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5d2503b
Adds cleanupsyncs command parameters
akolson Jul 13, 2023
89fac4c
Changes argument underscores to hythens, uodates changelog + version …
akolson Jul 18, 2023
5ef2225
Merge pull request #186 from akolson/add-cleanupsyncs-params
bjester Jul 18, 2023
6e5e0e0
Fix latest version number
bjester Jul 18, 2023
85b9e72
corrects version number on changelogs
akolson Jul 18, 2023
682b003
Merge pull request #189 from akolson/add-cleanupsyncs-params
bjester Jul 18, 2023
6c3a5f9
Update publishing workflow
bjester Jul 18, 2023
3962121
Use python3 instead
bjester Jul 18, 2023
7ed1215
Merge pull request #190 from bjester/update-publish-0.6.x
bjester Jul 18, 2023
f124187
Adds cleanupsyncs command parameters
akolson Jul 13, 2023
e95cb53
Changes argument underscores to hythens, uodates changelog
akolson Jul 18, 2023
e5fd0f8
Fix latest version number
bjester Jul 18, 2023
bbd92bb
Prepare changelog for new release
bjester Jul 18, 2023
08114a5
Ignore direnv file .envrc
bjester Jul 18, 2023
f3dbbe1
Update publishing workflow
bjester Jul 18, 2023
3b60db4
Use python3 instead
bjester Jul 18, 2023
5696895
Update unit tests workflows for python 2.7 separation
bjester Jul 18, 2023
c922417
Fix linting issue
bjester Jul 18, 2023
8ec8a66
add init file
bjester Jul 18, 2023
bbb8561
Add backported tests package to workaround missing test package for 2.7
bjester Jul 18, 2023
eeb3296
Remove sudo usage
bjester Jul 18, 2023
28f4d04
Fix things I keep breaking
bjester Jul 18, 2023
854e333
Import from backported for 2.7
bjester Jul 18, 2023
d74092a
Try explicit imports
bjester Jul 18, 2023
59b17c4
Install backports inside tox env
bjester Jul 18, 2023
a62a8e1
Add option to ignore process check when resuming sync session
bjester Jul 24, 2023
a0379b5
Fix merge conflicts
bjester Jul 25, 2023
b388507
Update changelog
bjester Jul 25, 2023
6d9fb2a
Merge branch 'optional-ignore-on-resume' into merge-up-0.6.x
bjester Jul 25, 2023
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
6 changes: 2 additions & 4 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@ on:

jobs:
deploy:

runs-on: ubuntu-20.04

runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 2.7
python-version: 3.9
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/python2-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ jobs:
name: Python 2 syntax checking
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
container:
image: python:2.7.18-buster
steps:
- uses: actions/checkout@v2
- name: Set up Python 2.7
uses: actions/setup-python@v2
with:
python-version: 2.7
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand Down
49 changes: 46 additions & 3 deletions .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ jobs:
strategy:
max-parallel: 5
matrix:
python-version: [2.7, 3.6, 3.7, 3.8, 3.9, '3.10', '3.11']

python-version: [3.6, 3.7, 3.8, 3.9, '3.10', '3.11']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -42,6 +41,26 @@ jobs:
key: ${{ runner.os }}-tox-py${{ matrix.python-version }}-${{ hashFiles('setup.py', 'requirements/*.txt') }}
- name: Test with tox
run: tox -e py${{ matrix.python-version }}
unit_test27:
name: Python unit tests (2.7)
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
runs-on: ubuntu-20.04
container:
image: python:2.7.18-buster
steps:
- uses: actions/checkout@v2
- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox
- name: tox env cache
uses: actions/cache@v2
with:
path: ${{ github.workspace }}/.tox/py2.7
key: ${{ runner.os }}-tox-py2.7-${{ hashFiles('setup.py', 'requirements/*.txt') }}
- name: Test with tox
run: tox -e py2.7
cryptography:
name: Python unit tests + cryptography
needs: pre_job
Expand All @@ -51,7 +70,7 @@ jobs:
max-parallel: 5
matrix:
# only crypto 3.3 seems to work
python-version: [ 2.7, 3.6, 3.7, 3.8, 3.9, '3.10', '3.11' ]
python-version: [ 3.6, 3.7, 3.8, 3.9, '3.10', '3.11' ]
crypto-version: [ 3.3 ]

steps:
Expand All @@ -75,6 +94,30 @@ jobs:
key: ${{ runner.os }}-tox-py${{ matrix.python-version }}-crypto${{ matrix.crypto-version }}-${{ hashFiles('setup.py', 'requirements/*.txt') }}
- name: Test with tox
run: tox -e py${{ matrix.python-version }}-cryptography${{ matrix.crypto-version }}
cryptography27:
name: Python unit tests (2.7) + cryptography
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
runs-on: ubuntu-20.04
container:
image: python:2.7.18-buster
steps:
- uses: actions/checkout@v2
- name: Install system dependencies
run: |
apt-get -y -qq update
apt-get install -y openssl libssl-dev
- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox
- name: tox env cache
uses: actions/cache@v2
with:
path: ${{ github.workspace }}/.tox/py2.7
key: ${{ runner.os }}-tox-py2.7-crypto3.3-${{ hashFiles('setup.py', 'requirements/*.txt') }}
- name: Test with tox
run: tox -e py2.7-cryptography3.3
postgres:
name: Python postgres unit tests
needs: pre_job
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ venv/
ENV/
.venv
Pipfile
.envrc

# Spyder project settings
.spyderproject
Expand All @@ -97,4 +98,4 @@ Pipfile

*.db

.vscode
.vscode
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# Release Notes

List of the most important changes for each release.
## 0.7.1
- Ported changes from 0.6.17

## 0.6.17
- Added `client-instance-id`, `server-instance-id`, `sync-filter`, `push` and `pull` arguments to `cleanupsyncs` management command
- Added option for resuming a sync to ignore the `SyncSession`'s existing `process_id`

## 0.7.0
- Dropped support for Python 3.4 and 3.5
- Upgraded cryptography to latest version that still supports Python 2.7 - 3.3.2

## 0.6.16
- Added dedicated `client_instance_id` and `server_instance_id` fields to `SyncSession`
Expand Down
46 changes: 46 additions & 0 deletions morango/management/commands/cleanupsyncs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import logging
import uuid

from django.core.management.base import BaseCommand
from django.db import transaction
Expand Down Expand Up @@ -29,6 +30,36 @@ def add_arguments(self, parser):
default=6,
help="Number of hours of inactivity after which a session should be considered stale",
)
parser.add_argument(
"--client-instance-id",
type=uuid.UUID,
default=None,
help="Filters the SyncSession models to those with matching 'client_instance_id'",
)
parser.add_argument(
"--server-instance-id",
type=uuid.UUID,
default=None,
help="Filters the SyncSession models to those with matching 'server_instance_id'",
)
parser.add_argument(
"--sync-filter",
type=str,
default=None,
help="Filters the TransferSession models to those with 'filters' starting with 'sync_filter'",
)
parser.add_argument(
"--push",
type=bool,
default=None,
help="Filters the TransferSession models to those with 'push' set to True",
)
parser.add_argument(
"--pull",
type=bool,
default=None,
help="Filters the TransferSession models to those with 'push' set to False",
)

def handle(self, *args, **options):

Expand All @@ -41,13 +72,28 @@ def handle(self, *args, **options):
if options["ids"]:
sync_sessions = sync_sessions.filter(id__in=options["ids"])

if options["client_instance_id"]:
sync_sessions = sync_sessions.filter(client_instance_id=options["client_instance_id"])

if options["server_instance_id"]:
sync_sessions = sync_sessions.filter(server_instance_id=options["server_instance_id"])

# retrieve all sessions still marked as active but with no activity since the cutoff
transfer_sessions = TransferSession.objects.filter(
sync_session_id__in=sync_sessions.values("id"),
active=True,
last_activity_timestamp__lt=cutoff,
)

if options["sync_filter"]:
transfer_sessions = transfer_sessions.filter(filter__startswith=options["sync_filter"])

if options["push"] and not options["pull"]:
transfer_sessions = transfer_sessions.filter(push=True)

if options["pull"] and not options["push"]:
transfer_sessions = transfer_sessions.filter(push=False)

transfer_count = transfer_sessions.count()

# loop over the stale sessions one by one to close them out
Expand Down
9 changes: 7 additions & 2 deletions morango/sync/syncsession.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,16 @@ def create_sync_session(self, client_cert, server_cert, chunk_size=None):
sync_session = SyncSession.objects.create(**data)
return SyncSessionClient(self, sync_session)

def resume_sync_session(self, sync_session_id, chunk_size=None):
def resume_sync_session(self, sync_session_id, chunk_size=None, ignore_existing_process=False):
"""
Resumes an existing sync session given an ID

:param sync_session_id: The UUID of the `SyncSession` to resume
:param chunk_size: An optional parameter specifying the size for each transferred chunk
:type chunk_size: int
:param ignore_existing_process:An optional parameter specifying whether to ignore an
existing active process ID
:type ignore_existing_process: bool
:return: A SyncSessionClient instance
:rtype: SyncSessionClient
"""
Expand All @@ -281,7 +285,8 @@ def resume_sync_session(self, sync_session_id, chunk_size=None):

# check that process of existing session isn't still running
if (
sync_session.process_id
not ignore_existing_process
and sync_session.process_id
and sync_session.process_id != os.getpid()
and pid_exists(sync_session.process_id)
):
Expand Down
Empty file added tests/testapp/__init__.py
Empty file.
11 changes: 8 additions & 3 deletions tests/testapp/tests/compat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
try:
from test.support import EnvironmentVarGuard # noqa F401
# In the Python 2.7 GH workflows, we have to install backported version
from backports.test.support import EnvironmentVarGuard # noqa F401
except ImportError:
# In Python 3.10, this has been moved to test.support.os_helper
from test.support.os_helper import EnvironmentVarGuard # noqa F401
try:
# For python >2.7 and <3.10
from test.support import EnvironmentVarGuard # noqa F401
except ImportError:
# In Python 3.10, this has been moved to test.support.os_helper
from test.support.os_helper import EnvironmentVarGuard # noqa F401
24 changes: 24 additions & 0 deletions tests/testapp/tests/sync/test_syncsession.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,30 @@ def create(**data):
with self.assertRaises(MorangoResumeSyncError):
self.network_connection.resume_sync_session(sync_session.id)

@mock.patch.object(SyncSession.objects, "create")
def test_resume_sync_session__still_running_but_ignore(self, mock_create):
def create(**data):
"""Trickery to get around same DB being used for both client and server"""
return SyncSession.objects.get(pk=data.get("id"))

mock_create.side_effect = create

# first create a session
client = self.network_connection.create_sync_session(self.subset_cert, self.root_cert)
# reset process ID
sync_session = client.sync_session
sync_session.process_id = 123000111
sync_session.save()

with mock.patch("morango.sync.syncsession.pid_exists") as mock_pid_exists:
mock_pid_exists.return_value = True
with mock.patch("morango.sync.syncsession.os.getpid") as mock_getpid:
mock_getpid.return_value = 245111222
resume_client = self.network_connection.resume_sync_session(
sync_session.id, ignore_existing_process=True
)
self.assertEqual(sync_session.id, resume_client.sync_session.id)


class SyncSessionClientTestCase(BaseClientTestCase):
def test_get_pull_client(self):
Expand Down
44 changes: 42 additions & 2 deletions tests/testapp/tests/test_management_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from morango.models.core import TransferSession


def _create_sessions(last_activity_offset=0, sync_session=None):
def _create_sessions(last_activity_offset=0, sync_session=None, push=True):

last_activity_timestamp = timezone.now() - datetime.timedelta(
hours=last_activity_offset
Expand All @@ -21,13 +21,16 @@ def _create_sessions(last_activity_offset=0, sync_session=None):
id=uuid.uuid4().hex,
profile="facilitydata",
last_activity_timestamp=last_activity_timestamp,
client_instance_id=uuid.uuid4().hex,
server_instance_id=uuid.uuid4().hex,
)

transfer_session = TransferSession.objects.create(
id=uuid.uuid4().hex,
sync_session=sync_session,
push=True,
push=push,
last_activity_timestamp=last_activity_timestamp,
filter="1:2\n"
)

return sync_session, transfer_session
Expand Down Expand Up @@ -100,6 +103,43 @@ def test_filtering_sessions_cleared(self):
self.assertTransferSessionIsNotCleared(self.transfersession_new)
self.assertSyncSessionIsActive(self.syncsession_new)

def test_filtering_sessions_by_client_instance_id_cleared(self):
call_command("cleanupsyncs", client_instance_id=self.syncsession_old.client_instance_id, expiration=0)
self.assertTransferSessionIsCleared(self.transfersession_old)
self.assertSyncSessionIsNotActive(self.syncsession_old)
self.assertTransferSessionIsNotCleared(self.transfersession_new)
self.assertSyncSessionIsActive(self.syncsession_new)

def test_filtering_sessions_by_server_instance_id_cleared(self):
call_command("cleanupsyncs", server_instance_id=self.syncsession_old.server_instance_id, expiration=0)
self.assertTransferSessionIsCleared(self.transfersession_old)
self.assertSyncSessionIsNotActive(self.syncsession_old)
self.assertTransferSessionIsNotCleared(self.transfersession_new)
self.assertSyncSessionIsActive(self.syncsession_new)

def test_filtering_sessions_by_sync_filter_cleared(self):
call_command("cleanupsyncs", sync_filter=self.transfersession_old.filter, expiration=0)
self.assertTransferSessionIsCleared(self.transfersession_old)
self.assertSyncSessionIsNotActive(self.syncsession_old)
self.assertTransferSessionIsCleared(self.transfersession_new)
self.assertSyncSessionIsNotActive(self.syncsession_new)

def test_filtering_sessions_by_push_cleared(self):
call_command("cleanupsyncs", push=self.transfersession_old.push, expiration=0)
self.assertTransferSessionIsCleared(self.transfersession_old)
self.assertSyncSessionIsNotActive(self.syncsession_old)
self.assertTransferSessionIsCleared(self.transfersession_new)
self.assertSyncSessionIsNotActive(self.syncsession_new)

def test_filtering_sessions_by_pull_cleared(self):
syncsession_old, transfersession_old = _create_sessions(push=False)
syncsession_new, transfersession_new = _create_sessions(push=False)
call_command("cleanupsyncs", pull=not transfersession_old.push, expiration=0)
self.assertTransferSessionIsCleared(transfersession_old)
self.assertSyncSessionIsActive(syncsession_old)
self.assertTransferSessionIsCleared(transfersession_new)
self.assertSyncSessionIsActive(syncsession_new)

def test_multiple_ids_as_list(self):
ids = [self.syncsession_old.id, self.syncsession_new.id]
call_command("cleanupsyncs", ids=ids, expiration=0)
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ basepython =
deps =
-r{toxinidir}/requirements/test.txt
cryptography3.3: cryptography==3.3.2
py2.7: backports.test.support==0.1.1

commands =
sh -c '! tests/testapp/manage.py makemigrations --dry-run --exit --noinput'
Expand Down
Loading