python3-cyberfusion-queue-support 1.1.1.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python3-cyberfusion-queue-support-1.1.1.1.3/PKG-INFO +61 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/README.md +51 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/pyproject.toml +21 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/setup.cfg +12 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/setup.py +25 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/__init__.py +74 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/exceptions/__init__.py +39 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/interfaces.py +38 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/__init__.py +22 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/chmod.py +78 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/chown.py +144 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/command.py +67 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/copy.py +68 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/mkdir.py +61 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/move.py +68 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/systemd_tmp_files_create.py +57 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/systemd_unit_disable.py +61 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/systemd_unit_enable.py +59 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/systemd_unit_reload.py +57 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/systemd_unit_restart.py +57 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/systemd_unit_stop.py +57 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/items/unlink.py +61 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/outcomes.py +311 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/utilities.py +9 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/python3_cyberfusion_queue_support.egg-info/PKG-INFO +61 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/python3_cyberfusion_queue_support.egg-info/SOURCES.txt +27 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/python3_cyberfusion_queue_support.egg-info/dependency_links.txt +1 -0
- python3-cyberfusion-queue-support-1.1.1.1.3/src/python3_cyberfusion_queue_support.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: python3-cyberfusion-queue-support
|
|
3
|
+
Version: 1.1.1.1.3
|
|
4
|
+
Summary: Library to queue actions.
|
|
5
|
+
Home-page: https://github.com/CyberfusionIO/python3-cyberfusion-queue-support
|
|
6
|
+
Author: Cyberfusion
|
|
7
|
+
Author-email: support@cyberfusion.io
|
|
8
|
+
Platform: linux
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# python3-cyberfusion-queue-support
|
|
12
|
+
|
|
13
|
+
Library to queue actions.
|
|
14
|
+
|
|
15
|
+
# Install
|
|
16
|
+
|
|
17
|
+
## PyPI
|
|
18
|
+
|
|
19
|
+
Run the following command to install the package from PyPI:
|
|
20
|
+
|
|
21
|
+
pip3 install python3-cyberfusion-queue-support
|
|
22
|
+
|
|
23
|
+
## Generic
|
|
24
|
+
|
|
25
|
+
Run the following command to create a source distribution:
|
|
26
|
+
|
|
27
|
+
python3 setup.py sdist
|
|
28
|
+
|
|
29
|
+
## Debian
|
|
30
|
+
|
|
31
|
+
Run the following commands to build a Debian package:
|
|
32
|
+
|
|
33
|
+
mk-build-deps -i -t 'apt -o Debug::pkgProblemResolver=yes --no-install-recommends -y'
|
|
34
|
+
dpkg-buildpackage -us -uc
|
|
35
|
+
|
|
36
|
+
# Configure
|
|
37
|
+
|
|
38
|
+
No configuration is supported.
|
|
39
|
+
|
|
40
|
+
# Usage
|
|
41
|
+
|
|
42
|
+
## Example
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from cyberfusion.QueueSupport import Queue
|
|
46
|
+
from cyberfusion.QueueSupport.items.chmod import ChmodItem
|
|
47
|
+
|
|
48
|
+
queue = Queue()
|
|
49
|
+
|
|
50
|
+
item = ChmodItem(path="/tmp/example.txt", mode=0o600)
|
|
51
|
+
print(item.outcomes)
|
|
52
|
+
|
|
53
|
+
queue.add(item)
|
|
54
|
+
|
|
55
|
+
preview = True or False
|
|
56
|
+
|
|
57
|
+
outcomes = queue.process(preview=preview)
|
|
58
|
+
|
|
59
|
+
for outcome in outcomes:
|
|
60
|
+
print(str(outcome))
|
|
61
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# python3-cyberfusion-queue-support
|
|
2
|
+
|
|
3
|
+
Library to queue actions.
|
|
4
|
+
|
|
5
|
+
# Install
|
|
6
|
+
|
|
7
|
+
## PyPI
|
|
8
|
+
|
|
9
|
+
Run the following command to install the package from PyPI:
|
|
10
|
+
|
|
11
|
+
pip3 install python3-cyberfusion-queue-support
|
|
12
|
+
|
|
13
|
+
## Generic
|
|
14
|
+
|
|
15
|
+
Run the following command to create a source distribution:
|
|
16
|
+
|
|
17
|
+
python3 setup.py sdist
|
|
18
|
+
|
|
19
|
+
## Debian
|
|
20
|
+
|
|
21
|
+
Run the following commands to build a Debian package:
|
|
22
|
+
|
|
23
|
+
mk-build-deps -i -t 'apt -o Debug::pkgProblemResolver=yes --no-install-recommends -y'
|
|
24
|
+
dpkg-buildpackage -us -uc
|
|
25
|
+
|
|
26
|
+
# Configure
|
|
27
|
+
|
|
28
|
+
No configuration is supported.
|
|
29
|
+
|
|
30
|
+
# Usage
|
|
31
|
+
|
|
32
|
+
## Example
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from cyberfusion.QueueSupport import Queue
|
|
36
|
+
from cyberfusion.QueueSupport.items.chmod import ChmodItem
|
|
37
|
+
|
|
38
|
+
queue = Queue()
|
|
39
|
+
|
|
40
|
+
item = ChmodItem(path="/tmp/example.txt", mode=0o600)
|
|
41
|
+
print(item.outcomes)
|
|
42
|
+
|
|
43
|
+
queue.add(item)
|
|
44
|
+
|
|
45
|
+
preview = True or False
|
|
46
|
+
|
|
47
|
+
outcomes = queue.process(preview=preview)
|
|
48
|
+
|
|
49
|
+
for outcome in outcomes:
|
|
50
|
+
print(str(outcome))
|
|
51
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[tool.isort]
|
|
2
|
+
profile = "black"
|
|
3
|
+
line_length = 79
|
|
4
|
+
known_first_party = ["cyberfusion"]
|
|
5
|
+
default_section = "THIRDPARTY"
|
|
6
|
+
|
|
7
|
+
[tool.black]
|
|
8
|
+
line-length = 79
|
|
9
|
+
exclude = '''
|
|
10
|
+
(
|
|
11
|
+
/(
|
|
12
|
+
\.eggs # exclude a few common directories in the
|
|
13
|
+
| \.git # root of the project
|
|
14
|
+
| \.hg
|
|
15
|
+
| \.mypy_cache
|
|
16
|
+
| \.tox
|
|
17
|
+
| \.venv
|
|
18
|
+
| venv
|
|
19
|
+
)/
|
|
20
|
+
)
|
|
21
|
+
'''
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""A setuptools based setup module."""
|
|
2
|
+
|
|
3
|
+
from setuptools import setup
|
|
4
|
+
|
|
5
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
|
6
|
+
long_description = fh.read()
|
|
7
|
+
|
|
8
|
+
setup(
|
|
9
|
+
name="python3-cyberfusion-queue-support",
|
|
10
|
+
version="1.1.1.1.3",
|
|
11
|
+
description="Library to queue actions.",
|
|
12
|
+
long_description=long_description,
|
|
13
|
+
long_description_content_type="text/markdown",
|
|
14
|
+
author="Cyberfusion",
|
|
15
|
+
author_email="support@cyberfusion.io",
|
|
16
|
+
url="https://github.com/CyberfusionIO/python3-cyberfusion-queue-support",
|
|
17
|
+
platforms=["linux"],
|
|
18
|
+
packages=[
|
|
19
|
+
"cyberfusion.QueueSupport",
|
|
20
|
+
"cyberfusion.QueueSupport.items",
|
|
21
|
+
"cyberfusion.QueueSupport.exceptions",
|
|
22
|
+
],
|
|
23
|
+
package_dir={"": "src"},
|
|
24
|
+
data_files=[],
|
|
25
|
+
)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Classes for queue."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
from cyberfusion.QueueSupport.exceptions import QueueFulfillFailed
|
|
7
|
+
from cyberfusion.QueueSupport.interfaces import OutcomeInterface
|
|
8
|
+
from cyberfusion.QueueSupport.items import _Item
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Queue:
|
|
14
|
+
"""Represents queue."""
|
|
15
|
+
|
|
16
|
+
def __init__(self) -> None:
|
|
17
|
+
"""Set attributes."""
|
|
18
|
+
self.items: List[_Item] = []
|
|
19
|
+
|
|
20
|
+
def add(self, item: _Item, *, move_duplicate_last: bool = True) -> None:
|
|
21
|
+
"""Add item to queue."""
|
|
22
|
+
if item not in self.items:
|
|
23
|
+
self.items.append(item)
|
|
24
|
+
|
|
25
|
+
logger.info(
|
|
26
|
+
"Added item to queue (reference: '%s')", item.reference
|
|
27
|
+
)
|
|
28
|
+
else:
|
|
29
|
+
# If item already in queue, move to last place
|
|
30
|
+
|
|
31
|
+
if move_duplicate_last:
|
|
32
|
+
self.items.append(self.items.pop(self.items.index(item)))
|
|
33
|
+
|
|
34
|
+
logger.info(
|
|
35
|
+
"Added item to queue (reference: '%s') (moving duplicate last)",
|
|
36
|
+
item.reference,
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
logger.info(
|
|
40
|
+
"Didn't add item to queue (reference: '%s') (already present)",
|
|
41
|
+
item.reference,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def process(self, preview: bool) -> List[OutcomeInterface]:
|
|
45
|
+
"""Process items."""
|
|
46
|
+
logger.info("Processing items")
|
|
47
|
+
|
|
48
|
+
results = []
|
|
49
|
+
|
|
50
|
+
for item in self.items:
|
|
51
|
+
logger.info("Processing item '%s'", item.reference)
|
|
52
|
+
|
|
53
|
+
if not item.hide_outcomes:
|
|
54
|
+
results.extend(item.outcomes)
|
|
55
|
+
|
|
56
|
+
if not preview:
|
|
57
|
+
try:
|
|
58
|
+
logger.info("Fulfilling item '%s'", item.reference)
|
|
59
|
+
|
|
60
|
+
item.fulfill()
|
|
61
|
+
|
|
62
|
+
logger.info("Fulfilled item '%s'", item.reference)
|
|
63
|
+
except QueueFulfillFailed:
|
|
64
|
+
raise
|
|
65
|
+
except Exception as e:
|
|
66
|
+
raise QueueFulfillFailed(
|
|
67
|
+
item,
|
|
68
|
+
) from e
|
|
69
|
+
|
|
70
|
+
logger.info("Processed item '%s'", item.reference)
|
|
71
|
+
|
|
72
|
+
logger.info("Processed items")
|
|
73
|
+
|
|
74
|
+
return results
|
python3-cyberfusion-queue-support-1.1.1.1.3/src/cyberfusion/QueueSupport/exceptions/__init__.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Exceptions."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
from cyberfusion.QueueSupport.items import _Item
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ItemError(Exception):
|
|
10
|
+
"""Issues with item."""
|
|
11
|
+
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class PathIsSymlinkError(ItemError):
|
|
17
|
+
"""Path is symlink."""
|
|
18
|
+
|
|
19
|
+
path: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class QueueFulfillFailed(Exception):
|
|
24
|
+
"""Error occurred while fulfilling queue."""
|
|
25
|
+
|
|
26
|
+
item: _Item
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class CommandQueueFulfillFailed(QueueFulfillFailed):
|
|
31
|
+
"""Error occurred while fulfilling queue, with command item."""
|
|
32
|
+
|
|
33
|
+
command: List[str]
|
|
34
|
+
stdout: str
|
|
35
|
+
stderr: str
|
|
36
|
+
|
|
37
|
+
def __str__(self) -> str:
|
|
38
|
+
"""Get string representation."""
|
|
39
|
+
return f"Command:\n\n{self.command}\n\nStdout:\n\n{self.stdout}\n\nStderr:\n\n{self.stderr}"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Interfaces."""
|
|
2
|
+
|
|
3
|
+
from abc import ABCMeta, abstractmethod
|
|
4
|
+
from typing import List
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OutcomeInterface(metaclass=ABCMeta):
|
|
8
|
+
"""Interface for outcomes."""
|
|
9
|
+
|
|
10
|
+
@abstractmethod
|
|
11
|
+
def __str__(self) -> str: # pragma: no cover
|
|
12
|
+
"""Get human-readable string."""
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
@abstractmethod
|
|
16
|
+
def __eq__(self, other: object) -> bool: # pragma: no cover
|
|
17
|
+
"""Get equality based on attributes."""
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ItemInterface(metaclass=ABCMeta):
|
|
22
|
+
"""Interface for items."""
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def outcomes(self) -> List[OutcomeInterface]: # pragma: no cover
|
|
27
|
+
"""Get outcomes of calling self.fulfill."""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def fulfill(self) -> None: # pragma: no cover
|
|
32
|
+
"""Fulfill outcomes."""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def __eq__(self, other: object) -> bool: # pragma: no cover
|
|
37
|
+
"""Get equality based on attributes."""
|
|
38
|
+
pass
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Items."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from cyberfusion.QueueSupport.interfaces import ItemInterface
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class _Item(ItemInterface):
|
|
12
|
+
"""Represents base item."""
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def hide_outcomes(self) -> bool:
|
|
16
|
+
"""Get if outcomes should be hidden."""
|
|
17
|
+
return self._hide_outcomes
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def reference(self) -> Optional[str]:
|
|
21
|
+
"""Get free-form reference, for users' own administrations."""
|
|
22
|
+
return self._reference
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Item."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
|
|
7
|
+
from cyberfusion.QueueSupport.exceptions import PathIsSymlinkError
|
|
8
|
+
from cyberfusion.QueueSupport.interfaces import OutcomeInterface
|
|
9
|
+
from cyberfusion.QueueSupport.items import _Item
|
|
10
|
+
from cyberfusion.QueueSupport.outcomes import ChmodItemModeChangeOutcome
|
|
11
|
+
from cyberfusion.QueueSupport.utilities import get_decimal_permissions
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ChmodItem(_Item):
|
|
17
|
+
"""Represents item."""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
*,
|
|
22
|
+
path: str,
|
|
23
|
+
mode: int,
|
|
24
|
+
reference: Optional[str] = None,
|
|
25
|
+
hide_outcomes: bool = False,
|
|
26
|
+
) -> None:
|
|
27
|
+
"""Set attributes."""
|
|
28
|
+
self.path = path
|
|
29
|
+
self.mode = mode
|
|
30
|
+
self._reference = reference
|
|
31
|
+
self._hide_outcomes = hide_outcomes
|
|
32
|
+
|
|
33
|
+
if os.path.islink(self.path):
|
|
34
|
+
raise PathIsSymlinkError(self.path)
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def outcomes(self) -> List[OutcomeInterface]:
|
|
38
|
+
"""Get outcomes of calling self.fulfill."""
|
|
39
|
+
outcomes = []
|
|
40
|
+
|
|
41
|
+
if not os.path.exists(self.path):
|
|
42
|
+
outcomes.append(
|
|
43
|
+
ChmodItemModeChangeOutcome(
|
|
44
|
+
path=self.path, old_mode=None, new_mode=self.mode
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
else:
|
|
48
|
+
old_mode = get_decimal_permissions(self.path)
|
|
49
|
+
mode_changed = old_mode != self.mode
|
|
50
|
+
|
|
51
|
+
if mode_changed:
|
|
52
|
+
outcomes.append(
|
|
53
|
+
ChmodItemModeChangeOutcome(
|
|
54
|
+
path=self.path, old_mode=old_mode, new_mode=self.mode
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return outcomes
|
|
59
|
+
|
|
60
|
+
def fulfill(self) -> None:
|
|
61
|
+
"""Fulfill outcomes."""
|
|
62
|
+
mode_change_outcomes = [
|
|
63
|
+
x
|
|
64
|
+
for x in self.outcomes
|
|
65
|
+
if isinstance(x, ChmodItemModeChangeOutcome)
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
if mode_change_outcomes:
|
|
69
|
+
os.chmod(
|
|
70
|
+
mode_change_outcomes[0].path, mode_change_outcomes[0].new_mode
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def __eq__(self, other: object) -> bool:
|
|
74
|
+
"""Get equality based on attributes."""
|
|
75
|
+
if not isinstance(other, ChmodItem):
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
return other.path == self.path and other.mode == self.mode
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Item."""
|
|
2
|
+
|
|
3
|
+
import grp
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import pwd
|
|
7
|
+
from grp import getgrgid
|
|
8
|
+
from pwd import getpwuid
|
|
9
|
+
from typing import List, Optional
|
|
10
|
+
|
|
11
|
+
from cyberfusion.QueueSupport.exceptions import PathIsSymlinkError
|
|
12
|
+
from cyberfusion.QueueSupport.interfaces import OutcomeInterface
|
|
13
|
+
from cyberfusion.QueueSupport.items import _Item
|
|
14
|
+
from cyberfusion.QueueSupport.outcomes import (
|
|
15
|
+
ChownItemGroupChangeOutcome,
|
|
16
|
+
ChownItemOwnerChangeOutcome,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_uid(username: str) -> int:
|
|
23
|
+
"""Get UID by username."""
|
|
24
|
+
return pwd.getpwnam(username).pw_uid
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_gid(group_name: str) -> int:
|
|
28
|
+
"""Get GID by group name."""
|
|
29
|
+
return grp.getgrnam(group_name).gr_gid
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ChownItem(_Item):
|
|
33
|
+
"""Represents item."""
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
*,
|
|
38
|
+
path: str,
|
|
39
|
+
owner_name: str,
|
|
40
|
+
group_name: str,
|
|
41
|
+
reference: Optional[str] = None,
|
|
42
|
+
hide_outcomes: bool = False,
|
|
43
|
+
) -> None:
|
|
44
|
+
"""Set attributes."""
|
|
45
|
+
self.path = path
|
|
46
|
+
self.owner_name = owner_name
|
|
47
|
+
self.group_name = group_name
|
|
48
|
+
self._reference = reference
|
|
49
|
+
self._hide_outcomes = hide_outcomes
|
|
50
|
+
|
|
51
|
+
if os.path.islink(self.path):
|
|
52
|
+
raise PathIsSymlinkError(self.path)
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def outcomes(self) -> List[OutcomeInterface]:
|
|
56
|
+
"""Get outcomes of calling self.fulfill."""
|
|
57
|
+
outcomes = []
|
|
58
|
+
|
|
59
|
+
if not os.path.exists(self.path):
|
|
60
|
+
outcomes.extend(
|
|
61
|
+
[
|
|
62
|
+
ChownItemOwnerChangeOutcome(
|
|
63
|
+
path=self.path,
|
|
64
|
+
old_owner_name=None,
|
|
65
|
+
new_owner_name=self.owner_name,
|
|
66
|
+
),
|
|
67
|
+
ChownItemGroupChangeOutcome(
|
|
68
|
+
path=self.path,
|
|
69
|
+
old_group_name=None,
|
|
70
|
+
new_group_name=self.group_name,
|
|
71
|
+
),
|
|
72
|
+
]
|
|
73
|
+
)
|
|
74
|
+
else:
|
|
75
|
+
try:
|
|
76
|
+
old_owner_name = getpwuid(os.stat(self.path).st_uid).pw_name
|
|
77
|
+
except KeyError:
|
|
78
|
+
old_owner_name = "(no user with UID exists)"
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
old_group_name = getgrgid(os.stat(self.path).st_gid).gr_name
|
|
82
|
+
except KeyError:
|
|
83
|
+
old_group_name = "(no group with GID exists)"
|
|
84
|
+
|
|
85
|
+
owner_name_changed = old_owner_name != self.owner_name
|
|
86
|
+
group_name_changed = old_group_name != self.group_name
|
|
87
|
+
|
|
88
|
+
if owner_name_changed:
|
|
89
|
+
outcomes.append(
|
|
90
|
+
ChownItemOwnerChangeOutcome(
|
|
91
|
+
path=self.path,
|
|
92
|
+
old_owner_name=old_owner_name,
|
|
93
|
+
new_owner_name=self.owner_name,
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
if group_name_changed:
|
|
98
|
+
outcomes.append(
|
|
99
|
+
ChownItemGroupChangeOutcome(
|
|
100
|
+
path=self.path,
|
|
101
|
+
old_group_name=old_group_name,
|
|
102
|
+
new_group_name=self.group_name,
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
return outcomes
|
|
107
|
+
|
|
108
|
+
def fulfill(self) -> None:
|
|
109
|
+
"""Fulfill outcomes."""
|
|
110
|
+
owner_name_change_outcomes = [
|
|
111
|
+
x
|
|
112
|
+
for x in self.outcomes
|
|
113
|
+
if isinstance(x, ChownItemOwnerChangeOutcome)
|
|
114
|
+
]
|
|
115
|
+
group_name_change_outcomes = [
|
|
116
|
+
x
|
|
117
|
+
for x in self.outcomes
|
|
118
|
+
if isinstance(x, ChownItemGroupChangeOutcome)
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
if owner_name_change_outcomes:
|
|
122
|
+
os.chown(
|
|
123
|
+
owner_name_change_outcomes[0].path,
|
|
124
|
+
uid=get_uid(owner_name_change_outcomes[0].new_owner_name),
|
|
125
|
+
gid=-1,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
if group_name_change_outcomes:
|
|
129
|
+
os.chown(
|
|
130
|
+
group_name_change_outcomes[0].path,
|
|
131
|
+
uid=-1,
|
|
132
|
+
gid=get_gid(group_name_change_outcomes[0].new_group_name),
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def __eq__(self, other: object) -> bool:
|
|
136
|
+
"""Get equality based on attributes."""
|
|
137
|
+
if not isinstance(other, ChownItem):
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
other.path == self.path
|
|
142
|
+
and other.owner_name == self.owner_name
|
|
143
|
+
and other.group_name == self.group_name
|
|
144
|
+
)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Item."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import subprocess
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
|
|
7
|
+
from cyberfusion.QueueSupport.exceptions import CommandQueueFulfillFailed
|
|
8
|
+
from cyberfusion.QueueSupport.interfaces import OutcomeInterface
|
|
9
|
+
from cyberfusion.QueueSupport.items import _Item
|
|
10
|
+
from cyberfusion.QueueSupport.outcomes import CommandItemRunOutcome
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CommandItem(_Item):
|
|
16
|
+
"""Represents item."""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
*,
|
|
21
|
+
command: List[str],
|
|
22
|
+
reference: Optional[str] = None,
|
|
23
|
+
hide_outcomes: bool = False,
|
|
24
|
+
) -> None:
|
|
25
|
+
"""Set attributes."""
|
|
26
|
+
self.command = command
|
|
27
|
+
self._reference = reference
|
|
28
|
+
self._hide_outcomes = hide_outcomes
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def outcomes(self) -> List[OutcomeInterface]:
|
|
32
|
+
"""Get outcomes of calling self.fulfill."""
|
|
33
|
+
outcomes = []
|
|
34
|
+
|
|
35
|
+
outcomes.append(CommandItemRunOutcome(command=self.command))
|
|
36
|
+
|
|
37
|
+
return outcomes
|
|
38
|
+
|
|
39
|
+
def fulfill(self) -> None:
|
|
40
|
+
"""Fulfill outcomes."""
|
|
41
|
+
run_outcomes = [
|
|
42
|
+
x for x in self.outcomes if isinstance(x, CommandItemRunOutcome)
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
command = run_outcomes[0].command
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
output = subprocess.run(
|
|
49
|
+
command,
|
|
50
|
+
check=True,
|
|
51
|
+
text=True,
|
|
52
|
+
capture_output=True,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
logger.info("Command stdout: %s", output.stdout)
|
|
56
|
+
logger.info("Command stderr: %s", output.stderr)
|
|
57
|
+
except subprocess.CalledProcessError as e:
|
|
58
|
+
raise CommandQueueFulfillFailed(
|
|
59
|
+
self, command=command, stdout=e.stdout, stderr=e.stderr
|
|
60
|
+
) from e
|
|
61
|
+
|
|
62
|
+
def __eq__(self, other: object) -> bool:
|
|
63
|
+
"""Get equality based on attributes."""
|
|
64
|
+
if not isinstance(other, CommandItem):
|
|
65
|
+
return False
|
|
66
|
+
|
|
67
|
+
return other.command == self.command
|