DCM Projects 文件和模板

DCM project 需要一个清单文件和一个或多个 SQL 对象定义文件。这些文件通常在 Git 存储库或本地工作区中存储和管理。

  • 清单文件

    • 指定要包含的对象定义文件。

    • 使用 模板变量 为不同环境定义配置。

  • 对象定义文件

    • 定义您希望在 DCM project 中一起管理的一组 Snowflake 对象。

创建 DCM project 文件的高级工作流程是:

  1. 创建用于存储定义文件的 DCM project 文件夹

  2. 创建清单文件

  3. 创建对象定义文件

创建用于存储定义文件的 DCM project 文件夹

要创建新的 DCM project,请创建一个文件夹来存储清单文件 (manifest.yml) 和 SQL 对象定义文件。

snow init <project_name> --template DCM_PROJECT

带有 DCM_PROJECT 模板的 snow init 命令会在您的项目目录中创建示例定义文件。您可以打开并编辑这些文件来定义您的 DCM project。

DCM Projects 遵循标准化文件夹结构:

  • DCM Projects 对象定义文件必须放在 sources/definitions/ 下。

  • 可选的全局宏文件可以放在 sources/macros/ 下。

  • 这些项目目录中的文件命名和嵌套非常灵活。

  • 来自 DCM 命令的已保存输出构件始终写入 out/

  • 如果您有想要用于 DCM 命令的其他脚本或项目文件,可以将它们添加到 sources 下(例如,dbt 项目文件)。

  • 如果您有其他自定义脚本希望存储在项目文件夹中,但不想被 DCM Projects 命令使用,也不从本地上传,请将它们放在 sources 文件夹之外的文件夹中。

  • CLI 命令仅上传 sources 文件夹内的文件。

备注

如果您使用的是 Git,请将 out/ 添加到您的 .gitignore 文件,以避免将本地输出文件推送到 Git。

DCM project 文件夹结构示例为:

my_dcm_project/
  ├── manifest.yml
  ├── sources/
  │   ├── definitions/
  │   │   ├── bronze.sql
  │   │   └── silver.sql
  │   ├── macros/
  │   │   └── global_macro.sql
  │   └── dbt/
  │       ├── my_dbt_project_1/
  │       └── my_dbt_project_2/
  ├── my_post_scripts/
  └── out/
      └── plan/

创建清单文件

每个 DCM project 需要一个 manifest.yml 文件。它包含项目的关键配置详细信息,并允许将项目文件夹标识为 DCM project。

您可以使用清单文件来控制部署到不同目标环境时使用哪些 DCM project 对象和角色,以及管理模板值集。

清单文件是包含以下属性的 YAML 文件:

manifest_version: 2
type: DCM_PROJECT
default_target:
targets:
templating:

属性

必填

描述

manifest_version

必填

清单架构的版本。当前版本为 2。

type

必填

项目的类型。设置为 DCM_PROJECT

default_target

可选

如果有多个目标,请指定默认目标。如果您未使用 --target 标志指定目标,则 Snowflake CLI 和 Workspaces 将使用默认目标。

targets

必填

targets 部分将每个部署目标映射到特定的 Snowflake 账户、DCM project 对象、所有者角色,以及可选的模板配置。此映射免除了在每个 CLI 命令中传递完全限定项目名称和配置标志的需要。有关更多详细信息,请参阅 项目目标

templating

可选

templating 部分定义要用于项目的模板化配置。有关更多详细信息,请参阅 项目模板配置

项目目标

清单文件中的每个目标都包含以下属性:

targets:
  <target_name>:
    account_identifier:
    project_name:
    project_owner:
    templating_config:

属性

描述

account_identifier

此目标的 Snowflake 账户标识符。

请参阅 查找账户的区域和定位器

project_name

DCM project 对象的完全限定名称,例如 DCM_DEMO.PROJECTS.DCM_PROJECT_DEV

使用 SHOW DCM PROJECTS SQL 命令来查找它。

project_owner

对此项目对象具有 OWNERSHIP 权限的角色。

使用 SHOW DCM PROJECTSDESCRIBE DCM PROJECT SQL 命令来查找它。

``templating_config``(可选)

在本 templating 部分中定义的模板配置的名称,将用于此目标。

项目定义和项目对象之间的映射

DCM Projects 定义文件并不严格绑定到特定 DCM project 对象。您可以使用同一组定义部署到多个项目,无论是在不同的 Snowflake 账户上,还是通过引用不同的配置配置文件。例如,仓库分支上的相同定义文件可以部署到 DEV 和 PROD 账户,如下图所示。

