如何在Jsonnet中获取指定路径下的所有子目录?
实现方案
Jsonnet本身是无副作用的纯配置语言,没有内置遍历本地文件系统的能力,所有外部数据必须通过导入、外部传参的方式传入,你要的读取子目录列表的需求可以按下面的方法实现:
方案1:预生成目录JSON后导入(最推荐,兼容性最好)
这是GitLab CI场景下最稳定的实现方式,不依赖Jsonnet的特殊扩展:
- 在执行Jsonnet生成CI配置的前置步骤中,先跑系统命令把目标路径下的子目录名输出为JSON数组文件:
# 提取customers下所有一级子目录名,输出为JSON数组 find path/to/customers-directory -mindepth 1 -maxdepth 1 -type d -printf "%f\n" | jq -R . | jq -s . > customer_dirs.json - 在Jsonnet代码中直接导入这个生成的文件,就拿到了目录名数组:
local customer_dirs = import "customer_dirs.json"; { // 对应你写的伪代码逻辑 customers:: customer_dirs, // 后续直接遍历数组生成对应CI作业即可 gitlab_ci_jobs: { ["deploy_%s" % dir_name]: { stage: "deploy", script: "cd path/to/customers-directory/%s && ./run.sh" % dir_name, } for dir_name in customer_dirs } }
方案2:通过命令行外部变量直接传入
如果不想生成中间JSON文件,可以在执行Jsonnet命令时直接把目录列表作为外部变量传入:
- 调用Jsonnet时拼接好数组参数:
jsonnet \ --ext-code customer_dirs="$(find path/to/customers-directory -mindepth 1 -maxdepth 1 -type d -printf '"%f",' | sed 's/,$//' | awk '{print "["$0"]"}')" \ -o .gitlab-ci.yml \ ci_template.jsonnet - 在Jsonnet中通过标准库读取外部变量:
local customer_dirs = std.extVar("customer_dirs"); { customers:: customer_dirs, // 后续作业生成逻辑和方案1一致 }
注意事项
- 不要尝试在Jsonnet内部实现直接读目录的逻辑,这门语言的设计就禁止运行时发起无约束IO,目的是保证任意环境下求值结果一致。
- 部分第三方Jsonnet运行时支持通过原生扩展调用文件系统接口,但这种方式会让你的配置绑定特定运行环境,跨环境跑很容易出问题,不推荐使用。
内容的提问来源于stack exchange,提问作者Christian Müller
相关产品推荐
相关产品推荐

