Ansible调用Harbor API时字符串ID转整数失败如何解决?
问题解决方案
你遇到的422错误核心是提交的JSON中id、project_id字段实际还是字符串类型,并非数值类型,Harbor后端Go语言的结构体严格要求对应字段为int64类型,无法自动转换字符串格式的数值。绝大多数情况下该问题是YAML书写时错误给jinja2表达式加了引号,导致转成int的数值又被包裹为字符串导致的。
步骤1:先验证原始字段类型
先执行debug任务确认GET返回的字段确实为字符串类型,排除其他问题:
- name: 验证返回字段类型 ansible.builtin.debug: msg: - project_id值:{{ item.project_id }},类型:{{ item.project_id | type_debug }} - retention_id值:{{ item.metadata.retention_id }},类型:{{ item.metadata.retention_id | type_debug }} loop: "{{ projects_result.json }}"
如果输出类型确实为AnsibleUnicode或者str,继续后续操作。
步骤2:正确编写PUT请求的uri任务
注意两个核心规则:
- 必须指定
body_format: json,让Ansible自动将YAML格式的body序列化为合法JSON,保留数值类型 - 数值类型的字段(id、project_id)的jinja2表达式不要加引号包裹,避免转成的int又被封装为字符串
正确的任务示例:
- name: 更新Harbor项目镜像保留规则 ansible.builtin.uri: url: "https://<你的Harbor域名>/api/v2.0/projects/{{ item.project_id | int }}/retention" method: PUT headers: Authorization: "Basic {{ (harbor_admin_username + ':' + harbor_admin_password) | b64encode }}" validate_certs: no body_format: json body: # 注意以下两个字段的jinja2表达式没有加引号 id: {{ item.metadata.retention_id | int }} project_id: {{ item.project_id | int }} # 其他保留规则字段按你的需求填写,以下为示例 algorithm: "or" rules: - action: "retain" template: "latestPushedK" parameters: latestPushedK: 15 # 保留最近推送的15个镜像 tag_selectors: [] scope_selectors: repository: - kind: "doublestar" decoration: "matches" pattern: "**" # 匹配项目下所有镜像仓库 status_code: 200 loop: "{{ projects_result.json }}"
可选:预处理变量避免类型问题
如果上述写法还是出现问题,可以先将字段转成整数存入事实变量,再调用:
- name: 预处理ID字段为整数类型 ansible.builtin.set_fact: processed_retention_id: "{{ item.metadata.retention_id | int }}" processed_project_id: "{{ item.project_id | int }}" loop: "{{ projects_result.json }}" register: processed_result - name: 提取处理后的项目列表 ansible.builtin.set_fact: processed_projects: "{{ processed_result.results | map(attribute='ansible_facts') | list }}" - name: 更新保留规则 ansible.builtin.uri: # 省略其他配置,和上面一致 body: id: {{ item.processed_retention_id }} project_id: {{ item.processed_project_id }} # 其他字段省略 loop: "{{ processed_projects }}"
验证方法
执行前可以加debug任务查看即将提交的字段格式,如果输出的id、project_id没有引号,就是正确的数值类型:
- name: 验证提交字段格式 ansible.builtin.debug: msg: id: {{ item.metadata.retention_id | int }} project_id: {{ item.project_id | int }} loop: "{{ projects_result.json }}"
内容的提问来源于stack exchange,提问作者nagilli
相关产品推荐
相关产品推荐

