# declare_install **Repository Path**: cs-open-project/declare_install ## Basic Information - **Project Name**: declare_install - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-16 - **Last Updated**: 2026-08-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ops-engine — 声明式安装引擎 一个基于 Go 模板的声明式安装/升级引擎,通过 YAML 配置文件描述安装流程,支持首次安装与升级两种模式。 ## 特性 - **声明式配置**:通过 YAML 描述安装步骤,无需编写复杂的安装脚本 - **两种模式**:自动检测首次安装(install)与升级(upgrade) - **变量分层**:input / computed / env 三层变量模型,职责清晰 - **模板驱动**:使用 Go `text/template` 支持条件控制(`if` 块)和变量展开 - **步骤类型**:mkdir / extract / chown / chmod / symlink / subst / replace / file_copy / shell - **版本管理**:内置 Semver 解析与比较,支持降级检测 - **内置脚本**:所有 shell 操作通过 embed 嵌入的 `.sh` 脚本实现,无需外部依赖 ## 快速开始 ### 构建 ```bash make build ``` ### 测试 ```bash make test # 运行所有测试 make test-race # 运行带 race detector 的测试 make vet # 静态分析检查 ``` ### 运行 PI Platform 安装器 ```bash # 基本用法 ./pi_platform /opt/packages/pai-2.0.0 # 指定变量文件 ./pi_platform --package /opt/packages/pai-2.0.0 --properties /tmp/vars.properties # 使用环境变量 SYSTEM_PACKAGE_PATH=/opt/packages/pai-2.0.0 ./pi_platform ``` ## 项目结构 ``` ops-engine/ ├── cmd/ │ └── pi_platform/ │ ├── main.go # 入口:参数解析、环境变量推导、编排流程 │ └── install.yaml # PI Platform 安装配置(嵌入二进制) ├── pkg/ │ ├── config/ │ │ ├── config.go # Config, Meta, InputDef, EnvDef, ComputedVar 等结构体 │ │ ├── step.go # StepAction 接口, BaseStep, StepWrapper, 注册表 │ │ ├── registry.go # Register(), NewInstance() │ │ └── semver.go # Semver 解析与比较 │ ├── entry/ │ │ ├── loader.go # NewConfig(), stripTemplateControls() │ │ └── loader_test.go │ ├── runner/ │ │ ├── runner.go # Runner, RunWithConfig(), 主执行流程 │ │ ├── load.go # loadProperties(), resolveComputed(), writeVarsFile() │ │ ├── generate.go # GenerateYAML() 模板渲染流水线 │ │ ├── template.go # renderTemplate(), renderFullTemplate(), templateData │ │ └── version.go # checkVersion(), writeVersion(), detectUpgradeMode() │ ├── shell/ │ │ ├── shell.go # Exec(), ExecString(), ExecFn, ExecStringFn │ │ ├── scripts.go # embed 脚本, GetScriptPath() │ │ └── scripts/ # .sh 脚本文件(mkdir, extract, chown, chmod, symlink, subst, replace, file_copy) │ ├── step/ │ │ ├── mkdir.go # MkdirStep │ │ ├── extract.go # ExtractStep │ │ ├── chown.go # ChownStep │ │ ├── chmod.go # ChmodStep │ │ ├── symlink.go # SymlinkStep │ │ ├── subst.go # SubstStep │ │ ├── replace.go # ReplaceStep │ │ ├── file_copy.go # FileCopyStep │ │ └── shell.go # ShellStep(直接 bash -s 执行) │ └── utils/ │ ├── properties.go # PropertyFile, ParseMap(), ParseVarList(), ReadValue() │ └── properties_test.go ├── design.md # 设计文档 ├── Makefile └── go.mod ``` ## YAML 配置 ### 完整示例 ```yaml name: my-install meta: vars_file: /etc/myapp/.vars.properties # 变量持久化文件(升级检测标志) version_file: "{{ .Vars.install_dir }}/VERSION" new_version: "{{ .Env.SYSTEM_VERSION }}" env: SYSTEM_PACKAGE_PATH: brief: 安装包根目录 SYSTEM_VERSION: brief: 安装包版本 input: - name: install_dir value: "/opt/myapp" immutable: true brief: 安装目录 - name: port value: "8080" immutable: false brief: 监听端口 computed: bin_path: value: "{{ .Vars.install_dir }}/bin" brief: 二进制目录 db_version: from_file: "/etc/base/base.properties" key: _PI_DB_VERSION brief: 数据库版本 steps: {{ if eq .Mode "install" }} - type: mkdir name: create-install-dir dest: "{{ .Vars.install_dir }}" clean: true - type: extract name: extract-package src: "{{ .Env.SYSTEM_PACKAGE_PATH }}/app.tar.gz" dest: "{{ .Vars.install_dir }}" format: targz - type: shell name: check-master-ip shell: | #!/bin/bash echo "检查主节点 IP..." {{ end }} {{ if eq .Mode "upgrade" }} - type: subst name: replace-config target_dir: "{{ .Vars.install_dir }}/conf" vars_file: "/etc/base/base.properties" target_file_prefix: "_PI_" var_prefix: "_PI_" {{ end }} ``` ### 变量模型 | 块 | 职责 | 生命周期 | 持久化 | |---|---|---|---| | `meta` | 框架配置(vars_file, version 等) | 每次运行 | 否 | | `env` | 系统环境变量声明(name + brief) | 每次运行 | 否 | | `input` | 用户填写,跨版本保留 | 跨版本 | 是(写入 vars_file) | | `computed` | 框架推导,运行时求值 | 每次重新计算 | 否 | **变量作用域**: | 访问方式 | 来源 | |---|---| | `{{ .Vars.XXX }}` | input 变量(YAML 默认值 + properties 文件合并) | | `{{ .Computed.XXX }}` | computed 变量(模板表达式求值 或 from_file 读取) | | `{{ .Env.XXX }}` | 系统环境变量(env 块声明的元信息,实际值来自系统) | | `{{ .Mode }}` | 运行模式(`install` 或 `upgrade`) | ### 步骤类型 | 类型 | 说明 | 主要字段 | |---|---|---| | `mkdir` | 创建目录 | `dest`, `clean` | | `extract` | 解压 tar/targz | `src`, `dest`, `format`, `patterns` | | `chown` | 修改所有者 | `src[]`, `owner`, `recursive` | | `chmod` | 修改权限 | `src`, `mode`, `recursive` | | `symlink` | 创建软链接 | `target`, `link`, `force` | | `subst` | 文件内容变量替换 | `target_dir`, `vars_file`, `var_prefix`, `target_file_prefix`, `vars` | | `replace` | 标记区间替换 | `target_file`, `prefix`, `content`, `suffix` | | `file_copy` | 复制文件 | `src`, `dst` | | `shell` | 内联 shell 脚本 | `shell` | ### 步骤条件控制 使用 Go template 的 `if` 块控制步骤执行,而非运行时条件评估: ```yaml {{ if eq .Mode "install" }} steps: - type: mkdir dest: "{{ .Vars.install_dir }}" {{ end }} ``` ## 命令行参数 ```bash pi_platform [options] [package_path] [input.properties] ``` | 参数 | 说明 | |---|---| | `--package`, `-p` | 安装包根目录路径 | | `--properties`, `--input`, `-i` | 用户输入变量文件 | | `--help`, `-h` | 显示帮助 | ### 自动推导的环境变量 | 变量 | 来源 | |---|---| | `SYSTEM_PACKAGE_PATH` | `--package` 参数 | | `SYSTEM_PACKAGE_NAME` | `filepath.Base(packagePath)` | | `SYSTEM_VERSION` | `$packagePath/VERSION` 文件内容 | 已设置的环境变量不会被覆盖。 ## 执行流程 ``` 1. parseArgs() // 解析命令行参数 2. autoSetSystemEnv() // 自动设置系统环境变量 3. 加载 inputVars // 从 --properties 文件(可选) 4. GenerateYAML() // 模板渲染(if 块 + 变量展开) 5. NewConfig() // 解析渲染后的 YAML 6. Run() // 按步骤执行安装 └─ 6.1 detectUpgradeMode() // 检测升级模式 └─ 6.2 loadProperties() // 加载 input 变量 └─ 6.3 resolveComputed() // 求值 computed 变量 └─ 6.4 checkVersion() // 升级模式下版本检查 └─ 6.5 执行步骤 └─ 6.6 writeVarsFile() // 持久化 input 变量 └─ 6.7 writeVersion() // 写入版本文件 ``` ## 设计文档 详细设计请参考 [design.md](design.md)。 ## 兼容性 - 支持 `install` 模式:首次安装,执行完整安装流程 - 支持 `upgrade` 模式:升级安装,仅执行配置替换和权限更新 - 升级检测:通过 `vars_file` 存在性自动判断 - 版本管理:Semver 解析,支持降级检测和同版本跳过 ## 构建安装器 ```bash # 构建 go build -o pi_platform ./cmd/pi_platform # 嵌入 install.yaml 到二进制 # main.go 中使用 //go:embed install.yaml ``` ## License MIT