├── .gitignore ├── README.md ├── defaults └── main.yml ├── meta └── main.yml ├── tasks ├── Darwin.yml ├── Linux.yml ├── Windows.yml └── main.yml └── vars ├── Darwin.yml ├── Linux.yml ├── Windows.yml ├── dependencies-Debian-10.yml ├── dependencies-Debian-9.yml ├── dependencies-RedHat-7.yml ├── dependencies-Ubuntu-16.yml ├── dependencies-Ubuntu-18.yml └── dependencies-Ubuntu-20.yml /.gitignore: -------------------------------------------------------------------------------- 1 | vagrant/.vagrant 2 | vagrant/*.retry 3 | vagrant/vars.yml 4 | .idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Azure DevOps Agent 2 | 3 | An Ansible role that installs and configures a Linux machine to be used as an [Azure DevOps build or deployment agent](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-linux?view=azure-devops). 4 | 5 | See [this blog post](https://medium.com/gsoft-tech/easily-configuring-an-azure-devops-agent-with-ansible-fb9cb0f98b73) for more detail. 6 | 7 | ## Requirements 8 | 9 | [See prerequisites](https://github.com/Microsoft/azure-pipelines-agent/blob/master/docs/start/envlinux.md) 10 | 11 | Installing on MacOS can be problematic when trying to use an admin user for connecting and another user for running the service. 12 | pipelining = True can help, especially if you run into issues where the devops agent user cannot access the temporary files ansible is creating. 13 | 14 | ## Role Variables 15 | 16 | Available variables are listed below, along with default values (see `defaults/main.yml`): 17 | 18 | ```yaml 19 | az_devops_accountname: null 20 | az_devops_accesstoken: null 21 | az_devops_project_name: null 22 | az_devops_agent_version: 2.188.3 23 | az_devops_agent_user: "az_devops_agent" 24 | az_devops_agent_uid: null 25 | az_devops_agent_name: "{{ ansible_hostname }}" 26 | az_devops_server_url: "https://dev.azure.com/{{ az_devops_accountname }}" 27 | az_devops_agent_folder: "/home/{{ az_devops_agent_user }}/agent/" 28 | az_devops_work_folder: "/home/{{ az_devops_agent_user }}/agent/_work" 29 | az_devops_agent_pool_name: "Default" 30 | az_devops_agent_role: "build" 31 | az_devops_deployment_group_tags: null 32 | az_devops_environment_name: null 33 | az_devops_deployment_group_name: null 34 | az_devops_agent_replace_existing: false 35 | az_devops_reconfigure_agent: false 36 | az_devops_agent_user_capabilities: null 37 | az_devops_proxy_url: null 38 | az_devops_proxy_username: null 39 | az_devops_proxy_password: null 40 | ``` 41 | 42 | - **az_devops_accountname** 43 | 44 | The name of your Azure DevOps account, i.e. https://dev.azure.com/YOUR_ACCOUNT_NAME 45 | 46 | - **az_devops_accesstoken** 47 | 48 | The Personal Access Token (PAT) used to authenticate to your account. [See here for details on how to generate this value](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-linux?view=vsts#authenticate-with-a-personal-access-token-pat). 49 | 50 | _Note: Think about using Ansible Vault to secure this value._ 51 | 52 | - **az_devops_project_name** 53 | 54 | The name of the Azure DevOps project in which to register the agent (only used for deployment groups). 55 | 56 | - **az_devops_agent_version** 57 | 58 | Version of the installed agent package. Should be periodically updated to the latest version (see [here](https://github.com/microsoft/azure-pipelines-agent/releases/latest)). 59 | 60 | - **az_devops_agent_user** 61 | 62 | Name of the user used to run and configure the service. 63 | 64 | - **az_devops_agent_uid** 65 | 66 | UID of the user used to run and configure the service. 67 | 68 | - **az_devops_agent_group** 69 | 70 | Default group of the user used to run and configure the service. 71 | 72 | - **az_devops_agent_name** 73 | 74 | Name of the agent shown in Azure DevOps (defaults to the name of the host.). 75 | 76 | - **az_devops_server_url** 77 | 78 | Url for your Azure DevOps account. 79 | 80 | - **az_devops_agent_folder** 81 | 82 | Folder location for all the agent specific files (note: important that the service user needs execution permissions on all the files in this folder). 83 | 84 | - **az_devops_work_folder** 85 | 86 | Folder location for all the work specific files (i.e. pulled source code and build results). 87 | 88 | - **az_devops_agent_pool_name** 89 | 90 | Pool name in which the Azure DevOps agent is added. 91 | 92 | - **az_devops_agent_role** 93 | 94 | Use either `build`, `deployment` or `resource`. Build role allows the use of the agent as a build server in pipeline build or releases. Deployment role allows the use of the agent in a deployment group. Resource role allows the use of the agent as a virtual machine resource that can be targeted by deployments from a pipeline and belongs to an environment. 95 | 96 | - **az_devops_deployment_group_tags** 97 | 98 | Use in conjuction with the `deployment` agent role. Allows the use of tags to identify the agent (ex: QA, Staging, Prod, etc.) 99 | 100 | - **az_devops_deployment_group_name** 101 | 102 | Use in conjuction with the `deployment` agent role. The name of the deployment group in which to add the agent. **This needs to be manually created in you Azure DevOps project beforehand.** 103 | 104 | - **az_devops_environment_name** 105 | 106 | Use in conjuction with the `resource` agent role. The name of the environment in which to add the VM resource. **This needs to be manually created in you Azure DevOps project beforehand.** 107 | 108 | - **az_devops_agent_replace_existing** 109 | 110 | Adds the `--replace` argument to the configuration script for the [scenario where you need to replace an exiting agent with a new host](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-linux?view=azure-devops#pool-and-agent-names). 111 | 112 | - **az_devops_reconfigure_agent** 113 | 114 | Forces a reconfiguration of the agent even if the service is already active 115 | 116 | - **az_devops_proxy_url** 117 | 118 | The URL of the proxy server, format is `http://url:port` 119 | 120 | This assumes the proxy does both http and https 121 | 122 | - **az_devops_proxy_username** 123 | 124 | Username for the proxy 125 | 126 | If the proxy does not require authentication, then just leave defaults 127 | 128 | - **az_devops_proxy_password** 129 | 130 | Password for the proxy 131 | 132 | Again if proxy does not require authentication, just leave the defaults. 133 | 134 | _Note: Think about using Ansible Vault to secure this value._ 135 | 136 | - **az_devops_agent_user_capabilties** 137 | 138 | A Dictionary of environment variables to set for the agent process which translate to User Capabilties which can be helpful for setting [release pipeline demands](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/demands?view=azure-devops&tabs=yaml) 139 | 140 | Example usage: 141 | 142 | ```yaml 143 | - az_devops_agent_user_capabilties: 144 | user_capabilty_key: user_capability_value 145 | ``` 146 | 147 | ## Example Playbooks 148 | 149 | ### Build Agent 150 | 151 | ```yaml 152 | - hosts: agents 153 | roles: 154 | - gsoft.azure_devops_agent 155 | vars: 156 | - az_devops_agent_role: build 157 | - az_devops_accountname: fubar 158 | - az_devops_accesstoken: *** 159 | ``` 160 | 161 | ### Deployment Agent 162 | 163 | ```yaml 164 | - hosts: agents 165 | roles: 166 | - gsoft.azure_devops_agent 167 | vars: 168 | - az_devops_agent_role: deployment 169 | - az_devops_accountname: fubar 170 | - az_devops_accesstoken: *** 171 | - az_devops_project_name: baz 172 | - az_devops_deployment_group_name: fubar_group 173 | - az_devops_deployment_group_tags: "web,prod" 174 | ``` 175 | 176 | ### Resource 177 | 178 | ```yaml 179 | - hosts: agents 180 | roles: 181 | - gsoft.azure_devops_agent 182 | vars: 183 | - az_devops_agent_role: resource 184 | - az_devops_accountname: fubar 185 | - az_devops_accesstoken: *** 186 | - az_devops_project_name: baz 187 | - az_devops_environment_name: staging 188 | ``` 189 | 190 | ### Proxy 191 | 192 | ```yaml 193 | - hosts: agents 194 | roles: 195 | - gsoft.azure_devops_agent 196 | vars: 197 | - az_devops_agent_role: build 198 | - az_devops_accountname: fubar 199 | - az_devops_accesstoken: *** 200 | - az_devops_proxy_url: "http://127.0.0.1:8080" 201 | - az_devops_proxy_username: bob 202 | - az_devops_proxy_password: *** 203 | ``` 204 | 205 | ## License 206 | 207 | Copyright © 2020, GSoft inc. This code is licensed under the Apache License, Version 2.0. You may obtain a copy of this license at https://github.com/gsoft-inc/gsoft-license/blob/master/LICENSE. 208 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | az_devops_agent_version: 2.188.3 2 | az_devops_agent_user: "az_devops_agent" 3 | az_devops_agent_name: "{{ ansible_hostname }}" 4 | az_devops_server_url: "https://dev.azure.com/{{ az_devops_accountname }}/" 5 | az_devops_agent_folder: "{{ az_devops_default_agent_folder }}" 6 | az_devops_work_folder: "{{ az_devops_default_work_folder }}" 7 | az_devops_agent_group: "{{ az_devops_default_agent_group }}" 8 | az_devops_agent_pool_name: "Default" 9 | az_devops_agent_role: "build" 10 | az_devops_agent_replace_existing: false 11 | az_devops_reconfigure_agent: false 12 | az_devops_project_name: null 13 | az_devops_agent_package_url: "{{ az_devops_default_agent_package_url }}" 14 | az_devops_environment_name: null 15 | az_devops_deployment_group_name: null 16 | az_devops_deployment_group_tags: null 17 | az_devops_proxy_url: null 18 | az_devops_proxy_username: null 19 | az_devops_proxy_password: null 20 | az_devops_agent_create_local_user: true 21 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | role_name: azure_devops_agent 3 | author: Yohan Belval 4 | description: Azure DevOps Agent for Linux. 5 | company: GSoft 6 | 7 | license: "license (Apache-2.0)" 8 | 9 | min_ansible_version: 2.4 10 | 11 | platforms: 12 | - name: Ubuntu 13 | versions: 14 | - xenial 15 | - bionic 16 | - focal 17 | - name: EL 18 | versions: 19 | - 7 20 | - name: Debian 21 | versions: 22 | - stretch 23 | - buster 24 | - name: Windows 25 | versions: 26 | - 2016 27 | - 2019 28 | - name: MacOSX 29 | versions: 30 | - 10.15 31 | 32 | galaxy_tags: 33 | - azure 34 | - devops 35 | - agent 36 | - build 37 | - deployment 38 | - ci 39 | - cd 40 | -------------------------------------------------------------------------------- /tasks/Darwin.yml: -------------------------------------------------------------------------------- 1 | - name: Add an agent user 2 | user: 3 | name: "{{ az_devops_agent_user }}" 4 | comment: "Azure DevOps Agent" 5 | shell: /bin/zsh 6 | group: "{{ az_devops_agent_group }}" 7 | uid: "{{ az_devops_agent_uid|default(omit) }}" 8 | become: true 9 | 10 | - name: Create directories 11 | file: 12 | state: directory 13 | path: "{{ item }}" 14 | owner: "{{ az_devops_agent_user }}" 15 | group: "{{ az_devops_agent_group }}" 16 | mode: 0755 17 | loop: 18 | - "{{ az_devops_launchagent_folder }}" 19 | - "{{ az_devops_agent_folder }}" 20 | - "{{ az_devops_work_folder }}" 21 | register: agent_directory 22 | become: true 23 | 24 | # Using get_url and shell to unarchive the agent as the unarchive module requires homebrew and 25 | # even then doesn't use the provided gnu tar. 26 | # Makes using ansible on macos a questionable endeavor (but some of us are left with that)... 27 | - name: Download agent 28 | get_url: 29 | url: "{{ az_devops_agent_package_url }}" 30 | dest: "{{ az_devops_default_agent_local_package }}" 31 | owner: "{{ az_devops_agent_user }}" 32 | group: "{{ az_devops_agent_group }}" 33 | mode: '0440' 34 | register: agent_download 35 | become: true 36 | 37 | - name: Unarchive agent 38 | shell: "cd {{ az_devops_agent_folder }} && tar -zxf {{ az_devops_default_agent_local_package }}" 39 | become: true 40 | become_user: "{{ az_devops_agent_user }}" 41 | when: agent_download.changed or agent_directory.changed 42 | tags: ['skip_ansible_lint'] 43 | 44 | - name: Check if svc.sh exists 45 | stat: 46 | path: "{{ '/'.join((az_devops_agent_folder, 'svc.sh')) }}" 47 | register: svc_sh 48 | become: true 49 | changed_when: false 50 | check_mode: no 51 | 52 | - name: Check service status 53 | command: ./svc.sh status 54 | become: true 55 | become_user: "{{ az_devops_agent_user }}" 56 | args: 57 | chdir: "{{ az_devops_agent_folder }}" 58 | register: svc_status 59 | changed_when: false 60 | check_mode: no 61 | when: svc_sh.stat.exists 62 | 63 | - name: Set agent config facts 64 | set_fact: 65 | agent_cmd_args: 66 | - "./config.sh" 67 | - "--unattended" 68 | - "--acceptteeeula" 69 | - "--url '{{ az_devops_server_url }}'" 70 | - "--work '{{ az_devops_work_folder }}'" 71 | - "--auth PAT" 72 | - "--token '{{ az_devops_accesstoken }}'" 73 | - "--runasservice" 74 | build_agent_cmd_args: 75 | - "--pool '{{ az_devops_agent_pool_name }}'" 76 | - "--agent '{{ az_devops_agent_name }}'" 77 | deployment_agent_cmd_args: 78 | - "--deploymentgroup" 79 | - "--deploymentgroupname '{{ az_devops_deployment_group_name }}'" 80 | - "--projectname '{{ az_devops_project_name }}'" 81 | resource_agent_cmd_args: 82 | - "--environment" 83 | - "--environmentname '{{ az_devops_environment_name }}'" 84 | - "--agent '{{ az_devops_agent_name }}'" 85 | - "--projectname '{{ az_devops_project_name }}'" 86 | service_is_installed: "{{ svc_status.stdout is defined and svc_status.stdout is not regex('not installed') }}" 87 | service_is_running: "{{ svc_status.stdout is defined and svc_status.stdout is regex('active \\(running\\)') }}" 88 | reconfigure_or_replace: "{{ az_devops_reconfigure_agent or az_devops_agent_replace_existing }}" 89 | 90 | - name: Add deployment group tags 91 | set_fact: 92 | deployment_agent_cmd_args: "{{ deployment_agent_cmd_args }} + 93 | ['--addDeploymentGroupTags', '--deploymentGroupTags \\'{{ az_devops_deployment_group_tags }}\\'']" 94 | when: 95 | - az_devops_deployment_group_tags is defined 96 | 97 | - name: Set proxy 98 | set_fact: 99 | agent_cmd_args: "{{ agent_cmd_args }} + ['--proxyurl \\'{{ az_devops_proxy_url }}\\'', 100 | '--proxyusername \\'{{ az_devops_proxy_username }}\\'', '--proxypassword \\'{{ az_devops_proxy_password }}\\'']" 101 | when: 102 | - az_devops_proxy_url is defined 103 | 104 | - name: Uninstall agent service 105 | command: ./svc.sh uninstall 106 | become: true 107 | become_user: "{{ az_devops_agent_user }}" 108 | args: 109 | chdir: "{{ az_devops_agent_folder }}" 110 | removes: "{{ az_devops_agent_folder }}/runsvc.sh" 111 | when: 112 | - service_is_installed 113 | - reconfigure_or_replace 114 | 115 | - name: Unconfigure agent 116 | command: "./config.sh remove --auth PAT --token {{ az_devops_accesstoken }}" 117 | args: 118 | chdir: "{{ az_devops_agent_folder }}" 119 | removes: "{{ az_devops_agent_folder }}/.agent" 120 | become: true 121 | become_user: "{{ az_devops_agent_user }}" 122 | when: 123 | - service_is_installed 124 | - reconfigure_or_replace 125 | 126 | - name: Add '--replace' configuration argument 127 | set_fact: 128 | build_agent_cmd_args: "{{ build_agent_cmd_args }} + ['--replace']" 129 | deployment_agent_cmd_args: "{{ build_agent_cmd_args }} + ['--replace']" 130 | resource_agent_cmd_args: "{{ resource_agent_cmd_args }} + ['--replace']" 131 | when: 132 | - az_devops_agent_replace_existing 133 | 134 | - name: Configure agent as a build server 135 | command: "{{ (agent_cmd_args + build_agent_cmd_args) | join(' ') }}" 136 | args: 137 | chdir: "{{ az_devops_agent_folder }}" 138 | creates: "{{ az_devops_agent_folder }}/.agent" 139 | become: true 140 | become_user: "{{ az_devops_agent_user }}" 141 | when: 142 | - az_devops_agent_role == 'build' 143 | - (not service_is_installed) or reconfigure_or_replace 144 | 145 | - name: Configure agent as a deployment server 146 | command: "{{ (agent_cmd_args + deployment_agent_cmd_args) | join(' ') }}" 147 | args: 148 | chdir: "{{ az_devops_agent_folder }}" 149 | creates: "{{ az_devops_agent_folder }}/.agent" 150 | become: true 151 | become_user: "{{ az_devops_agent_user }}" 152 | when: 153 | - az_devops_agent_role == 'deployment' 154 | - (not service_is_installed) or reconfigure_or_replace 155 | 156 | - name: Configure agent as an environment resource 157 | command: "{{ (agent_cmd_args + resource_agent_cmd_args) | join(' ') }}" 158 | args: 159 | chdir: "{{ az_devops_agent_folder }}" 160 | creates: "{{ az_devops_agent_folder }}/.agent" 161 | become: true 162 | become_user: "{{ az_devops_agent_user }}" 163 | when: 164 | - az_devops_agent_role == 'resource' 165 | - (not service_is_installed) or reconfigure_or_replace 166 | 167 | - name: Set provided user defined capabilities 168 | ini_file: 169 | path: "{{ az_devops_agent_folder }}/.env" 170 | section: null 171 | option: "{{ item.key }}" 172 | value: "{{ item.value }}" 173 | no_extra_spaces: yes 174 | owner: "{{ az_devops_agent_user }}" 175 | group: "{{ az_devops_agent_group }}" 176 | loop: "{{ az_devops_agent_user_capabilities | default({}) | dict2items }}" 177 | become: true 178 | 179 | - name: Install agent service 180 | command: ./svc.sh install {{ az_devops_agent_user }} 181 | become: true 182 | become_user: "{{ az_devops_agent_user }}" 183 | args: 184 | chdir: "{{ az_devops_agent_folder }}" 185 | when: 186 | - (not service_is_installed) or reconfigure_or_replace 187 | 188 | - name: Start agent service 189 | command: ./svc.sh start 190 | become: true 191 | become_user: "{{ az_devops_agent_user }}" 192 | args: 193 | chdir: "{{ az_devops_agent_folder }}" 194 | when: 195 | - (not service_is_running) or reconfigure_or_replace 196 | -------------------------------------------------------------------------------- /tasks/Linux.yml: -------------------------------------------------------------------------------- 1 | - name: Add an agent user 2 | user: 3 | name: "{{ az_devops_agent_user }}" 4 | group: "{{ az_devops_agent_group }}" 5 | uid: "{{ az_devops_agent_uid|default(omit) }}" 6 | comment: "Azure DevOps Agent" 7 | shell: /bin/bash 8 | become: true 9 | 10 | - name: Create directories 11 | file: 12 | state: directory 13 | path: "{{ item }}" 14 | owner: "{{ az_devops_agent_user }}" 15 | group: "{{ az_devops_agent_group }}" 16 | mode: 0755 17 | loop: 18 | - "{{ az_devops_agent_folder }}" 19 | - "{{ az_devops_work_folder }}" 20 | become: true 21 | 22 | - name: Install dependencies 23 | package: 24 | name: "{{ az_devops_agent_dependencies }}" 25 | state: present 26 | become: true 27 | 28 | - name: Check if svc.sh exists 29 | stat: 30 | path: "{{ '/'.join((az_devops_agent_folder, 'svc.sh')) }}" 31 | register: svc_sh 32 | become: true 33 | changed_when: false 34 | check_mode: no 35 | 36 | - name: Check service status 37 | command: ./svc.sh status 38 | become: true 39 | args: 40 | chdir: "{{ az_devops_agent_folder }}" 41 | register: svc_status 42 | changed_when: false 43 | check_mode: no 44 | when: svc_sh.stat.exists 45 | 46 | - name: Check if bin/Agent.Listener exists 47 | stat: 48 | path: "{{ '/'.join((az_devops_agent_folder, 'bin/Agent.Listener')) }}" 49 | register: bin_agent_listener 50 | become: true 51 | changed_when: false 52 | check_mode: no 53 | 54 | - name: Check agent version 55 | command: ./bin/Agent.Listener --version 56 | become: true 57 | args: 58 | chdir: "{{ az_devops_agent_folder }}" 59 | register: agent_listener_version 60 | changed_when: false 61 | check_mode: no 62 | when: bin_agent_listener.stat.exists 63 | 64 | - name: Set agent config facts 65 | set_fact: 66 | agent_cmd_args: 67 | - "./config.sh" 68 | - "--unattended" 69 | - "--acceptteeeula" 70 | - "--url '{{ az_devops_server_url }}'" 71 | - "--work '{{ az_devops_work_folder }}'" 72 | - "--auth PAT" 73 | - "--token '{{ az_devops_accesstoken }}'" 74 | - "--runasservice" 75 | build_agent_cmd_args: 76 | - "--pool '{{ az_devops_agent_pool_name }}'" 77 | - "--agent '{{ az_devops_agent_name }}'" 78 | deployment_agent_cmd_args: 79 | - "--deploymentgroup" 80 | - "--deploymentgroupname '{{ az_devops_deployment_group_name }}'" 81 | - "--projectname '{{ az_devops_project_name }}'" 82 | resource_agent_cmd_args: 83 | - "--environment" 84 | - "--environmentname '{{ az_devops_environment_name }}'" 85 | - "--agent '{{ az_devops_agent_name }}'" 86 | - "--projectname '{{ az_devops_project_name }}'" 87 | service_is_installed: "{{ svc_status.stdout is defined and svc_status.stdout is not regex('not installed') }}" 88 | service_is_running: "{{ svc_status.stdout is defined and svc_status.stdout is regex('active \\(running\\)') }}" 89 | is_requested_version: "{{ bin_agent_listener.stat.exists and agent_listener_version.stdout is defined and agent_listener_version.stdout == az_devops_agent_version }}" 90 | 91 | - name: Determine if the agent should be reconfigured or replaced 92 | set_fact: 93 | reconfigure_or_replace: "{{ az_devops_reconfigure_agent or az_devops_agent_replace_existing or not is_requested_version }}" 94 | 95 | - name: Add deployment group tags 96 | set_fact: 97 | deployment_agent_cmd_args: "{{ deployment_agent_cmd_args }} + 98 | ['--addDeploymentGroupTags', '--deploymentGroupTags \\'{{ az_devops_deployment_group_tags }}\\'']" 99 | when: 100 | - az_devops_deployment_group_tags is defined 101 | 102 | - name: Set proxy 103 | set_fact: 104 | agent_cmd_args: "{{ agent_cmd_args }} + ['--proxyurl \\'{{ az_devops_proxy_url }}\\'', '--proxyusername \\'{{ az_devops_proxy_username }}\\'', '--proxypassword \\'{{ az_devops_proxy_password }}\\'']" 105 | when: 106 | - az_devops_proxy_url is defined 107 | 108 | - name: Download and unarchive 109 | unarchive: 110 | src: "{{ az_devops_agent_package_url }}" 111 | dest: "{{ az_devops_agent_folder }}" 112 | remote_src: yes 113 | owner: "{{ az_devops_agent_user }}" 114 | group: "{{ az_devops_agent_group }}" 115 | become: true 116 | when: 117 | - (not service_is_installed) or reconfigure_or_replace 118 | 119 | - name: Uninstall agent service 120 | command: ./svc.sh uninstall 121 | become: true 122 | args: 123 | chdir: "{{ az_devops_agent_folder }}" 124 | removes: "{{ az_devops_agent_folder }}/runsvc.sh" 125 | when: 126 | - service_is_installed 127 | - reconfigure_or_replace 128 | 129 | - name: Unconfigure agent 130 | command: "./config.sh remove --auth PAT --token {{ az_devops_accesstoken }}" 131 | args: 132 | chdir: "{{ az_devops_agent_folder }}" 133 | removes: "{{ az_devops_agent_folder }}/.agent" 134 | become: true 135 | become_user: "{{ az_devops_agent_user }}" 136 | when: 137 | - service_is_installed 138 | - reconfigure_or_replace 139 | 140 | - name: Add '--replace' configuration argument 141 | set_fact: 142 | build_agent_cmd_args: "{{ build_agent_cmd_args }} + ['--replace']" 143 | deployment_agent_cmd_args: "{{ build_agent_cmd_args }} + ['--replace']" 144 | resource_agent_cmd_args: "{{ resource_agent_cmd_args }} + ['--replace']" 145 | when: 146 | - az_devops_agent_replace_existing 147 | 148 | - name: Configure agent as a build server 149 | command: "{{ (agent_cmd_args + build_agent_cmd_args) | join(' ') }}" 150 | args: 151 | chdir: "{{ az_devops_agent_folder }}" 152 | creates: "{{ az_devops_agent_folder }}/.agent" 153 | become: true 154 | become_user: "{{ az_devops_agent_user }}" 155 | when: 156 | - az_devops_agent_role == 'build' 157 | - (not service_is_installed) or reconfigure_or_replace 158 | 159 | - name: Configure agent as a deployment server 160 | command: "{{ (agent_cmd_args + deployment_agent_cmd_args) | join(' ') }}" 161 | args: 162 | chdir: "{{ az_devops_agent_folder }}" 163 | creates: "{{ az_devops_agent_folder }}/.agent" 164 | become: true 165 | become_user: "{{ az_devops_agent_user }}" 166 | when: 167 | - az_devops_agent_role == 'deployment' 168 | - (not service_is_installed) or reconfigure_or_replace 169 | 170 | - name: Configure agent as an environment resource 171 | command: "{{ (agent_cmd_args + resource_agent_cmd_args) | join(' ') }}" 172 | args: 173 | chdir: "{{ az_devops_agent_folder }}" 174 | creates: "{{ az_devops_agent_folder }}/.agent" 175 | become: true 176 | become_user: "{{ az_devops_agent_user }}" 177 | when: 178 | - az_devops_agent_role == 'resource' 179 | - (not service_is_installed) or reconfigure_or_replace 180 | 181 | - name: Set provided user defined capabilities 182 | community.general.ini_file: 183 | path: "{{ az_devops_agent_folder }}/.env" 184 | section: null 185 | option: "{{ item.key }}" 186 | value: "{{ item.value }}" 187 | no_extra_spaces: yes 188 | owner: "{{ az_devops_agent_user }}" 189 | group: "{{ az_devops_agent_group }}" 190 | loop: "{{ az_devops_agent_user_capabilities | default({}) | dict2items }}" 191 | become: true 192 | 193 | - name: Install agent service 194 | command: ./svc.sh install {{ az_devops_agent_user }} 195 | become: true 196 | args: 197 | chdir: "{{ az_devops_agent_folder }}" 198 | when: 199 | - (not service_is_installed) or reconfigure_or_replace 200 | 201 | - name: Start agent service 202 | command: ./svc.sh start 203 | become: true 204 | args: 205 | chdir: "{{ az_devops_agent_folder }}" 206 | when: 207 | - (not service_is_running) or reconfigure_or_replace 208 | -------------------------------------------------------------------------------- /tasks/Windows.yml: -------------------------------------------------------------------------------- 1 | - name: Add an agent user 2 | win_user: 3 | name: "{{ az_devops_agent_user }}" 4 | password: "{{ az_devops_agent_password }}" 5 | state: present 6 | password_never_expires: true 7 | become: yes 8 | when: 9 | - az_devops_agent_create_local_user 10 | 11 | - name: Ensure chocolatey is present 12 | win_chocolatey: 13 | name: chocolatey 14 | state: present 15 | 16 | # The full list of parameters is documented here: 17 | # https://github.com/flcdrg/au-packages/blob/master/azure-pipelines-agent/README.md 18 | 19 | - name: Set basic agent package parameters 20 | set_fact: 21 | common_install_options: 22 | - "/Directory:{{ az_devops_agent_folder }}" 23 | - "/Url:{{ az_devops_server_url }}" 24 | - "/Token:{{ az_devops_accesstoken }}" 25 | - "/Auth:PAT" 26 | - "/Pool:{{ az_devops_agent_pool_name }}" 27 | - "/Work:{{ az_devops_work_folder }}" 28 | - "/LogonAccount:{{ az_devops_agent_user }}" 29 | - "/LogonPassword:{{ az_devops_agent_password }}" 30 | build_agent_install_options: 31 | - "/Pool:{{ az_devops_agent_pool_name }}" 32 | - "/AgentName:{{ az_devops_agent_name }}" 33 | deployment_install_options: 34 | - "/DeploymentGroup" 35 | - "/DeploymentGroupName:{{ az_devops_deployment_group_name }}" 36 | - "/ProjectName:{{ az_devops_project_name }}" 37 | resource_agent_install_options: 38 | - "/Environment" 39 | - "/EnvironmentName:{{ az_devops_environment_name }}" 40 | - "/AgentName:{{ az_devops_agent_name }}" 41 | - "/ProjectName:{{ az_devops_project_name }}" 42 | 43 | - name: Add '/Replace' configuration argument 44 | set_fact: 45 | common_install_options: "{{ common_install_options }} + ['/Replace']" 46 | when: 47 | - az_devops_agent_replace_existing 48 | 49 | - name: Add deployment group tags 50 | set_fact: 51 | deployment_install_options: "{{ deployment_install_options }} + ['/DeploymentGroupTags:{{ az_devops_deployment_group_tags }}']" 52 | when: 53 | - az_devops_deployment_group_tags is defined 54 | 55 | - name: Add az_devops_proxy_url 56 | set_fact: 57 | common_install_options: "{{ common_install_options }} + ['/ProxyUrl:{{ az_devops_proxy_url }}']" 58 | when: 59 | - az_devops_proxy_url is defined and az_devops_proxy_url 60 | 61 | - name: Add az_devops_proxy_username 62 | set_fact: 63 | common_install_options: "{{ common_install_options }} + ['/ProxyUserName:{{ az_devops_proxy_username }}']" 64 | when: 65 | - az_devops_proxy_username is defined and az_devops_proxy_username 66 | 67 | - name: Add az_devops_proxy_password 68 | set_fact: 69 | common_install_options: "{{ common_install_options }} + ['/ProxyPassword:{{ az_devops_proxy_password }}']" 70 | when: 71 | - az_devops_proxy_password is defined and az_devops_proxy_password 72 | 73 | - name: Configure agent as a build server 74 | set_fact: 75 | az_devops_agent_package_params: "{{ common_install_options }} + {{ build_agent_install_options }}" 76 | when: 77 | - az_devops_agent_role == 'build' 78 | 79 | - name: Configure agent as a deployment server 80 | set_fact: 81 | az_devops_agent_package_params: "{{ common_install_options }} + {{ deployment_install_options }}" 82 | when: 83 | - az_devops_agent_role == 'deployment' 84 | 85 | - name: Configure agent as an environment resource 86 | set_fact: 87 | az_devops_agent_package_params: "{{ common_install_options }} + {{ resource_agent_install_options }}" 88 | when: 89 | - az_devops_agent_role == 'resource' 90 | 91 | - name: Install azure-pipelines-agent package 92 | win_chocolatey: 93 | name: azure-pipelines-agent 94 | state: present 95 | version: "{{ az_devops_agent_version }}" 96 | package_params: "{{ az_devops_agent_package_params | join(' ') }}" 97 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Read platform-specific variables 3 | include_vars: "{{ varfile }}" 4 | with_first_found: 5 | - files: 6 | - "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" 7 | - "{{ ansible_distribution }}.yml" 8 | - "{{ ansible_os_family }}.yml" 9 | - "{{ ansible_system }}.yml" 10 | skip: true 11 | loop_control: 12 | loop_var: varfile 13 | 14 | # - debug: 15 | # msg: 16 | # - "Dependency lookup variables are :" 17 | # - "ansible_distribution: {{ ansible_distribution }}" 18 | # - "ansible_distribution_major_version: {{ ansible_distribution_major_version }}" 19 | # - "ansible_os_family: {{ ansible_os_family }}" 20 | # - "ansible_system: {{ ansible_system }}" 21 | 22 | - name: Read platform-specific package list variables 23 | include_vars: "{{ varfile }}" 24 | with_first_found: 25 | - files: 26 | - "dependencies-{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" 27 | - "dependencies-{{ ansible_distribution }}.yml" 28 | - "dependencies-{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml" 29 | - "dependencies-{{ ansible_os_family }}.yml" 30 | - "dependencies-{{ ansible_system }}.yml" 31 | skip: true 32 | loop_control: 33 | loop_var: varfile 34 | 35 | - name: Read platform specific tasks 36 | include_tasks: "{{ taskfile }}" 37 | with_first_found: 38 | - "{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml" 39 | - "{{ ansible_distribution }}.yml" 40 | - "{{ ansible_os_family }}.yml" 41 | - "{{ ansible_system }}.yml" 42 | loop_control: 43 | loop_var: taskfile -------------------------------------------------------------------------------- /vars/Darwin.yml: -------------------------------------------------------------------------------- 1 | az_devops_default_agent_folder: "/Users/{{ az_devops_agent_user }}/agent/" 2 | az_devops_default_work_folder: "/Users/{{ az_devops_agent_user }}/agent/_work" 3 | az_devops_launchagent_folder: "/Users/{{ az_devops_agent_user }}/Library/LaunchAgents" 4 | az_devops_default_agent_package_url: "https://vstsagentpackage.azureedge.net/agent/{{ az_devops_agent_version }}/vsts-agent-osx-x64-{{ az_devops_agent_version }}.tar.gz" 5 | az_devops_default_agent_local_package: "/Users/{{ az_devops_agent_user }}/vsts-agent-osx-x64-{{ az_devops_agent_version }}.tar.gz" 6 | az_devops_default_agent_group: admin -------------------------------------------------------------------------------- /vars/Linux.yml: -------------------------------------------------------------------------------- 1 | az_devops_default_agent_folder: "/home/{{ az_devops_agent_user }}/agent/" 2 | az_devops_default_work_folder: "/home/{{ az_devops_agent_user }}/agent/_work" 3 | az_devops_default_agent_package_url: "https://vstsagentpackage.azureedge.net/agent/{{ az_devops_agent_version }}/vsts-agent-linux-x64-{{ az_devops_agent_version }}.tar.gz" 4 | az_devops_default_agent_group: "{{ az_devops_agent_user }}" 5 | -------------------------------------------------------------------------------- /vars/Windows.yml: -------------------------------------------------------------------------------- 1 | az_devops_default_agent_folder: "C:/a" 2 | az_devops_default_work_folder: "C:/w" 3 | az_devops_default_agent_package_url: "https://vstsagentpackage.azureedge.net/agent/{{ az_devops_agent_version }}/vsts-agent-win-x64-{{ az_devops_agent_version }}.zip" 4 | az_devops_default_agent_local_package: "C:/vsts-agent-win-x64-{{ az_devops_agent_version }}.zip" 5 | az_devops_default_agent_group: "{{ az_devops_agent_user }}" 6 | -------------------------------------------------------------------------------- /vars/dependencies-Debian-10.yml: -------------------------------------------------------------------------------- 1 | az_devops_agent_dependencies: 2 | - libcurl4 3 | - libgssapi-krb5-2 4 | - libicu63 5 | - libssl1.1 6 | -------------------------------------------------------------------------------- /vars/dependencies-Debian-9.yml: -------------------------------------------------------------------------------- 1 | az_devops_agent_dependencies: 2 | - libcurl3 3 | - libgssapi-krb5-2 4 | - libicu57 5 | - libssl1.1 6 | -------------------------------------------------------------------------------- /vars/dependencies-RedHat-7.yml: -------------------------------------------------------------------------------- 1 | az_devops_agent_dependencies: 2 | - krb5-libs 3 | - libicu 4 | - lttng-ust 5 | - openssl-libs 6 | - zlib -------------------------------------------------------------------------------- /vars/dependencies-Ubuntu-16.yml: -------------------------------------------------------------------------------- 1 | az_devops_agent_dependencies: 2 | - libcurl3 3 | - libgssapi-krb5-2 4 | - libicu55 5 | - libssl1.0.0 6 | -------------------------------------------------------------------------------- /vars/dependencies-Ubuntu-18.yml: -------------------------------------------------------------------------------- 1 | az_devops_agent_dependencies: 2 | - libcurl4 3 | - libgssapi-krb5-2 4 | - libicu60 5 | - libssl1.1 6 | -------------------------------------------------------------------------------- /vars/dependencies-Ubuntu-20.yml: -------------------------------------------------------------------------------- 1 | az_devops_agent_dependencies: 2 | - libcurl4 3 | - libgssapi-krb5-2 4 | - libicu66 5 | - libssl1.1 6 | - acl 7 | --------------------------------------------------------------------------------