Rules and Preconditions¶
Rules¶
Attributes¶
OwnerChanged¶
-
class
hammurabi.rules.attributes.
OwnerChanged
(name: str, path: Optional[pathlib.Path] = None, new_value: Optional[str] = None, **kwargs)[source] Change the ownership of a file or directory.
The new ownership of a file or directory can be set in three ways. To set only the user use
new_value="username"
. To set only the group usenew_value=":group_name"
(please note the colon:
). It is also possible to set both username and group at the same time by usingnew_value="username:group_name"
.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, OwnerChanged >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> OwnerChanged( >>> name="Change ownership of nginx config", >>> path=Path("./nginx.conf"), >>> new_value="www:web_admin" >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
ModeChanged¶
-
class
hammurabi.rules.attributes.
ModeChanged
(name: str, path: Optional[pathlib.Path] = None, new_value: Optional[int] = None, **kwargs)[source] Change the mode of a file or directory.
Supported modes:
Config option
Description
stat.S_ISUID
Set user ID on execution.
stat.S_ISGID
Set group ID on execution.
stat.S_ENFMT
Record locking enforced.
stat.S_ISVTX
Save text image after execution.
stat.S_IREAD
Read by owner.
stat.S_IWRITE
Write by owner.
stat.S_IEXEC
Execute by owner.
stat.S_IRWXU
Read, write, and execute by owner.
stat.S_IRUSR
Read by owner.
stat.S_IWUSR
Write by owner.
stat.S_IXUSR
Execute by owner.
stat.S_IRWXG
Read, write, and execute by group.
stat.S_IRGRP
Read by group.
stat.S_IWGRP
Write by group.
stat.S_IXGRP
Execute by group.
stat.S_IRWXO
Read, write, and execute by others.
stat.S_IROTH
Read by others.
stat.S_IWOTH
Write by others.
stat.S_IXOTH
Execute by others.
Example usage:
>>> import stat >>> from pathlib import Path >>> from hammurabi import Law, Pillar, ModeChanged >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> ModeChanged( >>> name="Update script must be executable", >>> path=Path("./scripts/update.sh"), >>> new_value=stat.S_IXGRP | stat.S_IXGRP | stat.S_IXOTH >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Directories¶
DirectoryExists¶
-
class
hammurabi.rules.directories.
DirectoryExists
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source] Ensure that a directory exists. If the directory does not exists, make sure the directory is created.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, DirectoryExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> DirectoryExists( >>> name="Create secrets directory", >>> path=Path("./secrets") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
DirectoryNotExists¶
-
class
hammurabi.rules.directories.
DirectoryNotExists
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source] Ensure that the given directory does not exists.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, DirectoryNotExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> DirectoryNotExists( >>> name="Remove unnecessary directory", >>> path=Path("./temp") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
DirectoryEmptied¶
-
class
hammurabi.rules.directories.
DirectoryEmptied
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source] Ensure that the given directory’s content is removed. Please note the difference between emptying a directory and recreating it. The latter results in lost ACLs, permissions and modes.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, DirectoryEmptied >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> DirectoryEmptied( >>> name="Empty results directory", >>> path=Path("./test-results") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Files¶
FileExists¶
-
class
hammurabi.rules.files.
FileExists
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source] Ensure that a file exists. If the file does not exists, make sure the file is created.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FileExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FileExists( >>> name="Create service descriptor", >>> path=Path("./service.yaml") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
FilesExist¶
-
class
hammurabi.rules.files.
FilesExist
(name: str, paths: Optional[Iterable[pathlib.Path]] = (), **kwargs)[source] Ensure that all files exists. If the files does not exists, make sure the files are created.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FilesExist >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FilesExist( >>> name="Create test files", >>> paths=[ >>> Path("./file_1"), >>> Path("./file_2"), >>> Path("./file_3"), >>> ] >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
FileNotExists¶
-
class
hammurabi.rules.files.
FileNotExists
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source] Ensure that the given file does not exists. If the file exists remove it, otherwise do nothing and return the original path.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FileNotExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FileNotExists( >>> name="Remove unused file", >>> path=Path("./debug.yaml") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
FilesNotExist¶
-
class
hammurabi.rules.files.
FilesNotExist
(name: str, paths: Optional[Iterable[pathlib.Path]] = (), **kwargs)[source] Ensure that the given files does not exist. If the files exist remove them, otherwise do nothing and return the original paths.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FilesNotExist >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FilesNotExist( >>> name="Remove several files", >>> paths=[ >>> Path("./file_1"), >>> Path("./file_2"), >>> Path("./file_3"), >>> ] >>> ), >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
FileEmptied¶
-
class
hammurabi.rules.files.
FileEmptied
(name: str, path: Optional[pathlib.Path] = None, **kwargs)[source] Remove the content of the given file, but keep the file. Please note the difference between emptying a file and recreating it. The latter results in lost ACLs, permissions and modes.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, FileEmptied >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> FileEmptied( >>> name="Empty the check log file", >>> path=Path("/var/log/service/check.log") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Ini files¶
SectionExists¶
-
class
hammurabi.rules.ini.
SectionExists
(name: str, path: Optional[pathlib.Path] = None, target: Optional[str] = None, options: Iterable[Tuple[str, Any]] = (), add_after: bool = True, **kwargs)[source] Ensure that the given config section exists. If needed, the rule will create a config section with the given name, and optionally the specified options. In case options are set, the config options will be assigned to that config sections.
Similarly to
hammurabi.rules.text.LineExists
, this rule is able to add a section before or after a target section. The limitation compared toLineExists
is that theSectionExists
rule is only able to add the new entry exactly before or after its target.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, SectionExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> SectionExists( >>> name="Ensure section exists", >>> path=Path("./config.ini"), >>> section="polling", >>> target="add_after_me", >>> options=( >>> ("interval", "2s"), >>> ("abort_on_error", True), >>> ), >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Warning
When
options
parameter is set, make sure you are using an iterable tuple. The option keys must be strings, but there is no limitation for the value. It can be set to anything what the parser can handle. For more information on the parser, please visit the documentation of configupdater.
SectionNotExists¶
-
class
hammurabi.rules.ini.
SectionNotExists
(name: str, path: Optional[pathlib.Path] = None, section: Optional[str] = None, **kwargs)[source] Make sure that the given file not contains the specified line. When a section removed, all the options belonging to it will be removed too.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, SectionNotExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> SectionNotExists( >>> name="Ensure section removed", >>> path=Path("./config.ini"), >>> section="invalid", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
SectionRenamed¶
-
class
hammurabi.rules.ini.
SectionRenamed
(name: str, path: Optional[pathlib.Path] = None, new_name: Optional[str] = None, **kwargs)[source] Ensure that a section is renamed. None of its options will be changed.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, SectionRenamed >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> SectionRenamed( >>> name="Ensure section renamed", >>> path=Path("./config.ini"), >>> section="polling", >>> new_name="fetching", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
OptionsExist¶
-
class
hammurabi.rules.ini.
OptionsExist
(name: str, path: Optional[pathlib.Path] = None, options: Iterable[Tuple[str, Any]] = None, force_value: bool = False, **kwargs)[source] Ensure that the given config option exists. If needed, the rule will create a config option with the given value. In case the
force_value
parameter is set to True, the original values will be replaced by the give ones.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, OptionsExist >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> OptionsExist( >>> name="Ensure options are changed", >>> path=Path("./config.ini"), >>> section="fetching", >>> options=( >>> ("interval", "2s"), >>> ("abort_on_error", True), >>> ), >>> force_value=True, >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Warning
When using the
force_value
parameter, please note that all the existing option values will be replaced by those set inoptions
parameter.
OptionsNotExist¶
-
class
hammurabi.rules.ini.
OptionsNotExist
(name: str, path: Optional[pathlib.Path] = None, options: Iterable[str] = (), **kwargs)[source] Remove one or more option from a section.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, OptionsNotExist >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> OptionsNotExist( >>> name="Ensure options are removed", >>> path=Path("./config.ini"), >>> section="invalid", >>> options=( >>> "remove", >>> "me", >>> "please", >>> ) >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
OptionRenamed¶
-
class
hammurabi.rules.ini.
OptionRenamed
(name: str, path: Optional[pathlib.Path] = None, option: Optional[str] = None, new_name: Optional[str] = None, **kwargs)[source] Ensure that an option of a section is renamed.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, OptionRenamed >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> OptionRenamed( >>> name="Rename an option", >>> path=Path("./config.ini"), >>> section="my_section", >>> option="typo", >>> new_name="correct", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Operations¶
Moved¶
-
class
hammurabi.rules.operations.
Moved
(name: str, path: Optional[pathlib.Path] = None, destination: Optional[pathlib.Path] = None, **kwargs)[source] Move a file or directory from “A” to “B”.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, Moved >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> Moved( >>> name="Move pyproject.toml to its place", >>> path=Path("/tmp/generated/pyproject.toml.template"), >>> destination=Path("./pyproject.toml"), # Notice the rename! >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Renamed¶
-
class
hammurabi.rules.operations.
Renamed
(name: str, path: Optional[pathlib.Path] = None, new_name: Optional[str] = None, **kwargs)[source] This rule is a shortcut for
hammurabi.rules.operations.Moved
. Instead of destination path a new name is required.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, Renamed >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> Renamed( >>> name="Rename pyproject.toml.bkp", >>> path=Path("/tmp/generated/pyproject.toml.bkp"), >>> new_name="pyproject.toml", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Copied¶
-
class
hammurabi.rules.operations.
Copied
(name: str, path: Optional[pathlib.Path] = None, destination: Optional[pathlib.Path] = None, **kwargs)[source] Ensure that the given file or directory is copied to the new path.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, Copied >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> Copied( >>> name="Create backup file", >>> path=Path("./service.yaml"), >>> destination=Path("./service.bkp.yaml") >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Templates¶
TemplateRendered¶
-
class
hammurabi.rules.templates.
TemplateRendered
(name: str, template: Optional[pathlib.Path] = None, destination: Optional[pathlib.Path] = None, context: Optional[Dict[str, Any]] = None, **kwargs)[source] Render a file from a Jinja2 template. In case the destination file not exists, this rule will create it, otherwise the file will be overridden.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, TemplateRendered >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> TemplateRendered( >>> name="Create gunicorn config from template", >>> template=Path("/tmp/templates/gunicorn.conf.py"), >>> destination=Path("./gunicorn.conf.py"), >>> context={ >>> "keepalive": 65 >>> }, >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Text files¶
LineExists¶
-
class
hammurabi.rules.text.
LineExists
(name: str, path: Optional[pathlib.Path] = None, text: Optional[str] = None, criteria: Optional[str] = None, target: Optional[str] = None, position: int = 1, respect_indentation: bool = True, **kwargs)[source] Make sure that the given file contains the required line. This rule is capable for inserting the expected text before or after the unique target text respecting the indentation of its context.
The default behaviour is to insert the required text exactly after the target line, and respect its indentation. Please note that
text
,criteria
andtarget
parameters are required.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, LineExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> LineExists( >>> name="Extend gunicorn config", >>> path=Path("./gunicorn.conf.py"), >>> text="keepalive = 65", >>> criteria=r"^keepalive.*", >>> target=r"^bind.*", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Note
The indentation of the target text will be extracted by a simple regular expression. If a more complex regexp is required, please inherit from this class.
LineNotExists¶
-
class
hammurabi.rules.text.
LineNotExists
(name: str, path: Optional[pathlib.Path] = None, text: Optional[str] = None, **kwargs)[source] Make sure that the given file not contains the specified line.
Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, LineNotExists >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> LineNotExists( >>> name="Remove keepalive", >>> path=Path("./gunicorn.conf.py"), >>> text="keepalive = 65", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
LineReplaced¶
-
class
hammurabi.rules.text.
LineReplaced
(name: str, path: Optional[pathlib.Path] = None, text: Optional[str] = None, target: Optional[str] = None, respect_indentation: bool = True, **kwargs)[source] Make sure that the given text is replaced in the given file.
The default behaviour is to replace the required text with the exact same indentation that the target line has. This behaviour can be turned off by setting the
respect_indentation
parameter to False. Please note thattext
andtarget
parameters are required.Example usage:
>>> from pathlib import Path >>> from hammurabi import Law, Pillar, LineReplaced >>> >>> example_law = Law( >>> name="Name of the law", >>> description="Well detailed description what this law does.", >>> rules=( >>> LineReplaced( >>> name="Replace typo using regex", >>> path=Path("./gunicorn.conf.py"), >>> text="keepalive = 65", >>> target=r"^kepalive.*", >>> ), >>> ) >>> ) >>> >>> pillar = Pillar() >>> pillar.register(example_law)
Note
The indentation of the target text will be extracted by a simple regular expression. If a more complex regexp is required, please inherit from this class.
Warning
This rule will replace all the matching lines in the given file. Make sure the given target regular expression is tested before the rule used against production code.