Install - .NET Dynamic Agent deployed via Ansible for .NET Framework Command Line Apps
Overview
During the vFunction Dynamic Agent installation via Ansible, the Agent is added to the Target Host as a ZIP file and configurable parameters are added to the Host in an installation.yaml. On the Host’s filessystem, the ZIP is unpacked and the installation.yaml is added to this location. An installation script is run to set the Agent configuration files. A separate script is used to start the Application with the Agent hooked into the running Application via COR_PROFILER process-level Environment Variables.
Prerequisites
- vFunction Windows Controller Installation TGZ downloaded to Ansible Management Host
- Ansible with WinRM connectivity to the Target Host(s) (pip install pywinrm)
- WinRM configured for Ansible Management on the Target Host(s)
- Prerequisites met on Target Host
Ansible Installation ZIP
The Ansible vFunction .NET Agent ZIP can be downloaded from here. The details below outline specific portions of this ZIP.
Layout
The Ansible vFunction .NET Agent should be configured in the following manner:
ansible-vfunction-dotnet-agent/
├── playbook.yml
├── requirements.yml
├── inventory.ini
├── group_vars/
│ └── windows.yml # all configurable values (edit this)
├── templates/
│ ├── installation.yaml.j2 # renders installation.yaml
│ └── start-thick-client.ps1.j2 # renders the COR_PROFILER launch script
└── files/
└── PLACE_ZIP_HERE.txt # drop the vFunction ZIP here
ansible-vfunction-dotnet-agent/playbook.yml
# Steps:
# 1. Move the Installation ZIP to the Windows host
# 2. Extract the vFunction Installation Package
# 3. Populate installation.yaml with the required configuration settings
# 4. Unblock files and run install.ps1 for the instance
# 5. Create a separate script that sets COR_PROFILER env vars and starts
# the thick client application
# 6. Run that script to launch the instrumented thick client
# ===========================================================================
- name: Install vFunction Dynamic Agent (.NET Framework, command-line workflow)
hosts: windows
gather_facts: false
vars:
vf_installation_yaml_dir: "{{ vf_base_dir }}\\vfunction\\config\\installation\\instances\\{{ vf_instance_name }}"
vf_controller_install_dir: "{{ vf_base_dir }}\\controller-installation"
vf_thick_client_script_path: "{{ vf_base_dir }}\\start-thick-client.ps1"
tasks:
# -----------------------------------------------------------------
# 1. Prep: create the base directory where vFunction will run
# -----------------------------------------------------------------
- name: Ensure vFunction base directory exists
ansible.windows.win_file:
path: "{{ vf_base_dir }}"
state: directory
# -----------------------------------------------------------------
# 2. Move the Installation ZIP to the Windows host
# -----------------------------------------------------------------
- name: Copy vFunction Controller Installation ZIP to the host
ansible.windows.win_copy:
src: "{{ vf_zip_local_path }}"
dest: "{{ vf_zip_remote_path }}"
# -----------------------------------------------------------------
# 3. Extract the vFunction Installation Package
# -----------------------------------------------------------------
- name: Extract the vFunction Installation Package
community.windows.win_unzip:
src: "{{ vf_zip_remote_path }}"
dest: "{{ vf_base_dir }}"
remote_src: true
# Unblock extracted files:
- name: Unblock extracted vFunction files
ansible.windows.win_shell: |
Get-ChildItem -Path '{{ vf_base_dir }}' -Recurse | Unblock-File
# -----------------------------------------------------------------
# 4. Populate installation.yaml with the required configuration
# settings
# -----------------------------------------------------------------
- name: Ensure installation.yaml target directory exists
ansible.windows.win_file:
path: "{{ vf_installation_yaml_dir }}"
state: directory
- name: Deploy installation.yaml with vFunction configuration
ansible.windows.win_template:
src: templates/installation.yaml.j2
dest: "{{ vf_installation_yaml_dir }}\\installation.yaml"
no_log: true # contains client_secret
# -----------------------------------------------------------------
# 5. Run install.ps1 for the instance
# -----------------------------------------------------------------
- name: Run vFunction install.ps1 for instance {{ vf_instance_name }}
ansible.windows.win_shell: |
& '{{ vf_controller_install_dir }}\install.ps1' -instance {{ vf_instance_name }}
args:
chdir: "{{ vf_controller_install_dir }}"
register: vf_install_result
- name: Show install.ps1 output
ansible.builtin.debug:
var: vf_install_result.stdout_lines
# -----------------------------------------------------------------
# 6. Create a separate script that sets the COR_PROFILER variables
# and starts the thick client application
# -----------------------------------------------------------------
- name: Deploy thick-client launch script with COR_PROFILER variables
ansible.windows.win_template:
src: templates/start-thick-client.ps1.j2
dest: "{{ vf_thick_client_script_path }}"
# -----------------------------------------------------------------
# 7. Run the script to start the instrumented thick client
# -----------------------------------------------------------------
- name: Launch the instrumented thick client
ansible.windows.win_shell: |
Start-Process -FilePath 'powershell.exe' `
-ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File','{{ vf_thick_client_script_path }}' `
-WindowStyle Normal
when: vf_start_thick_client | bool
async: 5
poll: 0
- name: Confirm thick client launch was triggered
ansible.builtin.debug:
msg: >
Thick client launch script '{{ vf_thick_client_script_path }}' has been triggered.
Confirm on the host that the application comes up and functions as expected.
If issues arise, see:
https://kb.vfunction.com/installations/known-issues/mono-dynamic-agent/dotnet
and
https://kb.vfunction.com/installations/general-troubleshooting/mono-dynamic-agent/dotnet/host/
when: vf_start_thick_client | bool
ansible-vfunction-dotnet-agent/group_vars/windows.yml
# ---------------------------------------------------------------------------
# vFunction installation package
# ---------------------------------------------------------------------------
# Local path (on the Ansible control node) to the vFunction Windows Controller
# Installation ZIP downloaded from:
# https://portal.vfunction.com/files/shares/installation-files/controller
vf_zip_local_path: "files/vfunction-controller-installation.zip"
# Location on the Windows target where vFunction should run/be extracted
vf_base_dir: "C:\\vFunction"
vf_zip_remote_path: "{{ vf_base_dir }}\\vfunction-controller-installation.zip"
vf_instance_name: "default-dotnet"
# ---------------------------------------------------------------------------
# installation.yaml - controller settings
# (see https://kb.vfunction.com/installations/configurable-settings/mono-dynamic-agent/dotnet/windows/#required)
# ---------------------------------------------------------------------------
vf_controller_name: "CHANGE_ME" # UI identifier for the Agent, e.g. QA-Win1-BillPay
vf_controller_host: "CHANGE_ME" # e.g. https://vfunction.organization.com
vf_org_id: "CHANGE_ME" # UUID from VF Server UI Install Instructions dialog
vf_app_id: "CHANGE_ME" # UUID from VF Server UI Install Instructions dialog
vf_client_id: "CHANGE_ME" # UUID from VF Server UI Install Instructions dialog
# Store this in an Ansible Vault-encrypted file/variable, never in plaintext:
vf_client_secret: "CHANGE_ME" # ansible-vault encrypt_string this value
vf_tags:
- "CHANGE_ME" # e.g. "prod" or "BillPay"
# instrconf_additions (optional inclusions/exclusions)
vf_instrconf_inclusions: []
vf_instrconf_exclusions: []
# agent block - fixed values required for the Framework / command-line workflow
vf_agent_version: "framework"
vf_agent_environment: "command"
# ---------------------------------------------------------------------------
# Thick client application to instrument
# ---------------------------------------------------------------------------
# Full path to the executable that starts the thick client application
vf_run_app_path: "C:\\Program Files\\MyThickClient\\MyThickClient.exe"
# Optional arguments passed to the thick client executable
vf_run_app_args: ""
# Whether to fire off the thick client launch script at the end of the play
# (set to false if you'd rather start it manually / via logon script)
vf_start_thick_client: true