news 2026/6/12 8:27:36

基础设施模板CLI工具:Boilerplates

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基础设施模板CLI工具:Boilerplates

Boilerplates CLI

Boilerplates是一个用于管理基础设施模板(boilerplates)的复杂集合,并配备了一个Python CLI工具。它支持Terraform、Docker、Ansible、Kubernetes等多种技术,帮助您快速生成、定制和部署配置模板。

功能特性

  • 多技术模板支持:提供Docker Compose、Terraform、Ansible、Kubernetes、Packer等基础设施模板。
  • 交互式变量收集:通过交互式CLI提示,引导用户为模板变量输入值。
  • 智能默认值管理:支持保存常用变量的默认值,并在多个项目中复用。
  • Git仓库集成:模板库基于Git管理,支持添加、更新和移除自定义模板仓库。
  • Jinja2模板渲染:使用Jinja2引擎渲染模板,支持条件语句和变量替换。
  • 模块化架构:通过模块系统(Module)组织不同技术的模板和命令。
  • 配置文件管理:提供配置管理功能,存储用户默认值和偏好设置。
  • 安全与验证:包含模板语法验证、变量类型检查和路径安全防护。

安装指南

使用安装脚本(推荐)

通过自动化安装脚本安装Boilerplates CLI:

# 安装最新版本curl-fsSL https://raw.githubusercontent.com/christianlempa/boilerplates/main/scripts/install.sh|bash# 安装特定版本curl-fsSL https://raw.githubusercontent.com/christianlempa/boilerplates/main/scripts/install.sh|bash-s -- --version v1.2.3

安装脚本使用pipx为CLI工具创建一个隔离环境。安装完成后,终端中即可使用boilerplates命令。

依赖要求

  • Python 3+
  • Git(用于模板库管理)
  • pipx(用于隔离安装,安装脚本会自动检查)

使用说明

基础命令

# 查看帮助信息boilerplates --help# 查看版本boilerplates --version# 更新模板库boilerplates repo update# 列出所有已配置的库boilerplates repo list

模板操作

# 列出所有可用的Docker Compose模板boilerplates compose list# 查看特定模板的详细信息boilerplates compose show nginx# 生成模板(交互式模式)boilerplates compose generate authentik# 生成模板到自定义输出目录boilerplates compose generate nginx my-nginx-server# 非交互式模式,直接指定变量值boilerplates compose generate traefik my-proxy\--varservice_name=traefik\--vartraefik_enabled=true\--vartraefik_host=proxy.example.com\--no-interactive

管理默认值

# 设置变量的默认值boilerplates compose defaultssetcontainer_timezone"America/New_York"boilerplates compose defaultssetrestart_policy"unless-stopped"

模板库管理

# 添加自定义模板库boilerplates repoaddmy-templates https://github.com/user/templates\--directory library\--branch main# 移除模板库boilerplates repo remove my-templates

核心代码

CLI主入口 (cli/__main__.py)

#!/usr/bin/env python3""" Main entry point for the Boilerplates CLI application. This file serves as the primary executable when running the CLI. """from__future__importannotationsimportimportlibimportloggingimportpkgutilimportsysfrompathlibimportPathfromtypingimportOptionalfromtyperimportTyper,Context,Optionfromrich.consoleimportConsoleimportcli.modulesfromcli.core.registryimportregistryfromcli.coreimportrepo# Using standard Python exceptions instead of custom ones# NOTE: Placeholder version - will be overwritten by release script (.github/workflows/release.yaml)__version__="0.0.0"app=Typer(help="CLI tool for managing infrastructure boilerplates.\n\n[dim]Easily generate, customize, and deploy templates for Docker Compose, Terraform, Kubernetes, and more.\n\n [white]Made with 💜 by [bold]Christian Lempa[/bold]",add_completion=True,rich_markup_mode="rich",)console=Console()defsetup_logging(log_level:str="WARNING")->None:"""Configure the logging system with the specified log level. Args: log_level: The logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) Raises: ValueError: If the log level is invalid RuntimeError: If logging configuration fails """numeric_level=getattr(logging,log_level.upper(),None)ifnotisinstance(numeric_level,int):raiseValueError(f"Invalid log level '{log_level}'. Valid levels: DEBUG, INFO, WARNING, ERROR, CRITICAL")try:logging.basicConfig(level=numeric_level,format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',datefmt='%Y-%m-%d %H:%M:%S')logger=logging.getLogger(__name__)logger.setLevel(numeric_level)exceptExceptionase:raiseRuntimeError(f"Failed to configure logging:{e}")@app.callback(invoke_without_command=True)defmain(version:Optional[bool]=Option(None,"--version","-v",help="Show the application version and exit",),log_level:str=Option("WARNING","--log-level","-l",help="Set the logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)",),ctx:Context=None,)->None:"""Main entry point for the boilerplates CLI. Args: version: Show version information log_level: Logging level for the application ctx: Typer context object """ifversion:console.print(f"Boilerplates CLI [bold]v{__version__}[/bold]")raiseSystemExit(0)try:setup_logging(log_level)except(ValueError,RuntimeError)ase:console_err.print(f"[red]Failed to set up logging:{e}[/red]")sys.exit(1)# Discover and register modules_discover_modules()# Register repository management commandsapp.add_typer(repo.app,name="repo")ifctx.invoked_subcommandisNone:console.print(app.info.help)raiseSystemExit(0)def_discover_modules()->None:"""Dynamically discover and register all modules in the modules package."""try:for_,name,_inpkgutil.iter_modules(cli.modules.__path__):module_path=f"cli.modules.{name}"try:importlib.import_module(module_path)logger.debug(f"Successfully imported module:{name}")exceptExceptionase:logger.warning(f"Failed to import module '{name}':{e}")continuelogger.info(f"Module discovery completed. Total modules:{len(list(registry.iter_module_classes()))}")exceptExceptionase:logger.error(f"Module discovery failed:{e}")raiseif__name__=="__main__":app()