从 DCM 定义到 DCM 项目对象

类似地,您可以通过引用不同路径的定义文件来执行 DCM Projects 对象。例如,您的 CI/CD 自动化可以从主分支部署定义,而您可以针对同一项目从本地定义文件手动运行 PLAN,以检查您的定义与最新部署之间的差异。您还可以使用此方法从其他分支或本地路径进行临时手动部署。

项目模板配置

以下是清单文件中模板配置的高级结构。您可以仅设置 defaults,或仅设置 configurations,或两者都设置。

templating:
  defaults:
    <variable_name>: <value>
  configurations:
    <configuration_name>:
      <variable_name>: <value>

属性

描述

defaults

以键值对形式存在的共享变量值,适用于所有配置,以避免重复。

configurations

用于项目的模板化配置。

各个配置可以使用特定于该配置的值来覆盖默认值。有关如何解析变量的详细信息,请参阅 配置

<configuration_name>

模板化配置的名称。

配置名称不区分大小写。

<variable_name>

变量的名称。

变量名称应遵循 Python 变量命名规则 (https://www.w3schools.com/python/python_variables_names.asp)。

项目定义中的所有变量必须在默认值、所选配置或运行时中声明。

如果希望字符串变量解析为空,请将它们指定为 ""

<value>

请注意变量的值。

值可以是字符串、数字、布尔值、列表或字典。

字典可以在清单中定义,但不能在运行时覆盖。

示例:manifest.yml

这是一个示例 DCM project 清单文件 (manifest.yml),包含三个 :ref:` 配置 <label-dcm_projects_files_configurations>`、DEV、STAGE 和 PROD,以及模板变量及其默认值:

manifest_version: 2

type: DCM_PROJECT

default_target: DCM_DEV

targets:
  DCM_DEV:
    account_identifier: MYORG-MYACCOUNT_DEV
    project_name: DCM_DEMO.PROJECTS.DCM_PROJECT_DEV
    project_owner: DCM_DEVELOPER
    templating_config: DEV

  DCM_STAGE:
    account_identifier: MYORG-MYACCOUNT_STAGE
    project_name: DCM_DEMO.PROJECTS.DCM_PROJECT_STG
    project_owner: DCM_STAGE_DEPLOYER
    templating_config: STAGE

  DCM_PROD:
    account_identifier: MYORG-MYACCOUNT_PROD
    project_name: DCM_DEMO.PROJECTS.DCM_PROJECT_PROD
    project_owner: DCM_PROD_DEPLOYER
    templating_config: PROD

templating:
  defaults:
    user: "GITHUB_ACTIONS_SERVICE_USER"
    wh_size: "SMALL"

  configurations:
    DEV:
      env_suffix: "_DEV"
      user: "INSERT_YOUR_USER"
      wh_size: "X-SMALL"
      teams:
        - name: "DEV_TEAM"
          write_access: TRUE

    STAGE:
      env_suffix: "_STG"
      teams:
        - name: "TEST_TEAM_A"
          write_access: TRUE
        - name: "TEST_TEAM_B"
          write_access: FALSE

    PROD:
      env_suffix: ""
      teams:
        - name: "Marketing"
          write_access: FALSE
        - name: "Finance"
          write_access: FALSE
          wh_size: "LARGE"
        - name: "HR"
          write_access: FALSE
        - name: "IT"
          write_access: TRUE

创建对象定义文件

DCM project 定义文件是一个模板,解析后可用于管理 Snowflake 对象的有效 SQL 语句。每个 DCM project 至少需要一个定义文件。

您可以跨多个文件和文件夹组织对象定义和授权。Snowflake 建议选择能够体现项目业务逻辑的结构(例如,青铜层、银层和金层),而不是按对象类型进行分组。

定义文件只能包含 DEFINE、GRANT 或 ATTACH 语句。不支持其他 SQL 命令。

为了快速上手 DCM Projects,您可以通过使用 DEFINE 关键字来处理您现有的 DDLs(针对支持的对象类型),从而转换现有的 SQL 部署脚本。

DEFINE 语句的工作方式类似于 CREATE OR ALTER <对象> 命令,但有以下主要区别:

  • DEFINE 语句的顺序和位置并不重要。在项目执行期间,Snowflake 会收集所有定义文件中的所有语句并对其进行排序。

  • 如果移除 DEFINE 语句,Snowflake 会在您下次部署项目时删除相应的对象。

  • 仅支持 Snowflake 对象的子集。DCM Projects 中支持的对象类型 是 Web 令牌 ()、 令牌或 编程访问令牌 。有关详细信息,请参阅 DCM Projects 中支持的对象类型

  • 所有对象都必须使用 database.schema.object_name 格式的完全限定名称进行定义。

定义文件可以包含各种 Jinja2 模板化 选项并支持高级模板功能,这些功能允许您执行以下操作:

  • 使用模板变量在运行时自定义文件内容。

  • 对循环和条件等逻辑使用 Jinja2 语法。

  • 使定义文件可重用并适应不同的场景。

对象定义模板化

DCM Projects 支持使用 Jinja2 框架为 SQL 语句创建模板。您可以使用 Jinja2 语法,通过配置文件、在 EXECUTE DCM PROJECT 命令中或在 Jinja 内部声明变量并赋值。您还可以通过值列表构建循环、case 语句、可重用函数等等。有关更多信息,请参阅 Jinja2 文档 (https://jinja.palletsprojects.com/en/stable/)。

支持的 Jinja2 功能包括:

  • 字符串替换

  • 列表

  • 字典和嵌套字典

  • 条件(IF 语句)

  • 循环

  • 全局宏和文件内宏

    • sources/macros 文件夹中定义的宏可用于所有定义文件。

    • 文件中定义的宏可以在文件中使用。

不支持的 Jinja2 功能包括:

  • 使用以下标签:

    • import (https://jinja.palletsprojects.com/en/stable/templates/#import)

    • extends (https://jinja.palletsprojects.com/en/stable/templates/#extends)

    • include (https://jinja.palletsprojects.com/en/stable/templates/#include)

备注

_snow 标识符被保留供将来使用,不能用作变量或宏名称。

重要

请勿在包含敏感信息或凭据的对象定义中使用 DCM Projects 模板变量。渲染的 SQL 定义不会编辑环境变量插入的任何值。

同样,在使用 Snowflake 服务时,请勿将任何个人数据、敏感数据、受出口管制数据或其他受监管数据输入为元数据,例如文件名、配置和变量名。有关更多信息,请参阅 Snowflake 中的元数据字段

以下是一个使用 Jinja2 模板的 DCM project 定义文件示例:

DEFINE WAREHOUSE DCM_PROJECT_WH_{{db}}
  WITH
    warehouse_size = '{{wh_size}}'
    auto_suspend = 300;

以下是一个示例 DCM project 清单文件 (manifest.yml),其中定义了两个配置:DEV 和 PROD。

templating:
  configurations:
    DEV:
      db: "DEV_2"
      wh_size: "X-SMALL"
    PROD:
      db: "PROD"
      wh_size: "LARGE"

使用 DEV 配置(通过目标的 templating_config 自动选择或在运行时选择)渲染此仓库定义后,结果如下:

DEFINE WAREHOUSE DCM_PROJECT_WH_DEV_2
  WITH
    warehouse_size = "X-SMALL"
    auto_suspend = 300;

宏文件是位于 macros 文件夹及其子文件夹中的任何 SQL 文件。它们只能包含宏。

包含宏文件的 DCM project 目录结构示例如下:

My_dcm_project
 |_ manifest.yml
 |_ sources
    |_ definitions
       |_ my_definitions.sql
    |_ macros
       |_ my_global_macros.sql

类似于常规编程语言中的函数,宏有助于将常用代码片段组织成可重用的函数,从而避免重复并遵循 DRY(不要重复自己)原则。DCM Projects 中的宏与 Jinja2 宏 (https://jinja.palletsprojects.com/en/stable/templates/#macros) 的工作方式相同,但有以下例外:

  • macros 文件夹中宏文件的专用位置。

  • 宏文件中定义的宏在其他源文件中自动可见。不允许使用 import (https://jinja.palletsprojects.com/en/stable/templates/#import) Jinja 标签。

  • 检测到同名宏的重复定义,并予以拒绝。

自动导入全局宏

在定义文件渲染过程中,会扫描源文件以查找潜在的宏调用。如果被调用的宏在宏文件中定义,则会自动添加隐式的 from [...] import 标签 (https://jinja.palletsprojects.com/en/stable/templates/#import),因此无需显式导入。

类似于 Jinja2 宏 (https://jinja.palletsprojects.com/en/stable/templates/#macros),可以通过在本地宏前加上下划线来定义本地宏。本地宏只能在声明它的文件中使用,对其他文件不可见。

模板注释

在 SQL 命令中,您可以在代码前添加 -- 来注释掉该行。Jinja 仍会处理 SQL 代码,但保留 SQL 注释。

例如,以下 Jinja 代码:

-- hello {{ project_owner_role }}

渲染为:

-- hello DCM_DEVELOPER

注释掉的命令不会在 SQL 中执行。您可以使用模板注释来调试 Jinja 模板,而不会影响您的 SQL 代码。

要在渲染期间忽略 Jinja 代码,请在左括号和右括号内添加 #,如以下示例所示:

{# This Jinja comment will not appear in the rendered output. #}

配置

在对象定义中使用模板时,您有以下选项:

  • 在运行时为变量赋值。

  • manifest.yml 中的 templating: configurations: 下定义不同的配置配置文件。每个目标都可以通过 templating_config 引用配置。有关更多详细信息,请参阅 项目模板配置

    如果定义了配置配置文件,并且目标通过 templating_config 引用了其中一个,则在使用该目标时会自动应用该配置。有关示例,请参阅 计划 DCM project

    在 DCM Projects 中,配置配置文件的主要用例是针对不同的环境。配置配置文件允许您执行以下操作:

    • 将相同的代码部署到多个环境。

    • 在非生产环境中以较小的规模测试生产代码。

    • 在同一账户上维护多个隔离环境。

    并非所有模板化配置都必须由目标配置文件引用。您可以保留未使用的配置,以便将目标的模板化配置从一个配置切换到另一个配置。

  • templating: defaults: 下定义共享的默认值,以避免在各配置中重复公共变量。有关更多详细信息,请参阅 项目模板配置

  • 在 CLI 中使用 --variable 标志,在运行时用一次性值覆盖特定变量。

变量使用三层层次结构解析:全局默认值 < 配置变量 < 运行时执行变量。

字典

DCM Projects 模板化支持将字典作为变量值,从而为复杂的多租户或多资源部署提供结构化配置。

通过将相关的配置详细信息分组到字典中,您可以获得:

  • 精细控制:将特定设置(如仓库大小、保留策略和授权)应用于各个资源,而无需为每种变化编写独特的逻辑。

  • 更简洁的代码库:用动态循环替换重复的硬编码脚本,这些循环会根据配置进行调整。

  • 可扩展性:通过向配置中添加条目来接入新团队或资源,而不是重构部署管道。

备注

字典可以在清单中定义,但不能在运行时通过 --variable 标志或 SQL USING CONFIGURATION (...) 覆盖进行重写。只有标量值和列表可以在运行时被覆盖。

字典的用例示例:多租户环境预置

考虑一个由多个部门共享的平台,例如市场部、财务部和 HR,每个部门都有不同的合规性和计算需求。使用字典,您可以定义一个满足每个团队需求的配置。

清单示例:

templating:
  defaults:
    user: "GITHUB_ACTIONS_SERVICE_USER"
    wh_size: "X-SMALL"
  configurations:
    PROD:
      env_suffix: ""
      project_owner_role: "DCM_PROD_DEPLOYER"
      teams:
        - name: "Marketing"
          wh_size: "MEDIUM"
          data_retention_days: 14
          needs_sandbox_schema: true
        - name: "Finance"
          wh_size: "X-LARGE"
          data_retention_days: 90
          needs_sandbox_schema: false
        - name: "HR"
          data_retention_days: 30
          needs_sandbox_schema: false

定义示例:

您的 SQL 模板会循环遍历此字典。它会自动创建架构、分配正确的保留策略,并仅为有需求的团队有条件地创建额外资源。

-- loop through team dictionaries
{% for team in teams %}
    {% set team_name = team.name | upper %}

    -- inject dictionary values directly into object properties
    define schema DCM_DEMO_1{{env_suffix}}.{{team_name}}
        comment = 'using JINJA dictionary values'
        data_retention_time_in_days = {{ team.data_retention_days }};

    -- pass the name to your macro
    {{ create_team_roles(team_name) }}

    define table DCM_DEMO_1{{env_suffix}}.{{team_name}}.PRODUCTS(
        ITEM_NAME varchar,
        ITEM_ID varchar,
        ITEM_CATEGORY array
    )
    data_metric_schedule = 'TRIGGER_ON_CHANGES';

    {% if team_name == 'HR' %}
        define table DCM_DEMO_1{{env_suffix}}.{{team_name}}.EMPLOYEES(
            NAME varchar,
            ID int
        )
        comment = 'This table is only created in HR';
    {% endif %}

    -- use dictionary booleans to deploy optional infrastructure
    {% if team.needs_sandbox_schema | default(false) %}
        define schema DCM_DEMO_1{{env_suffix}}.{{team_name}}_SANDBOX
            comment = 'Sandbox schema defined via dictionary flag'
            data_retention_time_in_days = 1;
    {% endif %}

{% endfor %}