Added RETURN doc string for all modules and few minor enhancements.

This commit is contained in:
Siva Popuri 2015-10-21 12:36:51 -05:00 committed by Matt Clay
parent e6fe4b10f5
commit 34ba9fa4f8
9 changed files with 603 additions and 61 deletions

View file

@ -98,6 +98,41 @@ EXAMPLES = '''
debug: var=policy
'''
RETURN = '''
changed:
description: A flag indicating if any change was made or not
returned: success
type: boolean
sample: True
policy:
description: The anti affinity policy information
returned: success
type: dict
sample:
{
"id":"1a28dd0988984d87b9cd61fa8da15424",
"name":"test_aa_policy",
"location":"UC1",
"links":[
{
"rel":"self",
"href":"/v2/antiAffinityPolicies/wfad/1a28dd0988984d87b9cd61fa8da15424",
"verbs":[
"GET",
"DELETE",
"PUT"
]
},
{
"rel":"location",
"href":"/v2/datacenters/wfad/UC1",
"id":"uc1",
"name":"UC1 - US West (Santa Clara)"
}
]
}
'''
__version__ = '${version}'
from distutils.version import LooseVersion

View file

@ -130,6 +130,52 @@ EXAMPLES = '''
debug: var=policy
'''
RETURN = '''
changed:
description: A flag indicating if any change was made or not
returned: success
type: boolean
sample: True
policy:
description: The alert policy information
returned: success
type: dict
sample:
{
"actions": [
{
"action": "email",
"settings": {
"recipients": [
"user1@domain.com",
"user1@domain.com"
]
}
}
],
"id": "ba54ac54a60d4a4f1ed6d48c1ce240a7",
"links": [
{
"href": "/v2/alertPolicies/alias/ba54ac54a60d4a4fb1d6d48c1ce240a7",
"rel": "self",
"verbs": [
"GET",
"DELETE",
"PUT"
]
}
],
"name": "test_alert",
"triggers": [
{
"duration": "00:05:00",
"metric": "disk",
"threshold": 80.0
}
]
}
'''
__version__ = '${version}'
from distutils.version import LooseVersion

View file

@ -73,12 +73,29 @@ EXAMPLES = '''
- name: Deploy package
clc_blueprint_package:
server_ids:
- UC1WFSDANS01
- UC1WFSDANS02
- UC1TEST-SERVER1
- UC1TEST-SERVER2
package_id: 77abb844-579d-478d-3955-c69ab4a7ba1a
package_params: {}
'''
RETURN = '''
changed:
description: A flag indicating if any change was made or not
returned: success
type: boolean
sample: True
server_ids:
description: The list of server ids that are changed
returned: success
type: list
sample:
[
"UC1TEST-SERVER1",
"UC1TEST-SERVER2"
]
'''
__version__ = '${version}'
from distutils.version import LooseVersion
@ -203,7 +220,7 @@ class ClcBlueprintPackage:
parameters=package_params)
except CLCException as ex:
self.module.fail_json(msg='Failed to install package : {0} to server {1}. {2}'.format(
package_id, server.id, ex.response_text
package_id, server.id, ex.message
))
return result

View file

@ -128,6 +128,52 @@ EXAMPLES = '''
firewall_policy_id: 'c62105233d7a4231bd2e91b9c791e43e1'
'''
RETURN = '''
changed:
description: A flag indicating if any change was made or not
returned: success
type: boolean
sample: True
firewall_policy_id
description: The fire wall policy id
returned: success
type: string
sample: fc36f1bfd47242e488a9c44346438c05
firewall_policy:
description: The fire wall policy information
returned: success
type: dict
sample:
{
"destination":[
"10.1.1.0/24",
"10.2.2.0/24"
],
"destinationAccount":"wfad",
"enabled":true,
"id":"fc36f1bfd47242e488a9c44346438c05",
"links":[
{
"href":"http://api.ctl.io/v2-experimental/firewallPolicies/wfad/uc1/fc36f1bfd47242e488a9c44346438c05",
"rel":"self",
"verbs":[
"GET",
"PUT",
"DELETE"
]
}
],
"ports":[
"any"
],
"source":[
"10.1.1.0/24",
"10.2.2.0/24"
],
"status":"active"
}
'''
__version__ = '${version}'
import urlparse

View file

