lib/ansible/modules/cloud/alicloud/ali_ros_stack.py (100 lines of code) (raw):

#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright (c) 2017-present Alibaba Group Holding Limited. He Steven # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see http://www.gnu.org/licenses/. from __future__ import (absolute_import, division, print_function) __metaclass__ = type ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} DOCUMENTATION = """ --- module: ali_ros_stack short_description: "Management cloud resource stack of Alibaba Cloud ROS" description: - Create, Delete and Modify for ROS Stack. author: - "Steven" options: state: description: - Whether or not to create, delete, modify ROS. choices: ['present', 'absent'] type: str default: 'present' required: True stack_name: description: - ROS stack resources name. type: str required: True template: description: - Ros stack resources template file path. type: str timeout_in_minutes: description: - Ros stack resources create timeout time. type: int default: 60 template_parameters: description: - Ros stack resources template parameters. type: dict requirements: - "python >= 3.6" - "footmark >= 1.20.0" extends_documentation_fragment: - alicloud """ EXAMPLES = """ - name: Changed. Create Ros Stack ali_ros_stack: stack_name: vpc_2020-04-08_test template: /tmp/create_vpn.json timeout_in_minutes: 60 template_parameters: CidrBlock: 192.168.0.0/16 VpcName: DemoVpc - name: Changed. Update Ros Stack ali_ros_stack: stack_name: vpc_2020-04-08_test template: /tmp/update_vpc.json timeout_in_minutes: 60 template_parameters: CidrBlock: 192.168.0.0/16 VpcName: UpdateVpc - name: Changed. Delete Ros Stack ali_ros_stack: state: absent stack_name: vpc_2020-04-08_test """ RETURN = """ stack: description: Return Ros stack detailed information. returned: always type: complex contains: create_time: description: Ros stack create time. returned: always type: str sample: '2020-04-09T01:21:26' disable_rollback: description: Ros stack Rollback options config. returned: always type: bool sample: false region_id: description: Ros stack resources region location. returned: always type: str sample: cn-beijing stack_id: description: Ros stack resources id. returned: always type: str sample: f15d848b-236c-4791-8487-75a24ab93a6b stack_name: description: Ros stack resources name. returned: always type: str sample: stack_2020-04-09 status: description: Ros stack resources status. returned: always type: str sample: CREATE_COMPLETE status_reason: description: Ros stack resources status description. returned: always type: str sample: Stack CREATE completed successfully timeout_in_minutes: 60 description: Ros stack resources create timeout time. returned: always type: int sample: 60 """ import re import json import ruamel.yaml from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.alicloud_ecs import ecs_argument_spec, ros_connect HAS_FOOTMARK = False try: from footmark.exception import ROSResponseError HAS_FOOTMARK = True except ImportError: HAS_FOOTMARK = False def get_template_body(template_path): if template_path.endswith('.yml') or template_path.endswith('.yaml'): yaml_body = open(template_path, 'r').read() yd = ruamel.yaml.load(yaml_body, ruamel.yaml.RoundTripLoader) template_body = json.dumps(yd, indent=2) else: template_body = open(template_path, 'r').read() return template_body def get_template_params(input_params): template_parameters_dict = [{"ParameterKey": k, "ParameterValue": v} for k, v in input_params.items()] return template_parameters_dict def ros_exists(ros_conn, stack_name): ros_stack = ros_conn.list_stacks(stack_names=[stack_name], get_one=True) if not ros_stack: return None else: return ros_stack.get('stack_id') def main(): argument_spec = ecs_argument_spec() argument_spec.update( dict( stack_name=dict(required=True, type='str'), template_parameters=dict(type='dict'), state=dict(default='present', choices=['present', 'absent'], type='str'), template=dict(type='str'), timeout_in_minutes=dict(default=60, type='int') ) ) module = AnsibleModule(argument_spec=argument_spec) if HAS_FOOTMARK is False: module.fail_json(msg='footmark required for the module ali_ros.') try: stack_name = module.params.get('stack_name') parameterss = get_template_params(module.params.get('template_parameters')) if \ module.params.get('template_parameters') else [] state = module.params.get('state') template_body = get_template_body(module.params.get('template')) if module.params.get('template') else None template_type = module.params.get('template').split('.')[1] if module.params.get( 'template') and '.' in module.params.get('template') else "" timeout_in_minutes = module.params.get('timeout_in_minutes') if not re.search('^[a-zA-Z][a-zA-Z0-9_\-]{0,255}$', stack_name): module.fail_json( msg='Stack name "%s" is invalid and exceeds 255 character limit. Stack names must contain only ' 'alphanumeric characters and hyphens and must start with an alphabetic character.' % stack_name) if template_type: if template_type not in ['json', 'yaml', 'yml']: module.fail_json( msg='Input template type : %s error, Please check it' % template_type) ros_conn = ros_connect(module) changed = False # Check if ROS stack exists stack_id = ros_exists(ros_conn, stack_name) params = {'stack_name': stack_name, 'parameterss': parameterss, 'template_body': template_body, 'timeout_in_minutes': timeout_in_minutes} if state == 'absent': if not stack_id: module.exit_json(changed=changed, ros={}) try: del_res = ros_conn.delete_stack(stack_id=stack_id) module.exit_json(stack={}, changed=del_res) except ROSResponseError as e: module.fail_json(msg='Unable to delete ros, error: {0}'.format(e)) elif state == 'present' and not stack_id: try: create_res = ros_conn.create_stack(**params) module.exit_json(changed=True, stack=create_res) except ROSResponseError as e: module.fail_json(msg='Unable to create ros, error: {0}'.format(e)) else: try: params['stack_id'] = stack_id del params['stack_name'] update_res = ros_conn.update_stack(**params) module.exit_json(changed=True, stack=update_res) except ROSResponseError as e: module.fail_json(msg='Unable to update ros, error: {0}'.format(e)) except Exception as e: module.fail_json(msg="Manage ros stack failed, and got an error: {0}.".format(e)) if __name__ == '__main__': main()