Featured image of post Veeam Backup & Replication RestAPI Ansible Collection

Veeam Backup & Replication RestAPI Ansible Collection

One of the highlights of the latest Veeam announcement is the Veeam Backup & Replication 11 RestAPI. Until now a RESTful API was only available for other products from Veeam, e.g. Veeam Availablity Orchestrator. Only through Veeam Enterprise Manager could users make some RESTful API calls for Veeam Backup & Replication. The focus of the Veeam Enterprise Manager RESTful API is more user-centric - Backup, Restore, add Tenant, and so on. The new Veeam Backup & Replication 11 RestAPI is currently mainly focused on infrastructure operations - add Managed Servers, create Backup Repositories, and so on. To leverage the new RestAPI fully integrated in the existing processes I have decided to create a Veeam Backup & Replication RestAPI Ansible Collection.

A few months ago I already tried to create a Veeam Ansible module based on the PowerShell Snap-In. Basically this worked, but unfortunately, the complexity was very high with this approach.

Note:

This blog post and the Ansible Module is based on the Veeam Backup & Replication 11 Beta Code. The implementation may change until the GA of the Product.

The implementation looks pretty modern and shippes with a Swagger-UI to explore the Veeam Backup & Replication 11 RestAPI (https://:9419/static/index.html).

Veeam Backup & Replication RestAPI - Swagger-UI

Working with the Veeam RestAPI

There are two simple Get Requests in the Service-Scope of the RestAPI available that do not require authentication, which are good Requests to check the general availability of the API endpoint itself. I typically use the “getServerTime” Request to verify the connection.

1
2
3
curl --location --request GET 'https://10.0.2.16:9419/api/v1/serverTime' \
--header 'x-api-version: 1.0-rev1' \
--header 'Accept: application/json'

Veeam Backup & Replication RestAPI - Basic Request

For all other Requests (except the authentication itself) an authorization token is required. The Veeam Backup & Replication 11 RestAPI uses Bearer Token.

Veeam RestAPI Authentication

To create a new access token a simple post request with credentials in the data is required.

1
2
3
4
5
6
7
curl --location --request POST 'https://10.0.2.16:9419/api/oauth2/token' \
--header 'x-api-version: 1.0-rev1' \
--header 'Accept: application/json' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=Administrator' \
--data-urlencode 'password=<Password>'

Veeam Backup & Replication RestAPI - Authentication

With the “access_token” from the response body all further requests can be authorized.

1
2
3
4
curl --location --request GET 'https://10.0.2.16:9419/api/v1/credentials' \
--header 'x-api-version: 1.0-rev1' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <access_token>'

If you use a tool like Postman you can automatically parse the response of the authentication request to handle further authorization. Postman uses “Tests” (scripts to process the response - See documentation for more details) to add values to the current environment (collection of variables and values).

1
2
var jsonData = JSON.parse(responseBody);
postman.setEnvironmentVariable("bearerToken", jsonData.access_token);

Veeam Backup & Replication RestAPI - Postman Test

Veeam Backup & Replication RestAPI - Postman Enviroment

The first Veeam RestAPI Ansible Module

With this basic knowledge about the Veeam Backup & Replication 11 RestAPI, we are now able to create our first Python-based Ansible Module.

If you are new to Ansible development you should have a look at this Guide: Ansible module development: getting started

To make the Veeam Backup & Replication RestAPI Ansible Collection more portable I have decided to create an Ansible Collection. Collections are the new distribution format for Ansible content and can be published through Ansible Galaxy.

My first module needs some basic error handling for the RestAPI request and should return the current Server certificate.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/python

# Copyright: (c) 2020, Your Name <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = r'''
---
module: veeam_vbr_servercertificate_info

short_description: Get Current Veeam Backup Server Certificate from RestAPI.

version_added: "1.0.0"

description: Get Current Veeam Backup Server Certificate from RestAPI.

options:
    validate_certs:
        description: Validate SSL certs
        required: false
        default: false
        type: bool
    server_name:
        description: VBR Server Name or IP
        required: true
        type: str
    server_port:
        description: VBR RestAPI Sever Port
        required: false
        default: 9419
        type: str

author:
    - Markus Kraus (@vMarkusK)
'''

EXAMPLES = r'''
# Pass in a message
- name: Test Veeam RestAPI Collection
  hosts: localhost
  tasks:
  - name: Test veeam_vbr_servercertificate_info
    veeamhub.veeam_rest.veeam_vbr_servercertificate_info:
        server_name: '10.0.2.16'
    register: testout
  - name: Debug Result
    debug:
        var: testout
'''

import json
import re
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.urls import fetch_url


def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(
        server_name=dict(type='str', required=True),
        server_port=dict(type='str', default='9419'),
        validate_certs=dict(type='bool', default='False')
    )

    # seed the result dict in the object
    # we primarily care about changed and state
    # changed is if this module effectively modified the target
    # state will include any data that you want your module to pass back
    # for consumption, for example, in a subsequent task
    result = dict(
        changed=False
    )

    # the AnsibleModule object will be our abstraction working with Ansible
    # this includes instantiation, a couple of common attr would be the
    # args/params passed to the execution, as well as if the module
    # supports check mode
    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=False
    )

    request_server = module.params['server_name']
    request_port = module.params['server_port']
    headers = {
        'accept': 'application/json',
        'x-api-version': '1.0-rev1',
        'Authorization': 'true'
    }

    request_url = 'https://' + request_server + ':' + request_port + '/api/v1/serverCertificate'

    method = "Get"
    req, info = fetch_url(module, request_url, headers=headers, method=method)

    if info['status'] != 200:
        module.fail_json(msg="Fail: %s" % ("Status: " + str(info['status']) + ", Message: " + str(info['msg'])))

    try:
        result['servercertificate'] = json.loads(req.read())
    except AttributeError:
        module.fail_json(msg='Parsing Response Failed', **result)

    module.exit_json(**result)


def main():
    run_module()


if __name__ == '__main__':
    main()

The playbook for this module looks pretty simple, only the IP / FQDN of the Veeam Backup & Replication Server is required, the “validate_certs” parameter is optional and the default is set to “false”.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
- name: Test Veeam RestAPI Collection
  hosts: localhost
  tasks:
  - name: Test veeam_vbr_servercertificate_info
    veeamhub.veeam_rest.veeam_vbr_servercertificate_info:
        server_name: '10.0.2.16'
    register: testout
  - name: Debug Result
    debug:
        var: testout

Veeam RestAPI Ansible Module - Get Server Certificate

Veeam RestAPI Ansible Module with Authentication

The required Python code gets a bit more complex when it comes to authentication. We need way more inputs and the response of one RestAPI Request needs to be handed over to another one.

The following Veeam Backup & Replication RestAPI Ansible Collection should return all configured Backup Repositories.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/python

# Copyright: (c) 2020, Your Name <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = r'''
---
module: veeam_vbr_repositories_info

short_description: Get Veeam Backup & Replication Repositories.

version_added: "1.0.0"

description: Get Veeam Backup & Replication Repositories.

options:
    validate_certs:
        description: Validate SSL certs.
        required: false
        default: false
        type: bool
    server_name:
        description: VBR Server Name or IP
        required: true
        type: str
    server_port:
        description: VBR RestAPI Sever Port
        required: false
        default: 9419
        type: str
    server_username:
        description: VBR Server Username
        required: true
        type: str
    server_password:
        description: VBR Server password
        required: true
        type: str

author:
    - Markus Kraus (@vMarkusK)
'''

EXAMPLES = r'''
# Pass in a message
- name: Test Veeam RestAPI Collection
  hosts: localhost
  tasks:
  - name: Test veeam_vbr_repositories_info
    veeamhub.veeam_rest.veeam_vbr_repositories_info:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: '<Password>'
    register: testout
  - name: Debug Result
    debug:
        var: testout
'''

import json
import re
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.urls import fetch_url


def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(
        server_name=dict(type='str', required=True),
        server_username=dict(type='str', required=True),
        server_password=dict(type='str', required=True, no_log=True),
        server_port=dict(type='str', default='9419'),
        validate_certs=dict(type='bool', default='false')
    )

    # seed the result dict in the object
    # we primarily care about changed and state
    # changed is if this module effectively modified the target
    # state will include any data that you want your module to pass back
    # for consumption, for example, in a subsequent task
    result = dict(
        changed=False
    )

    # the AnsibleModule object will be our abstraction working with Ansible
    # this includes instantiation, a couple of common attr would be the
    # args/params passed to the execution, as well as if the module
    # supports check mode
    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=False
    )

    # Authenticate
    request_server = module.params['server_name']
    request_port = module.params['server_port']
    request_username = module.params['server_username']
    request_password = module.params['server_password']
    payload = 'grant_type=password&username=' + request_username + '&password=' + request_password
    headers = {
        'accept': 'application/json',
        'x-api-version': '1.0-rev1',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'true'
    }

    request_url = 'https://' + request_server + ':' + request_port + '/api/oauth2/token'

    method = "Post"
    req, info = fetch_url(module, request_url, headers=headers, method=method, data=payload)

    if info['status'] != 200:
        module.fail_json(msg="Fail: %s" % ("Status: " + str(info['status']) + ", Message: " + str(info['msg'])))

    try:
        resp = json.loads(req.read())
    except AttributeError:
        module.fail_json(msg='Parsing Response Failed', **result)

    # Payload
    headers = {
        'x-api-version': '1.0-rev1',
        'Authorization': 'Bearer ' + resp['access_token']
    }
    request_url = 'https://' + request_server + ':' + request_port + '/api/v1/backupInfrastructure/repositories'

    method = "Get"
    req, info = fetch_url(module, request_url, headers=headers, method=method)

    if info['status'] != 200:
        module.fail_json(msg="Fail: %s" % ("Status: " + str(info['status']) + ", Message: " + str(info['msg'])))

    try:
        result['infrastructure_repositories'] = json.loads(req.read())
    except AttributeError:
        module.fail_json(msg='Parsing Response Failed', **result)

    module.exit_json(**result)


def main():
    run_module()


if __name__ == '__main__':
    main()

Because of the additional inputs for the authentication, the Playbook for the veeam_vbr_repositories_info module looks also a bit more complex.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
- name: Test Veeam RestAPI Collection
  hosts: localhost
  tasks:
  - name: Test veeam_vbr_repositories_info
    veeamhub.veeam_rest.veeam_vbr_repositories_info:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: '<Password>'
    register: testout
  - name: Debug Result
    debug:
        var: testout

Veeam RestAPI Ansible Module - Get Repositories

Veeam RestAPI Ansible Module with Changes

The next complexity level is adding or changing something. The first object you typically need to add when you create a new Veeam Backup & Replication infrastructure are Credentials (VMware vCenter, Managed Server, and so on). So, the first Veeam Backup & Replication RestAPI Ansible Collection with changes is for credential management.

The “veeam_vbr_credentials” module should be able to delete and add credentials. Changing existing Credentials is on the roadmap.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#!/usr/bin/python

# Copyright: (c) 2020, Your Name <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = r'''
---
module: veeam_vbr_credentials

short_description: Add and Remove Veeam Backup & Replication Credentials.

version_added: "1.0.0"

description: Add and Remove Veeam Backup & Replication Credentials.

options:
    validate_certs:
        description: Validate SSL certs.
        required: false
        default: false
        type: bool
    state:
        description:
        - Indicate desired state.
        default: present
        type: str
        choices: ['present', 'absent']
    server_name:
        description: VBR Server Name or IP
        required: true
        type: str
    server_port:
        description: VBR RestAPI Sever Port
        required: false
        default: 9419
        type: str
    server_username:
        description: VBR Server Username
        required: true
        type: str
    server_password:
        description: VBR Server password
        required: true
        type: str
    id:
        description: VBR Server credential ID
        required: false
        type: str
    username:
        description: VBR Server credential username
        required: false
        type: str
    password:
        description: VBR Server credential password
        required: false
        type: str
    description:
        description: VBR Server credential description
        required: false
        type: str
    type:
        description:
        - Set to C(windows) to create new windows credentials.
        - Set to C(linux) to create new liniux credentials.
        - Set to C(standard) to create new standard credentials.
        type: str
        choices: [ windows, linux, standard ]
        default: standard

author:
    - Markus Kraus (@vMarkusK)
'''

EXAMPLES = r'''
# Pass in a message
- name: Test Veeam RestAPI Collection
  hosts: localhost
  tasks:
  - name: Test veeam_vbr_credentials Create
    veeamhub.veeam_rest.veeam_vbr_credentials:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: 'Anfang!!'
        type: 'linux'
        username: 'root'
        password: '<Password>'
        description: 'Created by Ansible RestAPI Module'
    register: create_cred
  - name: Debug Result
    debug:
        var: create_cred
  - name: Test veeam_vbr_credentials Delete
    veeamhub.veeam_rest.veeam_vbr_credentials:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: 'Anfang!!'
        id: "{{ create_cred.msg.id }}"
        state: absent
    register: delete_cred
  - name: Debug Result
    debug:
        var: delete_cred
'''

import json
import re
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.urls import fetch_url


def run_module():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(
        server_name=dict(type='str', required=True),
        server_username=dict(type='str', required=True),
        server_password=dict(type='str', required=True, no_log=True),
        server_port=dict(type='str', default='9419'),
        state=dict(type="str", choices=("absent", "present"), default="present"),
        id=dict(type='str', required=False),
        username=dict(type='str', required=False),
        password=dict(type='str', required=False, no_log=True),
        type=dict(type='str', choices=("windows", "linux", "standard"), default='standard'),
        description=dict(type='str', required=False),
        validate_certs=dict(type='bool', default='false')
    )

    required_if_args = [
        ["state", "present", ["username", "password"]],
        ["state", "absent", ["id"]]
    ]

    required_together_args = [
        ["password", "username"]
    ]

    # seed the result dict in the object
    # we primarily care about changed and state
    # changed is if this module effectively modified the target
    # state will include any data that you want your module to pass back
    # for consumption, for example, in a subsequent task
    result = dict(
        changed=False
    )

    # the AnsibleModule object will be our abstraction working with Ansible
    # this includes instantiation, a couple of common attr would be the
    # args/params passed to the execution, as well as if the module
    # supports check mode
    module = AnsibleModule(
        argument_spec=module_args,
        required_if=required_if_args,
        required_together=required_together_args,
        supports_check_mode=False
    )

    # General
    state = module.params['state']
    request_server = module.params['server_name']
    request_port = module.params['server_port']

    # Authenticate
    request_username = module.params['server_username']
    request_password = module.params['server_password']
    payload = 'grant_type=password&username=' + request_username + '&password=' + request_password
    headers = {
        'accept': 'application/json',
        'x-api-version': '1.0-rev1',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'true'
    }

    request_url = 'https://' + request_server + ':' + request_port + '/api/oauth2/token'

    method = "Post"
    req, info = fetch_url(module, request_url, headers=headers, method=method, data=payload)

    if info['status'] != 200:
        module.fail_json(msg="Fail: %s" % ("Status: " + str(info['status']) + ", Message: " + str(info['msg'])))

    try:
        resp = json.loads(req.read())
    except AttributeError:
        module.fail_json(msg='Parsing Response Failed', **result)

    # Payload
    if state == 'present':
        username = module.params['username']
        password = module.params['password']
        credtype = module.params['type']
        description = module.params['description']

        body = {
            'type': credtype,
            'username': username,
            'password': password,
            'description': description
        }
        bodyjson = json.dumps(body)
        headers = {
            'x-api-version': '1.0-rev1',
            'Authorization': 'Bearer ' + resp['access_token'],
            'Content-Type': 'application/json'
        }
        request_url = 'https://' + request_server + ':' + request_port + '/api/v1/credentials'

        method = "Post"
        req, info = fetch_url(module, request_url, headers=headers, method=method, data=bodyjson)

        if info['status'] != 200:
            module.fail_json(msg="Fail: %s" % ("Status: " + str(info['status']) + ", Message: " + str(info['msg'])))

        try:
            result['msg'] = json.loads(req.read())
            result['changed'] = True
        except AttributeError:
            module.fail_json(msg='Parsing Response Failed', **result)

    if state == 'absent':
        credid = module.params['id']

        headers = {
            'x-api-version': '1.0-rev1',
            'Authorization': 'Bearer ' + resp['access_token']
        }
        request_url = 'https://' + request_server + ':' + request_port + '/api/v1/credentials/' + credid

        method = "get"
        req, info = fetch_url(module, request_url, headers=headers, method=method)

        if info['status'] == 200:
            method = "Delete"
            req, info = fetch_url(module, request_url, headers=headers, method=method)

            if info['status'] != 200:
                module.fail_json(msg="Fail: %s" % ("Status: " + str(info['status']) + ", Message: " + str(info['msg'])))

            try:
                result['changed'] = True
            except AttributeError:
                module.fail_json(msg='Parsing Response Failed', **result)

    module.exit_json(**result)


def main():
    run_module()


if __name__ == '__main__':
    main()

The playbook for the veeam_vbr_credentials module requires different parameters, depending on the requested State (“absent” or “present”).

  • Present: Creates new Credentials and requires “username”, “password” and “type”
  • Absent: Deletes existing Credentials and requires “id”
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- name: Test Veeam RestAPI Collection
  hosts: localhost
  tasks:
  - name: Test veeam_vbr_credentials Create
    veeamhub.veeam_rest.veeam_vbr_credentials:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: '<Password>'
        type: 'Linux'
        username: 'root'
        password: '<Password>'
        description: 'Created by Ansible RestAPI Module'
    register: create_cred
  - name: Debug Result
    debug:
        var: create_cred
  - name: Test veeam_vbr_credentials Delete
    veeamhub.veeam_rest.veeam_vbr_credentials:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: '<Password>'
        id: "{{ create_cred.msg.id }}"
        state: absent
    register: delete_cred
  - name: Debug Result
    debug:
        var: delete_cred
        

Veeam RestAPI Ansible Module - Create and Delete Credentials

Ansible Module Testing

One of the simplest code validation for Ansible Modules are Sanity Tests. Sanity tests are made up of scripts and tools used to perform static code analysis. The primary purpose of these tests is to enforce Ansible coding standards and requirements.

Veeam RestAPI  Ansible Collection - Module Testing

GitHub Action for Ansible Module Testing

With GitHub Actions, you can create a simple CI to verify your code on each commit or pull request (in my case the Sanity tests). My use case for GitHub Actions is just a small part of the capabilities this CI/CD pipeline offers.

Github Action - Ansible-Test

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# README FIRST
# 1. replace "veeamhub/veeam_rest" with the correct name, ie "community/zabbix"
# 2. If you don't have unit tests remove that section
# 3. If your collection depends on other collections ensure they are installed, see "Install collection dependencies"
# If you need help please ask in #ansible-devel on Freenode IRC

name: BasicLint
on:
  # Run CI against all pushes (direct commits, also merged PRs), Pull Requests
  push:
  pull_request:
  # Uncomment the following two lines to run CI once per day (at 06:00 UTC)
  # schedule:
  #   - cron: '0 6 * * *'

jobs:

###
# Sanity tests (REQUIRED)
#
# https://docs.ansible.com/ansible/latest/dev_guide/testing_sanity.html

  sanity:
    name: Sanity (Ⓐ${{ matrix.ansible }})
    strategy:
      matrix:
        ansible:
          # It's important that Sanity is tested against all stable-X.Y branches
          # Testing against `devel` may fail as new tests are added.
          # - stable-2.9 # Only if your collection supports Ansible 2.9
          - stable-2.10
          - devel
    runs-on: ubuntu-latest
    steps:

      # ansible-test requires the collection to be in a directory in the form
      # .../ansible_collections/veeamhub/veeam_rest/

      - name: Check out code
        uses: actions/checkout@v2
        with:
          path: ansible_collections/veeamhub/veeam_rest

      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          # it is just required to run that once as "ansible-test sanity" in the docker image
          # will run on all python versions it supports.
          python-version: 3.8

      # Install the head of the given branch (devel, stable-2.10)
      - name: Install ansible-base (${{ matrix.ansible }})
        run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check

      # run ansible-test sanity inside of Docker.
      # The docker container has all the pinned dependencies that are required
      # and all python versions ansible supports.
      - name: Run sanity tests
        run: ansible-test sanity --docker -v --color
        working-directory: ./ansible_collections/veeamhub/veeam_rest

With the use of a basic CI pipeline, you are able to guarantee a baseline of the code quality for each Pull request.

GitHub CI/CD

Veeam RestAPI Postman Collection

I have published the current version of my Postman Collection that handles the authentication via script as a GitHub Gist: REST API service for Veeam backup & Replication Postman Collection

REST API service for Veeam backup & Replication Postman Collection

Feel free reach out for a newer version as soon as Veeam Backup & Replication 11 is GA.

Veeam RestAPI Ansible Collection

The Veeam Backup & Replication RestAPI Ansible Module is publicly available as a GitHub Repository. All contributions and feedback are welcome.

As soon as the Modules and the Collection reaches a valuable and properly validated level I will publish on Ansible Galaxy.

The full documentation, including the parameters, of the individual module is included in the python file. The inline documentation can be displayed by using: ansible-doc veeam_vbr_credentials_info -M ./plugins/modules/

veeam_vbr_servercertificate_info

Get Current Veeam Backup Server Certificate from RestAPI.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
- name: Test Veeam RestAPI Collection
  hosts: localhost
  gather_facts: false
  tasks:
  - name: Test veeam_vbr_servercertificate_info
    veeamhub.veeam_rest.veeam_vbr_servercertificate_info:
        server_name: '10.0.2.16'
    register: testout
  - name: Debug Result
    debug:
        var: testout

veeam_vbr_credentials_info

Get Veeam Backup & Replication Credentials.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
- name: Test Veeam RestAPI Collection
  hosts: localhost
  tasks:
  - name: Test veeam_vbr_credentials_info
    veeamhub.veeam_rest.veeam_vbr_credentials_info:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: '<Password>'
    register: testout
  - name: Debug Result
    debug:
        var: testout

veeam_vbr_credentials

Add and Remove Veeam Backup & Replication Credentials.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
- name: Test Veeam RestAPI Collection
  hosts: localhost
  gather_facts: false
  tasks:
  - name: Test veeam_vbr_credentials Create
    veeamhub.veeam_rest.veeam_vbr_credentials:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: '<Password>'
        type: 'Linux'
        username: 'root'
        password: '<Password>'
        description: 'Created by Ansible RestAPI Module'
    register: create_cred
  - name: Debug Result
    debug:
        var: create_cred
  - name: Test veeam_vbr_credentials Delete
    veeamhub.veeam_rest.veeam_vbr_credentials:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: '<Password>'
        id: "{{ create_cred.msg.id }}"
        state: absent
    register: delete_cred
  - name: Debug Result
    debug:
        var: delete_cred
        

veeam_vbr_repositories_info

Get Veeam Backup & Replication Repositories.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
- name: Test Veeam RestAPI Collection
  hosts: localhost
  tasks:
  - name: Test veeam_vbr_repositories_info
    veeamhub.veeam_rest.veeam_vbr_repositories_info:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: '<Password>'
    register: testout
  - name: Debug Result
    debug:
        var: testout

veeam_vbr_managedservers_info

Get Veeam Backup & Replication Managed Servers.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
- name: Test Veeam RestAPI Collection
  hosts: localhost
  tasks:
  - name: Test veeam_vbr_managedservers_info
    veeamhub.veeam_rest.veeam_vbr_managedservers_info:
        server_name: '10.0.2.16'
        server_username: 'Administrator'
        server_password: '<Password>'
    register: testout
  - name: Debug Result
    debug:
        var: testout
Built with Hugo
Theme Stack designed by Jimmy