Coverage for /Users/jingyu.wy/git/ansible-module-apsarastack/src/ansible_collections/alibaba/apsarastack/plugins/modules/ali_vswitch.py: 37%

95 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-03-12 18:06 +0800

1#!/usr/bin/python 

2# -*- coding: utf-8 -*- 

3 

4# Copyright (c) 2017-present Alibaba Group Holding Limited. He Guimin <heguimin36@163.com.com> 

5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 

6# 

7# This file is part of Ansible 

8# 

9# Ansible is free software: you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation, either version 3 of the License, or 

12# (at your option) any later version. 

13# 

14# Ansible is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with Ansible. If not, see http://www.gnu.org/licenses/. 

21 

22from __future__ import (absolute_import, division, print_function) 

23 

24import time 

25 

26from ansible.module_utils.basic import AnsibleModule 

27from ansible.module_utils.basic import env_fallback 

28 

29__metaclass__ = type 

30 

31ANSIBLE_METADATA = {'metadata_version': '1.1', 

32 'status': ['preview'], 

33 'supported_by': 'community'} 

34 

35DOCUMENTATION = """ 

36--- 

37module: ali_vswitch 

38short_description: Manage subnet in Alibaba Cloud virtual private cloud(VPC) 

39description: 

40 - Manage subnet in Alibaba Cloud virtual private cloud(VPC). 

41 If an VSwitch ID or cidr block with VPC id is provided, the existing VSwitch (if any) will be modified. 

42options: 

43 state: 

44 description: 

45 - Create or delete vswitch. 

46 choices: ['present', 'absent'] 

47 default: 'present' 

48 type: str 

49 zone_id: 

50 description: 

51 - Aliyun availability zone ID which to launch the vswitch or list vswitches. 

52 It is required when creating a new vswitch. 

53 aliases: ['availability_zone', 'apsarastack_zone'] 

54 type: str 

55 vpc_id: 

56 description: 

57 - The ID of a VPC to which that Vswitch belongs. 

58 This is used in combination with C(cidr_block) to determine if a VSwitch already exists. 

59 required: True 

60 type: str 

61 cidr_block: 

62 description: 

63 - The CIDR block representing the Vswitch e.g. 10.0.0.0/8. The value must be sub cidr_block of Vpc. 

64 This is used in conjunction with the C(vpc_id) to ensure idempotence. 

65 required: True 

66 type: str 

67 name: 

68 description: 

69 - The name of vswitch, which is a string of 2 to 128 Chinese or English characters. It must begin with an 

70 uppercase/lowercase letter or a Chinese character and can contain numerals, "_" or "-". 

71 It cannot begin with http:// or https://. 

72 aliases: ['vswitch_name', 'subnet_name'] 

73 type: str 

74 description: 

75 description: 

76 - The description of vswitch, which is a string of 2 to 256 characters. It cannot begin with http:// or https://. 

77 type: str 

78 vswitch_id: 

79 description: 

80 - VSwitch ID. 

81 aliases: ['subnet_id', 'id'] 

82 type: str 

83 tags: 

84 description: 

85 - A hash/dictionaries of vswitch tags. C({"key":"value"}) 

86 type: dict 

87 purge_tags: 

88 description: 

89 - Delete existing tags on the vswitch that are not specified in the task. 

90 If True, it means you have to specify all the desired tags on each task affecting a vswitch. 

91 default: False 

92 type: bool 

93requirements: 

94 - "python >= 3.6" 

95 - "footmark >= 1.13.0" 

96extends_documentation_fragment: 

97 - apsarastack 

98author: 

99 - "Wang Yu (@zshongyi) 

100 - "He Guimin (@xiaozhu36)" 

101""" 

102 

103EXAMPLES = """ 

104# Note: These examples do not set authentication details, see the Alibaba Cloud Guide for details. 

105- name: Create a new vswitch 

106 ali_vswitch: 

107 cidr_block: '{{ cidr_blok }}' 

108 name: 'my-vsw' 

109 vpc_id: 'vpc-abc12345' 

110 

111- name: Modify the existing vswitch 

112 ali_vswitch: 

113 cidr_block: '{{ cidr_blok }}' 

114 vpc_id: 'vpc-abc12345' 

115 name: 'my-vsw-from-ansible' 

116 

117- name: Delete the existing vswitch 

118 ali_vswitch: 

119 cidr_block: '{{ cidr_blok }}' 

120 vpc_id: 'vpc-abc12345' 

121 state: 'absent' 

122""" 

123 

124RETURN = ''' 

125vswitch: 

126 description: Dictionary of vswitch values 

127 returned: always 

128 type: complex 

129 contains: 

130 id: 

131 description: alias of vswitch_id 

132 returned: always 

133 type: str 

134 sample: vsw-b883b2c4 

135 cidr_block: 

136 description: The IPv4 CIDR of the VSwitch 

137 returned: always 

138 type: str 

139 sample: "10.0.0.0/16" 

140 zone_id: 

141 description: Availability zone of the VSwitch 

142 returned: always 

143 type: str 

144 sample: cn-beijing-a 

145 state: 

146 description: state of the Subnet 

147 returned: always 

148 type: str 

149 sample: available 

150 is_default: 

151 description: indicates whether this is the default VSwitch 

152 returned: always 

153 type: bool 

154 sample: false 

155 tags: 

156 description: tags attached to the Subnet, includes name 

157 returned: always 

158 type: dict 

159 sample: {"Name": "My Subnet", "env": "staging"} 

160 vpc_id: 

161 description: the id of the VPC where this VSwitch exists 

162 returned: always 

163 type: str 

164 sample: vpc-67236184 

165 available_ip_address_count: 

166 description: number of available IPv4 addresses 

167 returned: always 

168 type: str 

169 sample: 250 

170 vswitch_id: 

171 description: VSwitch resource id 

172 returned: always 

173 type: str 

174 sample: vsw-b883b2c4 

175 subnet_id: 

176 description: alias of vswitch_id 

177 returned: always 

178 type: str 

179 sample: vsw-b883b2c4 

180 vswitch_name: 

181 description: VSwitch resource name 

182 returned: always 

183 type: str 

184 sample: my-vsw 

185 creation_time: 

186 description: The time the VSwitch was created. 

187 returned: always 

188 type: str 

189 sample: '2018-06-24T15:14:45Z' 

190''' 