@ -61,8 +61,8 @@ requirements:
notes:
- To use this module, it is required to set the below environment variables which enables access to the
Centurylink Cloud
- CLC_V2_API_USERNAME: the account login id for the centurylink cloud
- CLC_V2_API_PASSWORD: the account passwod for the centurylink cloud
- CLC_V2_API_USERNAME, the account login id for the centurylink cloud
- CLC_V2_API_PASSWORD, the account password for the centurylink cloud
- Alternatively, the module accepts the API token and account alias. The API token can be generated using the
CLC account login and password via the HTTP api call @ https://api.ctl.io/v2/authentication/login
- CLC_V2_API_TOKEN: the API token generated from https://api.ctl.io/v2/authentication/login
@ -110,6 +110,110 @@ EXAMPLES = '''
'''
RETURN = '''
changed:
description: A flag indicating if any change was made or not
returned: success
type: boolean
sample: True
group:
description: The group information
returned: success
type: dict
sample:
{
"changeInfo":{
"createdBy":"service.wfad",
"createdDate":"2015-07-29T18:52:47Z",
"modifiedBy":"service.wfad",
"modifiedDate":"2015-07-29T18:52:47Z"
},
"customFields":[
],
"description":"test group",
"groups":[
],
"id":"bb5f12a3c6044ae4ad0a03e73ae12cd1",
"links":[
{
"href":"/v2/groups/wfad",
"rel":"createGroup",
"verbs":[
"POST"
]
},
{
"href":"/v2/servers/wfad",
"rel":"createServer",
"verbs":[
"POST"
]
},
{
"href":"/v2/groups/wfad/bb5f12a3c6044ae4ad0a03e73ae12cd1",
"rel":"self",
"verbs":[
"GET",
"PATCH",
"DELETE"
]
},
{
"href":"/v2/groups/wfad/086ac1dfe0b6411989e8d1b77c4065f0",
"id":"086ac1dfe0b6411989e8d1b77c4065f0",
"rel":"parentGroup"
},
{
"href":"/v2/groups/wfad/bb5f12a3c6044ae4ad0a03e73ae12cd1/defaults",
"rel":"defaults",
"verbs":[
"GET",
"POST"
]
},
{
"href":"/v2/groups/wfad/bb5f12a3c6044ae4ad0a03e73ae12cd1/billing",
"rel":"billing"
},
{
"href":"/v2/groups/wfad/bb5f12a3c6044ae4ad0a03e73ae12cd1/archive",
"rel":"archiveGroupAction"
},
{
"href":"/v2/groups/wfad/bb5f12a3c6044ae4ad0a03e73ae12cd1/statistics",
"rel":"statistics"
},
{
"href":"/v2/groups/wfad/bb5f12a3c6044ae4ad0a03e73ae12cd1/upcomingScheduledActivities",
"rel":"upcomingScheduledActivities"
},
{
"href":"/v2/groups/wfad/bb5f12a3c6044ae4ad0a03e73ae12cd1/horizontalAutoscalePolicy",
"rel":"horizontalAutoscalePolicyMapping",
"verbs":[
"GET",
"PUT",
"DELETE"
]
},
{
"href":"/v2/groups/wfad/bb5f12a3c6044ae4ad0a03e73ae12cd1/scheduledActivities",
"rel":"scheduledActivities",
"verbs":[
"GET",
"POST"
]
}
],
"locationId":"UC1",
"name":"test group",
"status":"active",
"type":"default"
}
'''
__version__ = '${version}'
from distutils.version import LooseVersion
@ -178,13 +282,16 @@ class ClcGroup(object):
if state == "absent":
changed, group, requests = self._ensure_group_is_absent(
group_name=group_name, parent_name=parent_name)
else:
changed, group, requests = self._ensure_group_is_present(
group_name=group_name, parent_name=parent_name, group_description=group_description)
if requests:
self._wait_for_requests_to_complete(requests)
self.module.exit_json(changed=changed, group=group_name)
else:
changed, group = self._ensure_group_is_present(
group_name=group_name, parent_name=parent_name, group_description=group_description)
try:
group = group.data
except AttributeError:
group = group_name
self.module.exit_json(changed=changed, group=group)
@staticmethod
def _define_module_argument_spec():
@ -238,14 +345,16 @@ class ClcGroup(object):
:return: changed, group
"""
changed = False
requests = []
group = []
results = []
if self._group_exists(group_name=group_name, parent_name=parent_name):
if not self.module.check_mode:
request = self._delete_group(group_name)
requests.append(request)
group.append(group_name)
result = self._delete_group(group_name)
results.append(result)
changed = True
return changed, group_name, requests
return changed, group, results
def _delete_group(self, group_name):
"""
@ -281,6 +390,7 @@ class ClcGroup(object):
parent = parent_name if parent_name is not None else self.root_group.name
description = group_description
changed = False
group = group_name
parent_exists = self._group_exists(group_name=parent, parent_name=None)
child_exists = self._group_exists(
@ -292,8 +402,8 @@ class ClcGroup(object):
changed = False
elif parent_exists and not child_exists:
if not self.module.check_mode:
self._create_group(
group=group_name,
group = self._create_group(
group=group,
parent=parent,
description=description)
changed = True
@ -303,7 +413,7 @@ class ClcGroup(object):
parent +
" does not exist")
return changed, group_name, None
return changed, group
def _create_group(self, group, parent, description):
"""
@ -319,8 +429,7 @@ class ClcGroup(object):
response = parent.Create(name=group, description=description)
except CLCException, ex:
self.module.fail_json(msg='Failed to create group :{0}. {1}'.format(
group, ex.response_text
))
group, ex.response_text))
return response
def _group_exists(self, group_name, parent_name):

View file

@ -172,6 +172,48 @@ notes:
- Users can set CLC_V2_API_URL to specify an endpoint for pointing to a different CLC environment.
'''
RETURN = '''
changed:
description: A flag indicating if any change was made or not
returned: success
type: boolean
sample: True
loadbalancer:
description: The load balancer result object from CLC
returned: success
type: dict
sample:
{
"description":"test-lb",
"id":"ab5b18cb81e94ab9925b61d1ca043fb5",
"ipAddress":"66.150.174.197",
"links":[
{
"href":"/v2/sharedLoadBalancers/wfad/wa1/ab5b18cb81e94ab9925b61d1ca043fb5",
"rel":"self",
"verbs":[
"GET",
"PUT",
"DELETE"
]
},
{
"href":"/v2/sharedLoadBalancers/wfad/wa1/ab5b18cb81e94ab9925b61d1ca043fb5/pools",
"rel":"pools",
"verbs":[
"GET",
"POST"
]
}
],
"name":"test-lb",
"pools":[
],
"status":"enabled"
}
'''
__version__ = '${version}'
from time import sleep
@ -827,8 +869,8 @@ class ClcLoadBalancer:
argument_spec = dict(
name=dict(required=True),
description=dict(default=None),
location=dict(required=True, default=None),
alias=dict(required=True, default=None),
location=dict(required=True),
alias=dict(required=True),
port=dict(choices=[80, 443]),
method=dict(choices=['leastConnection', 'roundRobin']),
persistence=dict(choices=['standard', 'sticky']),

View file

@ -27,22 +27,23 @@ description:
version_added: 1.0
options:
protocol:
descirption:
description:
- The protocol that the public IP will listen for.
default: TCP
choices: ['TCP', 'UDP', 'ICMP']
required: False
ports:
description:
- A list of ports to expose.
required: True
- A list of ports to expose. This is required when state is 'present'
required: False
default: None
server_ids:
description:
- A list of servers to create public ips on.
required: True
state:
description:
- Determine wheteher to create or delete public IPs. If present module will not create a second public ip if one
- Determine whether to create or delete public IPs. If present module will not create a second public ip if one
already exists.
default: present
choices: ['present', 'absent']
@ -60,8 +61,8 @@ requirements:
notes:
- To use this module, it is required to set the below environment variables which enables access to the
Centurylink Cloud
- CLC_V2_API_USERNAME: the account login id for the centurylink cloud
- CLC_V2_API_PASSWORD: the account passwod for the centurylink cloud
- CLC_V2_API_USERNAME, the account login id for the centurylink cloud
- CLC_V2_API_PASSWORD, the account password for the centurylink cloud
- Alternatively, the module accepts the API token and account alias. The API token can be generated using the
CLC account login and password via the HTTP api call @ https://api.ctl.io/v2/authentication/login
- CLC_V2_API_TOKEN: the API token generated from https://api.ctl.io/v2/authentication/login
@ -83,8 +84,8 @@ EXAMPLES = '''
ports:
- 80
server_ids:
- UC1ACCTSRVR01
- UC1ACCTSRVR02
- UC1TEST-SVR01
- UC1TEST-SVR02
state: present
register: clc
@ -99,8 +100,8 @@ EXAMPLES = '''
- name: Create Public IP For Servers
clc_publicip:
server_ids:
- UC1ACCTSRVR01
- UC1ACCTSRVR02
- UC1TEST-SVR01
- UC1TEST-SVR02
state: absent
register: clc
@ -108,6 +109,23 @@ EXAMPLES = '''
debug: var=clc
'''
RETURN = '''
changed:
description: A flag indicating if any change was made or not
returned: success
type: boolean
sample: True
server_ids:
description: The list of server ids that are changed
returned: success
type: list
sample:
[
"UC1TEST-SVR01",
"UC1TEST-SVR02"
]
'''
__version__ = '${version}'
from distutils.version import LooseVersion
@ -136,7 +154,6 @@ else:
class ClcPublicIp(object):
clc = clc_sdk
module = None
group_dict = {}
def __init__(self, module):
"""
@ -158,7 +175,6 @@ class ClcPublicIp(object):
def process_request(self):
"""
Process the request - Main Code Path
:param params: dictionary of module parameters
:return: Returns with either an exit_json or fail_json
"""
self._set_clc_credentials_from_env()
@ -167,21 +183,18 @@ class ClcPublicIp(object):
ports = params['ports']
protocol = params['protocol']
state = params['state']
requests = []
chagned_server_ids = []
changed = False
if state == 'present':
changed, chagned_server_ids, requests = self.ensure_public_ip_present(
changed, changed_server_ids, requests = self.ensure_public_ip_present(
server_ids=server_ids, protocol=protocol, ports=ports)
elif state == 'absent':
changed, chagned_server_ids, requests = self.ensure_public_ip_absent(
changed, changed_server_ids, requests = self.ensure_public_ip_absent(
server_ids=server_ids)
else:
return self.module.fail_json(msg="Unknown State: " + state)
self._wait_for_requests_to_complete(requests)
return self.module.exit_json(changed=changed,
server_ids=chagned_server_ids)
server_ids=changed_server_ids)
@staticmethod
def _define_module_argument_spec():
@ -192,7 +205,7 @@ class ClcPublicIp(object):
argument_spec = dict(
server_ids=dict(type='list', required=True),
protocol=dict(default='TCP', choices=['TCP', 'UDP', 'ICMP']),
ports=dict(type='list', required=True),
ports=dict(type='list'),
wait=dict(type='bool', default=True),
state=dict(default='present', choices=['present', 'absent']),
)
@ -265,6 +278,7 @@ class ClcPublicIp(object):
return changed, changed_server_ids, results
def _remove_publicip_from_server(self, server):
result = None
try:
for ip_address in server.PublicIPs().public_ips:
result = ip_address.Delete()

View file

@ -193,7 +193,7 @@ options:
- The template to use for server creation. Will search for a template if a partial string is provided.
This is required when state is 'present'
default: None
required: false
required: False
ttl:
description:
- The time to live for the server in seconds. The server will be deleted when this time expires.
@ -204,7 +204,20 @@ options:
- The type of server to create.
default: 'standard'
required: False
choices: ['standard', 'hyperscale']
choices: ['standard', 'hyperscale', 'bareMetal']
configuration_id:
description:
- Only required for bare metal servers.
Specifies the identifier for the specific configuration type of bare metal server to deploy.
default: None
required: False
os_type:
description:
- Only required for bare metal servers.
Specifies the OS to provision with the bare metal server.
default: None
required: False
choices: ['redHat6_64Bit', 'centOS6_64Bit', 'windows2012R2Standard_64Bit', 'ubuntu14_64Bit']
wait:
description:
- Whether to wait for the provisioning tasks to finish before returning.
@ -248,20 +261,203 @@ EXAMPLES = '''
- name: Stop a Server
clc_server:
server_ids: ['UC1ACCTTEST01']
server_ids: ['UC1ACCT-TEST01']
state: stopped
- name: Start a Server
clc_server:
server_ids: ['UC1ACCTTEST01']
server_ids: ['UC1ACCT-TEST01']
state: started
- name: Delete a Server
clc_server:
server_ids: ['UC1ACCTTEST01']
server_ids: ['UC1ACCT-TEST01']
state: absent
'''
RETURN = '''
changed:
description: A flag indicating if any change was made or not
returned: success
type: boolean
sample: True
server_ids:
description: The list of server ids that are created
returned: success
type: list
sample:
[
"UC1TEST-SVR01",
"UC1TEST-SVR02"
]
partially_created_server_ids:
description: The list of server ids that are partially created
returned: success
type: list
sample:
[
"UC1TEST-SVR01",
"UC1TEST-SVR02"
]
servers:
description: The list of server objects returned from CLC
returned: success
type: list
sample:
[
{
"changeInfo":{
"createdBy":"service.wfad",
"createdDate":1438196820,
"modifiedBy":"service.wfad",
"modifiedDate":1438196820
},
"description":"test-server",
"details":{
"alertPolicies":[
],
"cpu":1,
"customFields":[
],
"diskCount":3,
"disks":[
{
"id":"0:0",
"partitionPaths":[
],
"sizeGB":1
},
{
"id":"0:1",
"partitionPaths":[
],
"sizeGB":2
},
{
"id":"0:2",
"partitionPaths":[
],
"sizeGB":14
}
],
"hostName":"",
"inMaintenanceMode":false,
"ipAddresses":[
{
"internal":"10.1.1.1"
}
],
"memoryGB":1,
"memoryMB":1024,
"partitions":[
],
"powerState":"started",
"snapshots":[
],
"storageGB":17
},
"groupId":"086ac1dfe0b6411989e8d1b77c4065f0",
"id":"test-server",
"ipaddress":"10.120.45.23",
"isTemplate":false,
"links":[
{
"href":"/v2/servers/wfad/test-server",
"id":"test-server",
"rel":"self",
"verbs":[
"GET",
"PATCH",
"DELETE"
]
},
{
"href":"/v2/groups/wfad/086ac1dfe0b6411989e8d1b77c4065f0",
"id":"086ac1dfe0b6411989e8d1b77c4065f0",
"rel":"group"
},
{
"href":"/v2/accounts/wfad",
"id":"wfad",
"rel":"account"
},
{
"href":"/v2/billing/wfad/serverPricing/test-server",
"rel":"billing"
},
{
"href":"/v2/servers/wfad/test-server/publicIPAddresses",
"rel":"publicIPAddresses",
"verbs":[
"POST"
]
},
{
"href":"/v2/servers/wfad/test-server/credentials",
"rel":"credentials"
},
{
"href":"/v2/servers/wfad/test-server/statistics",
"rel":"statistics"
},
{
"href":"/v2/servers/wfad/510ec21ae82d4dc89d28479753bf736a/upcomingScheduledActivities",
"rel":"upcomingScheduledActivities"
},
{
"href":"/v2/servers/wfad/510ec21ae82d4dc89d28479753bf736a/scheduledActivities",
"rel":"scheduledActivities",
"verbs":[
"GET",
"POST"
]
},
{
"href":"/v2/servers/wfad/test-server/capabilities",
"rel":"capabilities"
},
{
"href":"/v2/servers/wfad/test-server/alertPolicies",
"rel":"alertPolicyMappings",
"verbs":[
"POST"
]
},
{
"href":"/v2/servers/wfad/test-server/antiAffinityPolicy",
"rel":"antiAffinityPolicyMapping",
"verbs":[
"PUT",
"DELETE"
]
},
{
"href":"/v2/servers/wfad/test-server/cpuAutoscalePolicy",
"rel":"cpuAutoscalePolicyMapping",
"verbs":[
"PUT",
"DELETE"
]
}
],
"locationId":"UC1",
"name":"test-server",
"os":"ubuntu14_64Bit",
"osType":"Ubuntu 14 64-bit",
"status":"active",
"storageType":"standard",
"type":"standard"
}
]
'''
__version__ = '${version}'
from time import sleep
@ -361,7 +557,7 @@ class ClcServer:
elif state == 'present':
# Changed is always set to true when provisioning new instances
if not p.get('template'):
if not p.get('template') and p.get('type') != 'bareMetal':
return self.module.fail_json(
msg='template parameter is required for new instance')
@ -406,7 +602,7 @@ class ClcServer:
choices=[
'standard',
'hyperscale']),
type=dict(default='standard', choices=['standard', 'hyperscale']),
type=dict(default='standard', choices=['standard', 'hyperscale', 'bareMetal']),
primary_dns=dict(default=None),
secondary_dns=dict(default=None),
additional_disks=dict(type='list', default=[]),
@ -440,6 +636,14 @@ class ClcServer:
'UDP',
'ICMP']),
public_ip_ports=dict(type='list', default=[]),
configuration_id=dict(default=None),
os_type=dict(default=None,
choices=[
'redHat6_64Bit',
'centOS6_64Bit',
'windows2012R2Standard_64Bit',
'ubuntu14_64Bit'
]),
wait=dict(type='bool', default=True))
mutually_exclusive = [
@ -462,7 +666,6 @@ class ClcServer:
v2_api_passwd = env.get('CLC_V2_API_PASSWD', False)
clc_alias = env.get('CLC_ACCT_ALIAS', False)
api_url = env.get('CLC_V2_API_URL', False)
if api_url:
self.clc.defaults.ENDPOINT_URL_V2 = api_url
@ -520,9 +723,12 @@ class ClcServer:
"""
location = module.params.get('location')
try:
datacenter = clc.v2.Datacenter(location)
return datacenter
except CLCException:
if not location:
account = clc.v2.Account()
location = account.data.get('primaryDataCenter')
data_center = clc.v2.Datacenter(location)
return data_center
except CLCException as ex:
module.fail_json(
msg=str(
"Unable to find location: {0}".format(location)))
@ -668,9 +874,10 @@ class ClcServer:
"""
lookup_template = module.params.get('template')
state = module.params.get('state')
type = module.params.get('type')
result = None
if state == 'present':
if state == 'present' and type != 'bareMetal':
try:
result = datacenter.Templates().Search(lookup_template)[0].id
except CLCException:
@ -793,7 +1000,9 @@ class ClcServer:
'source_server_password': p.get('source_server_password'),
'cpu_autoscale_policy_id': p.get('cpu_autoscale_policy_id'),
'anti_affinity_policy_id': p.get('anti_affinity_policy_id'),
'packages': p.get('packages')
'packages': p.get('packages'),
'configuration_id': p.get('configuration_id'),
'os_type': p.get('os_type')
}
count = override_count if override_count else p.get('count')
@ -1123,6 +1332,11 @@ class ClcServer:
try:
if state == 'started':
result = server.PowerOn()
else:
# Try to shut down the server and fall back to power off when unable to shut down.
result = server.ShutDown()
if result and hasattr(result, 'requests') and result.requests[0]:
return result
else:
result = server.PowerOff()
except CLCException:
@ -1251,7 +1465,9 @@ class ClcServer:
'customFields': server_params.get('custom_fields'),
'additionalDisks': server_params.get('additional_disks'),
'ttl': server_params.get('ttl'),
'packages': server_params.get('packages')}))
'packages': server_params.get('packages'),
'configurationId': server_params.get('configuration_id'),
'osType': server_params.get('os_type')}))
result = clc.v2.Requests(res)
except APIFailedResponse as ex:

View file

@ -69,8 +69,8 @@ EXAMPLES = '''
- name: Create server snapshot
clc_server_snapshot:
server_ids:
- UC1TESTSVR01
- UC1TESTSVR02
- UC1TEST-SVR01
- UC1TEST-SVR02
expiration_days: 10
wait: True
state: present
@ -78,20 +78,37 @@ EXAMPLES = '''
- name: Restore server snapshot
clc_server_snapshot:
server_ids:
- UC1TESTSVR01
- UC1TESTSVR02
- UC1TEST-SVR01
- UC1TEST-SVR02
wait: True
state: restore
- name: Delete server snapshot
clc_server_snapshot:
server_ids:
- UC1TESTSVR01
- UC1TESTSVR02
- UC1TEST-SVR01
- UC1TEST-SVR02
wait: True
state: absent
'''
RETURN = '''
changed:
description: A flag indicating if any change was made or not
returned: success
type: boolean
sample: True
server_ids:
description: The list of server ids that are changed
returned: success
type: list
sample:
[
"UC1TEST-SVR01",
"UC1TEST-SVR02"
]
'''
__version__ = '${version}'
from distutils.version import LooseVersion