Ansible: using the Evergreen API for collecting Windows apps

02 Feb 2023 by Ryan Ververs-Bijkerk

Category:

    Ansible

Ansible: using the Evergreen API for collecting Windows apps

Table of Content

Obtaining the latest version of an application can often be a challenge. To address this issue, tools and projects such as Chocolaty, WinGet, or Evergreen were created. However, there may be situations where using these solutions is not permitted, and manual management is required. The Evergreen API enables you to retrieve information on the latest version of an application, while still managing the download and installation process yourself. This blog post will demonstrate an example of using the new Evergreen API in an Ansible playbook.

What is Evergreen?

Evergreen is a PowerShell module that provides the latest version numbers and download URLs for common Windows applications. The module features simple functions for tasks such as:

Retrieving the latest version of an application for comparison with a previously installed or downloaded version. Returning the URL for the latest version of the application for local installation or deployment to target machines.

This project is managed by Aaron Packer, also known as stealthpuppy, and is available on GitHub to the public.

Recently, Aaron introduced the Evergreen API in a tweet:

As stated in the tweet, the API allows for the use of Evergreen without installing the necessary PowerShell modules. This is a valuable addition to the project, as it enables individuals like myself to utilize Evergreen while still maintaining control over the installation process.

Exploring the Evergreen API

The following page contains documentation on how to use the Evergreen API: How to use the Evergreen API - Evergreen (stealthpuppy.com)

A Swagger page is also available, enabling you to directly execute the API and view the results within the Swagger interface. In addition to clear documentation, the Swagger interface is useful in gaining a better understanding of the API structure.

evergreen-api - 1.0.0 - stealthpuppy - SwaggerHub

There are two basic API calls:

  • /apps, which returns all available applications.
  • /app/{appName}, which returns the details of a specific application.

Both API calls are publicly accessible and do not require any form of authentication.

The schema of an application will always include a version and URI. The URI will contain the download link for the setup file. It is important to note that the other properties may vary among different applications. For example:

[
  {
    "Version": "22.01",
    "Architecture": "ARM32",
    "Type": "exe",
    "URI": "https://nchc.dl.sourceforge.net/project/sevenzip/7-Zip/22.01/7z2201-arm.exe"
  }
]

[
  {
    "Version": "22.003.20314",
    "Language": "MUI",
    "Architecture": "x64",
    "Name": "Reader DC 2022.003.20314 MUI for Windows-64bit",
    "URI": "https://ardownload2.adobe.com/pub/adobe/acrobat/win/AcrobatDC/2200320314/AcroRdrDCx642200320314_MUI.exe"
  }
]

Using the Evergreen API in an Ansible playbook

The following demonstrates how to utilize the Evergreen API in practice. This example focuses on retrieving the latest version of Microsoft Visual Studio Code (since it’s the best editor ever!).

When accessing the information through the Swagger API, it becomes apparent that multiple installers are available. To retrieve the desired version, filtering is necessary based on specific criteria:

  • Architecture: x64
  • Channel: Stable
  • Platform: win32-x64

The output will be the installer for the 64-bit machine. The playbook will follow these steps:

  • Collect the available version
  • Apply filter
  • Install application

The API call can be executed and the required information can be collected by utilizing the win_uri module.

  - name: "Collect Evergreen info for {{ app_name }}"
    win_uri:
      url: "https://evergreen-api.stealthpuppy.com/app/{{ app_name }}"
      method: GET
      content_type: application/json
      return_content: true
    register: app

The app.json return value will be equivalent to the results of the Swagger API, which is a list of available installers.

A json_query filter can be applied to obtain the correct version:

  - name: "Set Evergreen object for {{ app_name }}"
    set_fact:
      app_details: "{{ app.json | json_query('[?Architecture == `x64` && Channel == `Stable` && Platform == `win32-x64`]') | first }}"

By selecting the first result, only one property will be returned, ensuring that app_details is a single object rather than a list.

Based on the details, the application can be installed:

  - name: "Install {{ app_name }} {{ app_details.Version }}"
    win_package:
      path: "{{ app_details.URI }}"
      creates_path: C:\Program Files\Microsoft VS Code\Code.exe
      arguments: /VERYSILENT /NORESTART /MERGETASKS=!runcode
      expected_return_code: [0]
      state: present

The application can then be installed based on the details. The win_package path can be a URL, allowing for direct download of the setup from the internet. It is important to note that an internet connection is required for both using the API and downloading the setup. Example playbook:

---
- name: Test Evergreen
  hosts: mngt
  vars_files:
  - ansible.yml
  - domain.yml
  tasks:

  - name: Update fact to MicrosoftVisualStudioCode
    set_fact:
      app_name: MicrosoftVisualStudioCode

  - name: "Collect Evergreen info for {{ app_name }}"
    win_uri:
      url: "https://evergreen-api.stealthpuppy.com/app/{{ app_name }}"
      method: GET
      content_type: application/json
      return_content: true
    register: app

  - name: "Set Evergreen object for {{ app_name }}"
    set_fact:
      app_details: "{{ app.json | json_query('[?Architecture == `x64` && Channel == `Stable` && Platform == `win32-x64`]') | first }}"

  - name: "Install {{ app_name }} {{ app_details.Version }}"
    win_package:
      path: "{{ app_details.URI }}"
      creates_path: C:\Program Files\Microsoft VS Code\Code.exe
      arguments: /VERYSILENT /NORESTART /MERGETASKS=!runcode
      expected_return_code: [0]
      state: present

Conclusion

Evergreen was already a robust project, but with the addition of the Evergreen API, it can be consumed in even more versatile ways. This blog post demonstrated an example of integrating the API in an Ansible playbook, showcasing its benefits.

However, there are a few areas for improvement. The “app” object returns various properties that vary between applications. Consistency across all packages would be more advantageous, as it would allow for the use of a single filter, for example. At the time of writing, there is also no information in the API regarding the required installation parameters. Including this information in the API would be valuable, so you don’t have to search for it elsewhere in the project.

Despite these areas for improvement, I am truly impressed with the Evergreen API. I was able to create this example from scratch within 15 minutes. Keep up the great work, Aaron, and I look forward to following the progress of your project.

Photo by fabio on Unsplash

Tags:
    ansible
    dsc
    code
    evergreen
Ryan Ververs-Bijkerk
Written by Ryan Ververs-Bijkerk

Ryan is a self-employed technologist at GO-INIT who specializes in the EUC and code area. He primarily focuses on the user experience in centralized desktop environments.

Search

    Follow me

    Community