191 

192try: 

193 from ansible_collections.alibaba.apsarastack.plugins.module_utils.apsarastack_common import common_argument_spec 

194 from ansible_collections.alibaba.apsarastack.plugins.module_utils.apsarastack_connections import vpc_connect 

195except ImportError: 

196 from ..module_utils.apsarastack_common import common_argument_spec 

197 from ..module_utils.apsarastack_connections import vpc_connect 

198 

199HAS_FOOTMARK = False 

200 

201try: 

202 from footmark.exception import VPCResponseError 

203 HAS_FOOTMARK = True 

204except ImportError: 

205 HAS_FOOTMARK = False 

206 

207 

208def vswitch_exists(conn, module, vswitch_id, vpc_id, cidr): 

209 try: 

210 for vsw in conn.describe_vswitches(): 

211 if cidr and vsw.cidr_block != cidr: 

212 continue 

213 if vpc_id and vpc_id != vsw.vpc_id: 

214 continue 

215 if vswitch_id and vswitch_id != vsw.vswitch_id: 

216 continue 

217 return vsw 

218 except Exception as e: 

219 module.fail_json(msg="Couldn't get matching subnet: {0}".format(e)) 

220 

221 

222def main(): 

223 argument_spec = common_argument_spec() 

224 argument_spec.update(dict( 

225 state=dict(default='present', choices=['present', 'absent']), 

226 cidr_block=dict(type='str', required=True), 

227 description=dict(type='str'), 

228 zone_id=dict(type='str', aliases=['availability_zone', 'apsarastack_zone'], 

229 fallback=(env_fallback, ['APSARASTACK_ZONE', 'APSARASTACK_ZONE_ID'])), 

230 vpc_id=dict(type='str', required=True), 

231 name=dict(type='str', aliases=['vswitch_name', 'subnet_name']), 

232 vswitch_id=dict(type='str', aliases=['subnet_id', 'id']), 

233 tags=dict(type='dict'), 

234 purge_tags=dict(type='bool', default=False) 

235 )) 

236 

237 module = AnsibleModule(argument_spec=argument_spec) 

238 

239 if HAS_FOOTMARK is False: 

240 module.fail_json(msg='footmark required for the module ali_vswitch.') 

241 

242 vpc = vpc_connect(module) 

243 

244 # Get values of variable 

245 state = module.params['state'] 

246 vswitch_id = module.params['vswitch_id'] 

247 

248 changed = False 

249 vswitch = vswitch_exists(vpc, module, vswitch_id, module.params['vpc_id'], module.params['cidr_block']) 

250 

251 if state == 'absent': 

252 if not vswitch: 

253 module.exit_json(changed=changed, vswitch={}) 

254 try: 

255 changed = vswitch.delete() 

256 module.exit_json(changed=changed, vswitch={}) 

257 except VPCResponseError as ex: 

258 module.fail_json(msg='Unable to delete vswitch: {0}, error: {1}'.format(vswitch.id, ex)) 

259 

260 vswitch_name = module.params['name'] 

261 description = module.params['description'] 

262 if str(description).startswith('http://') or str(description).startswith('https://'): 

263 module.fail_json(msg='description can not start with http:// or https://') 

264 

265 if str(vswitch_name).startswith('http://') or str(vswitch_name).startswith('https://'): 

266 module.fail_json(msg='vswitch_name can not start with http:// or https://') 

267 

268 if not vswitch: 

269 try: 

270 params = module.params 

271 params['client_token'] = "Ansible-Apsarastack-{0}-{1}".format(hash(str(module.params)), str(time.time())) 

272 params['vswitch_name'] = vswitch_name 

273 vswitch = vpc.create_vswitch(**params) 

274 module.exit_json(changed=True, vswitch=vswitch.get().read()) 

275 except VPCResponseError as e: 

276 module.fail_json(msg='Unable to create VSwitch, error: {0}'.format(e)) 

277 

278 if not vswitch_name: 

279 vswitch_name = vswitch.vswitch_name 

280 if not description: 

281 description = vswitch.description 

282 try: 

283 if vswitch.modify(name=vswitch_name, description=description): 

284 changed = True 

285 except VPCResponseError as e: 

286 module.fail_json(msg='Unable to modify vswitch attribute, error: {0}'.format(e)) 

287 

288 tags = module.params['tags'] 

289 if module.params['purge_tags']: 

290 if not tags: 

291 tags = vswitch.tags 

292 try: 

293 if vswitch.remove_tags(tags): 

294 changed = True 

295 module.exit_json(changed=changed, vswitch=vswitch.get().read()) 

296 except Exception as e: 

297 module.fail_json(msg="{0}".format(e)) 

298 

299 if tags: 

300 try: 

301 if vswitch.add_tags(tags): 

302 changed = True 

303 except Exception as e: 

304 module.fail_json(msg="{0}".format(e)) 

305 module.exit_json(changed=changed, vswitch=vswitch.get().read()) 

306 

307 

308if __name__ == '__main__': 

309 main()