A python-syntax declarative IT automation tool.
项目描述
uPlaybook
使用uPlaybook释放自动化的力量
uPlaybook(发音为“Micro Playbook”)位于Cookiecutter等模板工具和Ansible等“舰队级”配置管理/基础设施即代码生态系统之间。如果Ansible是一个shell脚本,那么你就有了uPlaybook。
uPlaybook仅针对单个系统运行,因此管理“舰队清单”的复杂性消失了。在此基础上是
uPlaybook由声明式“任务”的“playbook”组成,具有Python的全部功能,提供了比Ansible中使用的YAML更丰富的脚本体验。声明性特性允许您指定系统或服务的所需状态,而playbook将执行所需更改。修改playbook并重新运行以获取新状态,并将playbook存储在git中以进行版本控制和重用。
教程
优点
- 在本地系统上运行:消除管理“舰队基础设施”的复杂性。
- playbook可发现性:运行“up”并显示可用playbook列表。通过搜索路径查找系统、用户和项目级别的playbook。
- 参数处理:简单的CLI参数处理,playbook可以创建项目脚手架、部署和配置Apache模块等...
- Shell脚本,但声明式而非基于命令的。内置参数解析、模板化和更改时调用的“处理程序”(类似于Ansible)。
用例
- 简化工作流程
- 自动化重复性任务
- 配置项目
- 安装和部署软件或服务
- 管理工作站或服务器的安装和配置
- 项目模板。
- IT 自动化。
命令行参数处理使 Playbook 在运行时能够进行专业化。在 "examples/new-uplaybook" 中有一个示例,通过运行以下命令创建一个骨架 Playbook:up new-uplaybook my-example-playbook
。
uPlaybook 从 Ansible 和 Cookiecutter 中汲取灵感,用 Python 语法替换了它们的 YAML 语法。Playbook 类似于 shell 脚本,专门用于设置系统或环境。Playbook 包含 CLI 参数处理,这在传统 shell 脚本中通常难以做好。
尽管简单,但 uPlaybook 在功能上并不妥协。核心任务可以通过任意 Python 代码进行增强,以获得最大的力量。
高级思想
uPlaybook 提供以下思想
- Python syntax
- First-class CLI argument handling.
- Declare the state you want to end up at.
- Tasks communicate whether they have changed something.
- Changed tasks can trigger a handler (if this config file changes, restart a service).
- Jinja2 templating of arguments and files delivered via fs.copy()
- Status output.
安装
可以使用以下方式安装:
pipx install uplaybook
或者
pip install uplaybook
或从存储库中运行
git clone git@github.com:linsomniac/uplaybook.git
pip install poetry
poetry shell
上面的命令启动了一个具有 uPlaybook 的 shell,可供运行。
入门指南
您可以使用以下命令在 uplaybook git 检出中创建一个骨架 Playbook:
up new-uplaybook my-test-playbook
这将创建一个名为 "my-test-playbook" 的目录,其中包含骨架 Playbook 文件 "playbook"。用于创建此骨架的 Playbook 在 .uplaybooks/new-uplaybook/playbook
中。
文档
简单示例
部署 Apache 网站
from uplaybook import fs, core, pyinfra
# Restart apache, but only if the site config or symlink to sites-enabled notify
# that it has changed
def restart_apache():
pyinfra.systemd.service(service="apache2", restarted=True)
pyinfra.apt.packages(packages=["apache2"])
fs.cp(src="my-site.conf.j2", path="/etc/apache2/sites-available/my-site.conf").notify(restart_apache)
fs.ln(src="/etc/apache2/sites-available/my-site.conf", path="/etc/apache2/sites-enabled/", symbolic=True).notify(restart_apache)
启用 Apache 模块
from uplaybook import fs, core, pyinfra
core.playbook_args(options=[
core.Argument(name="module_name", description="Name of module"),
core.Argument(name="remove", type="bool", default=False,
description="Remove the module rather than install it"),
])
def restart_and_enable_apache():
pyinfra.systemd.service(service="apache2", restarted=True, enabled=True)
if not ARGS.remove:
pyinfra.apt.packages(packages=["apache2", f"libapache2-mod-{ARGS.module_name}"]
).notify(restart_and_enable_apache)
fs.ln(src="/etc/apache2/mods-available/{{ ARGS.module_name }}.load",
path="/etc/apache2/mods-enabled/{{ ARGS.module_name }}.load",
symbolic=True).notify(restart_and_enable_apache)
else:
fs.rm(path="/etc/apache2/mods-enabled/{{ ARGS.module_name }}.load",
).notify(restart_and_enable_apache)
pyinfra.apt.packages(packages=[f"libapache2-mod-{ARGS.module_name}"], present=False,
).notify(restart_and_enable_apache)
示例 Playbook
状态
这是 Beta 版本软件:核心已完成,但在正式发布前,由于实际应用,可能会以不兼容的方式发生变化。
目前(2023 年 11 月晚些时候)我正在做以下工作:
- 编写文档。
- 测试 uPlaybook 以发现粗糙的边缘。
- 添加更多任务。
如果您查看它,您的反馈将受到赞赏。
与...
Ansible
uPlaybook 的主要优势是使用 Python 语法并且易于在本地系统上运行。Ansible 拥有更丰富的任务生态系统,并且能够同时在一台或多台远程系统上运行 plays。
Cookiecutter
uPlaybook 由于基于 Python 语言,因此具有更丰富的配置语法和更多的灵活性。Cookiecutter 提供了更多的 cookiecutter,而有限的语法确实提供了更多安全性,以防第三方 cookiecutter 在运行时可能造成的影响。
Shell
uPlaybook 具有第一级的 CLI 参数处理,是声明性的,并且(尚未实现)能够询问 Playbook 将会做出哪些更改,并试图将一些 shell 第一级操作引入 Python。Shell 在盲目运行命令和管道方面做得更好。
功能
将变量提升到模板中
version = "3.2"
fs.mkdir(path="myprogram-{{version}}") # Makes directory "myprogram-3.2"
fs.template(path="foo", src="foo.j2") # "foo.j2" can access "{{version}}"
大多数参数使用 Jinja2 模板
path="/etc/rsyslog.d/49-haproxy.conf"
fs.template(src="{{ path | basename }}.j2") # src becomes "49-haproxy.conf.j2"
只有当任务更改系统时,任务才会生效
fs.mkfile(path="foo") # Only takes action if "foo" does not exist
fs.mkfile(path="foo") # Never takes action because "foo" would be created above
任务可以触发处理程序,如果它们更改了某些内容
def restart_apache()
core.service(name="apache2", state="restarted")
fs.template(path="/etc/apache2/sites-enabled/test.conf", src="test.conf.j2").notify(restart_apache)
fs.template(path="/etc/apache2/sites-enabled/other_site.conf", src="other_site.conf.j2").notify(restart_apache)
上述操作将在创建或更新任一配置文件时重启 Apache。即使两个文件都更新了,也只会重启 Apache 一次。
运行 Playbook 时显示任务状态
core.run("rm -rf testdir")
fs.builder(state="directory", path="testdir", mode="a=rX,u+w")
fs.cd("testdir")
fs.builder(state="exists", path="testfile", mode="a=rX")
fs.chown(path="testfile", group="docker")
fs.builder(state="exists", path="testfile", mode="a=rX", group="sean")
产生以下状态输出
=> run(command=rm -rf testdir, shell=True, ignore_failure=False, change=True)
==> mkdir(path=testdir, mode=a=rX,u+w, parents=True)
==# chmod(path=testdir, mode=493)
=> builder(path=testdir, mode=a=rX,u+w, state=directory)
=# cd(path=testdir)
==> mkfile(path=testfile, mode=a=rX)
==# chmod(path=testfile, mode=292)
=> builder(path=testfile, mode=a=rX, state=exists)
=> chown(path=testfile, group=docker) (group)
===# chmod(path=testfile, mode=292)
==# mkfile(path=testfile, mode=a=rX)
==# chmod(path=testfile, mode=292)
==> chown(path=testfile, group=sean) (group)
=# builder(path=testfile, mode=a=rX, group=sean, state=exists)
*** RECAP: total=14 changed=7 failure=0
其中 ">" 在状态中表示发生了更改,"#" 表示没有发生更改,额外的 "=" 缩进表示由父任务触发的任务。父任务是在上述额外的缩进后的无缩进任务("builder" 任务)。
许可证
Creative Commons Zero v1.0 Universal
项目详细信息
下载文件
下载适合您平台上的文件。如果您不确定选择哪个,请了解更多关于安装软件包的信息。