变量集合管理 (cli/core/collection.py)

from__future__importannotationsfromcollectionsimportdefaultdictfromtypingimportAny,Dict,List,Optional,Set,Unionimportloggingfrom.variableimportVariablefrom.sectionimportVariableSection logger=logging.getLogger(__name__)classVariableCollection:"""Manages variables grouped by sections and builds Jinja context."""def__init__(self,spec:dict[str,Any])->None:"""Initialize VariableCollection from a specification dictionary. Args: spec: Dictionary containing the complete variable specification structure Expected format (as used in compose.py): { "section_key": { "title": "Section Title", "prompt": "Optional prompt text", "toggle": "optional_toggle_var_name", "description": "Optional description", "vars": { "var_name": { "description": "Variable description", "type": "str", "default": "default_value", ... } } } } """ifnotisinstance(spec,dict):raiseValueError("Spec must be a dictionary")self._sections:Dict[str,VariableSection]={}# NOTE: The _variable_map provides a flat, O(1) lookup for any variable by its name,# avoiding the need to iterate through sections. It stores references to the same# Variable objects contained in the _set structure.self._variable_map:Dict[str,Variable]={}self._initialize_sections(spec)# Validate dependencies after all sections are loadedself._validate_dependencies()def_initialize_sections(self,spec:dict[str,Any])->None:"""Initialize sections from the spec."""forsection_key,section_datainspec.items():ifnotisinstance(section_data,dict):continue# Create VariableSectionsection_dict={"key":section_key,"title":section_data.get("title",section_key.title()),"description":section_data.get("description"),"toggle":section_data.get("toggle"),"required":section_data.get("required",section_key=="general"),}# Handle dependenciesifneeds:=section_data.get("needs"):section_dict["needs"]=needs section=VariableSection(section_dict)# Add variables to sectionif"vars"insection_dataandisinstance(section_data["vars"],dict):forvar_name,var_datainsection_data["vars"].items():ifnotisinstance(var_data,dict):continue# Create Variablevar_dict=var_data.copy()var_dict["name"]=var_name var_dict["origin"]="template"variable=Variable(var_dict)# Store in section and flat mapsection.variables[var_name]=variable self._variable_map[var_name]=variable self._sections[section_key]=sectiondef_validate_dependencies(self)->None:"""Validate that all section dependencies exist."""forsection_key,sectioninself._sections.items():fordepinsection.needs:ifdepnotinself._sections:logger.warning(f"Section '{section_key}' depends on non-existent section '{dep}'")defget_section(self,section_key:str)->Optional[VariableSection]:"""Get a section by its key."""returnself._sections.get(section_key)defget_sections(self)->Dict[str,VariableSection]:"""Get all sections."""returnself._sections.copy()defis_section_satisfied(self,section_key:str)->bool:"""Check if a section's dependencies are satisfied."""section=self._sections.get(section_key)ifnotsection:returnFalse# General section is always satisfiedifsection_key=="general":returnTrue# Check all dependenciesfordepinsection.needs:dep_section=self._sections.get(dep)ifnotdep_sectionornotdep_section.is_enabled():returnFalsereturnTruedefget_jinja_context(self)->Dict[str,Any]:"""Build Jinja2 template contextfromallvariables.Returns:Dictionary mapping variable names to their valuesfor更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手) 对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 16:42:53

【Open-AutoGLM高效应用指南】:掌握AI自动推理的5大核心技巧

第一章:Open-AutoGLM高效应用的核心价值Open-AutoGLM作为新一代自动化语言模型框架,凭借其模块化设计与高性能推理能力,在企业级AI应用中展现出显著优势。该框架不仅支持多场景任务的快速适配,还通过动态计算图优化大幅降低资源消…

作者头像 李华
网站建设 2026/6/10 0:46:57

【Open-AutoGLM使用体验】:为什么顶尖开发者都在悄悄用它?

第一章:Open-AutoGLM使用体验Open-AutoGLM 是一款面向自动化自然语言处理任务的开源框架,专为简化大语言模型(LLM)在实际业务场景中的部署与调优而设计。其核心优势在于支持零代码配置下的任务编排、模型微调与推理优化&#xff0…

作者头像 李华
网站建设 2026/6/9 21:14:41

【大模型开发必备技能】:Open-AutoGLM API地址获取与安全调用全流程

第一章:Open-AutoGLM API地址获取与安全调用全流程API地址的获取方式 Open-AutoGLM服务通过统一的RESTful接口对外提供能力。开发者需首先登录官方开发者控制台,进入“项目管理”页面创建新项目或选择已有项目。 在项目详情页中点击“启用AutoGLM服务”系…

作者头像 李华
网站建设 2026/6/6 14:30:45

Linux如何查看系统版本相关信息

在使用Linux操作系统的过程中,了解系统版本信息是非常重要的。这不仅有助于我们在进行系统管理时做出正确的决策,还能帮助我们在安装软件或进行系统升级时避免不必要的麻烦。本文将详细介绍如何在不同的Linux发行版中查看系统版本信息。 1. 使用命令行查…

作者头像 李华
网站建设 2026/6/6 9:49:25

深入理解I2S协议工作原理:STM32项目应用实例

深入理解I2S协议工作原理:STM32项目应用实例从一个音频播放卡顿的问题说起你有没有遇到过这样的情况?在做一个基于STM32的音频播放器时,明明代码逻辑没问题,PCM数据也正确加载了,可耳机里传出来的声音却断断续续、像是…

作者头像 李华