Create datasource/database (if not exists) via the Metabase API using Ansible

Hey everyone!

In one of my Ansible playbooks I use the POST /api/database API endpoint to create a database (a.k.a., datasource) so that my users find it there already when they log in. Before creating it I wanted to check whether it existed, to avoid duplicating it. It took me a while to figure it out, so here is the code for future reference:

- name: Create a data source for the Metabase Warehouse database
  tags:
    - datasource
  delegate_to: "{{ whs_mb_host }}"
  block:

    - name: Obtain a session token from Metabase
      ansible.builtin.uri:
        url: "http://localhost:3000/api/session"
        method: POST
        headers:
          Accept: "application/json"
          Content-Type: "application/json"
        body:
          username: "{{ user }}"
          password: "{{ password }}"
        body_format: "json"
        status_code: 200
        timeout: 5
      register: mbtoken # Data will be inside `mbtoken.json` by design

    - name: Retrieve existing datasources
      ansible.builtin.uri:
        url: "http://localhost:3000/api/database"
        method: GET
        headers:
          Accept: "application/json"
          Content-Type: "application/json"
          X-Metabase-Session: "{{ mbtoken.json.id }}"
        status_code: 200
        timeout: 5
      register: datasources

    - name: Add a data source for the Metabase Warehouse database
      ansible.builtin.uri:
        url: "http://localhost:3000/api/database"
        method: POST
        headers:
          Accept: "application/json"
          Content-Type: "application/json"
          X-Metabase-Session: "{{ mbtoken.json.id }}"
        body:
          auto_run_queries: true
          advanced-options: true
          details:
            dbname: "{{ whsdb_name }}"
            host: "{{ whsdb_host }}"
            json-unfolding: true
            let-user-control-scheduling: false
            password: "{{ password }}"
            port: 5432
            schema-filters-type: "all"
            ssl: true
            ssl-mode: "verify-full"
            ssl-root-cert-options: "local"
            ssl-root-cert-path: "/etc/ssl/certs/ISRG_Root_X1.pem"
            ssl-user-client-auth: false
            tunnel-enabled: false
            user: "{{ whsdb_user }}"
          engine: "postgres"
          is_full_sync: true
          is_on_demand: false
          is_sample: false
          name: "Metabase Warehouse"
          refingerprint: false
        body_format: "json"
        status_code: 200
        timeout: 5
      when: whsds | length == 0
      vars:
        whsds: "{{ datasources.json.data | selectattr('details.dbname', 'match', whsdb_name) | map(attribute='name') }}"

Any feedback will be appreciated. Enjoy!

2 Likes