Connecting to the FileMaker Data API using Ansible

Ansible, FileMaker Data API

Connecting to the FileMaker Data API using Ansible

We do lots of work with FileMaker, particularly with the FileMaker Data API. We also use Ansible for lots of the deployments we do of web applications we build.

Recently we needed to put both of these things together because we needed to pull information from FileMaker and make decisions in Ansible about what needed to be done based on data in a FileMaker field.

As with most APIs the first thing we needed to do was to authenticate against FileMaker. To do that we make use of the Ansible uri module, run as a local task.

- name: Login to the remote FileMaker server
  local_action:
    module: uri
    url: "https://{{ filemaker_server }}/fmi/data/v1/databases/{{ filemaker_file }}/sessions"
    method: POST
    force_basic_auth: yes
    url_username: "{{ dapi_username }}"
    url_password: "{{ dapi_password }}"
    return_content: yes
    status_code: 200
    body: ""
    body_format: json
  register: response

Breaking this down:

local_action: Tell Ansible that we want to run this command locally. There’s no need to ssh into the remote server to perform an API call which we can do from anywhere.
module: uri The task we want to perform uses the uri module.
url: “https://{{ filemaker_server }}/fmi/data/v1/databases/{{ filemaker_file }}/sessions” Define the location to connect to. We’re using two variables filemaker_server and filemaker_file so they only need to be modified in one place if things change.
method: POST Perform this as a post – this is required by the FileMaker Data API.
force_basic_auth: yes Force the URI module to use BASIC Authentication, since this is the only option supported by the FileMaker Data API.
url_username: “{{ dapi_username }}” The username to send, stored in an Ansible variable.
url_password: “{{ dapi_password }}” The password to send, stored in an Ansible variable. Make sure you’re using ansible-vault to encrypt any file containing password variables!
return_content: yes We want to get the result of the call back.
status_code: 200 We expect status code 200 – anything else will be deemed as a failure by Ansible.
body: “” We have to explicitly set the post body to an empty string. Anything else, including omitting the body entirely will upset the FileMaker Data API and you won’t get your token back!
body_format: json Even though we’re setting the body to be an empty string, we need to specify the body format as JSON so that the correct Content-Type header is sent. I agree that this seems odd given we’re sending an empty string, however this combination of settings is the only way we can get this to work!
register: response This tells Ansible that we want the response from the API call to be stored in the variable response.

Next we need to extract the returned token. We’re going use set_fact to store that as a variable for later use. Because the response we receive from the FileMaker Data API is a JSON object we can access the token itself using ‘dot’ notation.

- name: Extract the token from the response
  set_fact:
    dapi_token: "{{ response.json.response.token }}"

Now that we have the token we can begin communicating with the FileMaker Data API. Again we use the uri module running as a local action.

Many of the parameters are the same as logging in, but we also need to send the token back in an Authorization header. In the code below we’re getting the record from the Version layout, which has (internal FileMaker) record ID 1. If you didn’t know exactly which record you needed, you could also perform a find query here – see the documentation for the FileMaker Data API for further details (that can be easily accessed from https://your.fms.com/fmi/data/apidoc).

- name: Get the remote interface version data
  local_action:
    module: uri
    url: "https://{{ filemaker_server }}/fmi/data/v1/databases/{{ interface_file }}/layouts/Version/records/1"
    method: GET
    return_content: yes
    status_code: 200
    headers:
      Authorization: "Bearer {{ dapi_token }}"
  register: response

Again we’re storing the response from the API call in the response variable. For our purposes we needed the content of the VersionBuild field. Again the response is a JSON object so we can traverse that tree to the data point we need.

- name: Set remote build version
  set_fact:
    remote_build: "{{ response.json.response.data[0].fieldData.VersionBuild | int }}"
  tags:
    - api

You’ll note that we use data[0] because even though we’re only requesting a single record (by record ID) the FileMaker Data API still returns an array of record objects.

At this stage we don’t need to write data back to FileMaker but that would also be possible to do using the same techniques above, for example to write a log record recording that a deployment had been completed.

Leave A Comment

*
*