Skip to content

Commit

Permalink
Merge branch 'main' into relation-broken-940
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyandrewmeyer authored Dec 14, 2023
2 parents 7dc4f06 + 09b2d8f commit 9c4c793
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 9 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/db-charm-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ jobs:
charm-repo:
- "canonical/postgresql-operator"
- "canonical/postgresql-k8s-operator"
- "canonical/mysql-operator"
- "canonical/mysql-k8s-operator"
# TODO: uncomment once secrets issues are fixed in these charms (eg: https://github.com/canonical/mysql-operator/issues/367)
# - "canonical/mysql-operator"
# - "canonical/mysql-k8s-operator"

steps:
- name: Checkout the ${{ matrix.charm-repo }} repository
Expand Down
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,30 @@ mkdir ops-example
cd ops-example
charmcraft init
```
This has created a standard charm directory structure. Poke around.
This has created a standard charm directory structure:

```shell-script
$ ls -R
.:
CONTRIBUTING.md README.md pyproject.toml src tox.ini
LICENSE charmcraft.yaml requirements.txt tests

./src:
charm.py

./tests:
integration unit

./tests/integration:
test_charm.py

./tests/unit:
test_charm.py
```

Things to note:

- The `metadata.yaml` file shows that what we have is an example charm called `ops-example`, which uses an OCI image resource `httpbin` from `kennethreitz/httpbin`.
- The `charmcraft.yaml` file shows that what we have is an example charm called `ops-example`, which uses an OCI image resource `httpbin` from `kennethreitz/httpbin`.

- The `requirements.txt` file lists the version of `ops` to use.

Expand Down
6 changes: 5 additions & 1 deletion ops/_private/timeconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def parse_rfc3339(s: str) -> datetime.datetime:
that Go's encoding/json package produces for time.Time values.
Unfortunately we can't use datetime.fromisoformat(), as that does not
support more than 6 digits for the fractional second, nor the 'Z' for UTC.
support more than 6 digits for the fractional second, nor the 'Z' for UTC,
in Python 3.8 (Python 3.11+ has the required functionality).
"""
match = _TIMESTAMP_RE.match(s)
if not match:
Expand All @@ -50,6 +51,9 @@ def parse_rfc3339(s: str) -> datetime.datetime:
tz = datetime.timezone(tz_delta if sign == '+' else -tz_delta)

microsecond = round(float(sfrac or '0') * 1000000)
# Ignore any overflow into the seconds - this aligns with the Python
# standard library behaviour.
microsecond = min(microsecond, 999999)

return datetime.datetime(int(y), int(m), int(d), int(hh), int(mm), int(ss),
microsecond=microsecond, tzinfo=tz)
14 changes: 12 additions & 2 deletions ops/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2487,6 +2487,16 @@ def _build_fileinfo(path: Union[str, Path]) -> pebble.FileInfo:
import grp
import pwd
info = path.lstat()
try:
pw_name = pwd.getpwuid(info.st_uid).pw_name
except KeyError:
logger.warning("Could not get name for user %s", info.st_uid)
pw_name = None
try:
gr_name = grp.getgrgid(info.st_gid).gr_name
except KeyError:
logger.warning("Could not get name for group %s", info.st_gid)
gr_name = None
return pebble.FileInfo(
path=str(path),
name=path.name,
Expand All @@ -2495,9 +2505,9 @@ def _build_fileinfo(path: Union[str, Path]) -> pebble.FileInfo:
permissions=stat.S_IMODE(info.st_mode),
last_modified=datetime.datetime.fromtimestamp(info.st_mtime),
user_id=info.st_uid,
user=pwd.getpwuid(info.st_uid).pw_name,
user=pw_name,
group_id=info.st_gid,
group=grp.getgrgid(info.st_gid).gr_name)
group=gr_name)

@staticmethod
def _list_recursive(list_func: Callable[[Path], Iterable[pebble.FileInfo]],
Expand Down
2 changes: 2 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ pytest-operator~=0.23
coverage[toml]~=7.0
typing_extensions~=4.2

macaroonbakery != 1.3.3 # TODO: remove once this is fixed: https://github.com/go-macaroon-bakery/py-macaroon-bakery/issues/94

-r requirements.txt
23 changes: 22 additions & 1 deletion test/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from collections import OrderedDict
from test.test_helpers import fake_script, fake_script_calls
from textwrap import dedent
from unittest.mock import patch
from unittest.mock import MagicMock, patch

import pytest

Expand Down Expand Up @@ -969,6 +969,27 @@ def test_run_error(self):
self.assertEqual(str(cm.exception), 'ERROR cannot get status\n')
self.assertEqual(cm.exception.args[0], 'ERROR cannot get status\n')

@patch("grp.getgrgid")
@patch("pwd.getpwuid")
def test_push_path_unnamed(self, getpwuid: MagicMock, getgrgid: MagicMock):
getpwuid.side_effect = KeyError
getgrgid.side_effect = KeyError
harness = ops.testing.Harness(ops.CharmBase, meta='''
name: test-app
containers:
foo:
resource: foo-image
''')
harness.begin()
harness.set_can_connect('foo', True)
container = harness.model.unit.containers['foo']

with tempfile.TemporaryDirectory() as push_src:
push_path = pathlib.Path(push_src) / 'src.txt'
push_path.write_text('hello')
container.push_path(push_path, "/")
assert container.exists("/src.txt"), 'push_path failed: file "src.txt" missing'


class PushPullCase:
"""Test case for table-driven tests."""
Expand Down
6 changes: 6 additions & 0 deletions test/test_private.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ def test_parse_rfc3339(self):
self.assertEqual(timeconv.parse_rfc3339('2020-12-25T13:45:50.123456789+00:00'),
datetime.datetime(2020, 12, 25, 13, 45, 50, 123457, tzinfo=utc))

self.assertEqual(timeconv.parse_rfc3339('2006-08-28T13:20:00.9999999Z'),
datetime.datetime(2006, 8, 28, 13, 20, 0, 999999, tzinfo=utc))

self.assertEqual(timeconv.parse_rfc3339('2006-12-31T23:59:59.9999999Z'),
datetime.datetime(2006, 12, 31, 23, 59, 59, 999999, tzinfo=utc))

tzinfo = datetime.timezone(datetime.timedelta(hours=-11, minutes=-30))
self.assertEqual(timeconv.parse_rfc3339('2020-12-25T13:45:50.123456789-11:30'),
datetime.datetime(2020, 12, 25, 13, 45, 50, 123457, tzinfo=tzinfo))
Expand Down
15 changes: 14 additions & 1 deletion test/test_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import typing
import unittest
import uuid
from unittest.mock import MagicMock
from unittest.mock import MagicMock, patch

import pytest
import yaml
Expand Down Expand Up @@ -4096,6 +4096,7 @@ class PebbleStorageAPIsTestMixin:

assertEqual = unittest.TestCase.assertEqual # noqa
assertIn = unittest.TestCase.assertIn # noqa
assertIs = unittest.TestCase.assertIs # noqa
assertIsInstance = unittest.TestCase.assertIsInstance # noqa
assertRaises = unittest.TestCase.assertRaises # noqa

Expand Down Expand Up @@ -4572,6 +4573,18 @@ def test_make_dir_with_ownership(self):
dir_ = client.list_files(f"{self.prefix}/dir{idx}", itself=True)[0]
self.assertEqual(dir_.path, f"{self.prefix}/dir{idx}")

@patch("grp.getgrgid")
@patch("pwd.getpwuid")
def test_list_files_unnamed(self, getpwuid: MagicMock, getgrgid: MagicMock):
getpwuid.side_effect = KeyError
getgrgid.side_effect = KeyError
data = 'data'
self.client.push(f"{self.prefix}/file", data)
files = self.client.list_files(f"{self.prefix}/")
self.assertEqual(len(files), 1)
self.assertIs(files[0].user, None)
self.assertIs(files[0].group, None)


class TestFilesystem(unittest.TestCase, _TestingPebbleClientMixin):
def setUp(self) -> None:
Expand Down

0 comments on commit 9c4c793

Please sign in to comment.