mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add param for doc/fragments/alicloud (#108)
This commit is contained in:
parent
6d7f66539c
commit
4ebb65e6f6
6 changed files with 791 additions and 378 deletions
6
changelogs/fragments/alicloud_params_add.yml
Normal file
6
changelogs/fragments/alicloud_params_add.yml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
changes:
|
||||||
|
- "alicloud modules - now only support Python 3.6, not support Python 2.x"
|
||||||
|
- "ali_instance and ali_instance_info - the required package footmark needs a version higher than 1.19.0"
|
||||||
|
- "ali_instance - Add params ``unique_suffix``, ``tags``, ``purge_tags``, ``ram_role_name``, ``spot_price_limit``, ``spot_strategy``, ``period_unit``, ``dry_run``, ``include_data_disks``"
|
||||||
|
- "ali_instance_info - Add params ``name_prefix``, ``filters``"
|
||||||
|
- "alicloud modules - Add authentication params to all modules"
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright: (c) 2017 Alibaba Group Holding Limited. He Guimin <heguimin36@163.com>
|
# Copyright (c) 2017-present Alibaba Group Holding Limited. He Guimin <heguimin36@163.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,46 +11,95 @@ class ModuleDocFragment(object):
|
||||||
options:
|
options:
|
||||||
alicloud_access_key:
|
alicloud_access_key:
|
||||||
description:
|
description:
|
||||||
- Aliyun Cloud access key.
|
- Alibaba Cloud access key. If not set then the value of environment variable C(ALICLOUD_ACCESS_KEY),
|
||||||
- If not set then the value of environment variable C(ALICLOUD_ACCESS_KEY),
|
|
||||||
C(ALICLOUD_ACCESS_KEY_ID) will be used instead.
|
C(ALICLOUD_ACCESS_KEY_ID) will be used instead.
|
||||||
|
aliases: ['access_key_id', 'access_key']
|
||||||
type: str
|
type: str
|
||||||
aliases: [ access_key_id, access_key ]
|
|
||||||
alicloud_secret_key:
|
alicloud_secret_key:
|
||||||
description:
|
description:
|
||||||
- Aliyun Cloud secret key.
|
- Alibaba Cloud secret key. If not set then the value of environment variable C(ALICLOUD_SECRET_KEY),
|
||||||
- If not set then the value of environment variable C(ALICLOUD_SECRET_KEY),
|
|
||||||
C(ALICLOUD_SECRET_ACCESS_KEY) will be used instead.
|
C(ALICLOUD_SECRET_ACCESS_KEY) will be used instead.
|
||||||
|
aliases: ['secret_access_key', 'secret_key']
|
||||||
type: str
|
type: str
|
||||||
aliases: [ secret_access_key, secret_key ]
|
|
||||||
alicloud_region:
|
alicloud_region:
|
||||||
description:
|
description:
|
||||||
- The Aliyun Cloud region to use.
|
- The Alibaba Cloud region to use. If not specified then the value of environment variable
|
||||||
- If not specified then the value of environment variable
|
|
||||||
C(ALICLOUD_REGION), C(ALICLOUD_REGION_ID) will be used instead.
|
C(ALICLOUD_REGION), C(ALICLOUD_REGION_ID) will be used instead.
|
||||||
|
aliases: ['region', 'region_id']
|
||||||
|
required: true
|
||||||
type: str
|
type: str
|
||||||
aliases: [ region, region_id ]
|
|
||||||
alicloud_security_token:
|
alicloud_security_token:
|
||||||
description:
|
description:
|
||||||
- The Aliyun Cloud security token.
|
- The Alibaba Cloud security token. If not specified then the value of environment variable
|
||||||
- If not specified then the value of environment variable
|
|
||||||
C(ALICLOUD_SECURITY_TOKEN) will be used instead.
|
C(ALICLOUD_SECURITY_TOKEN) will be used instead.
|
||||||
|
aliases: ['security_token']
|
||||||
|
type: str
|
||||||
|
alicloud_assume_role:
|
||||||
|
description:
|
||||||
|
- If provided with a role ARN, Ansible will attempt to assume this role using the supplied credentials.
|
||||||
|
- The nested assume_role block supports I(alicloud_assume_role_arn), I(alicloud_assume_role_session_name),
|
||||||
|
I(alicloud_assume_role_session_expiration) and I(alicloud_assume_role_policy)
|
||||||
|
type: dict
|
||||||
|
aliases: ['assume_role']
|
||||||
|
alicloud_assume_role_arn:
|
||||||
|
description:
|
||||||
|
- The Alibaba Cloud role_arn. The ARN of the role to assume. If ARN is set to an empty string,
|
||||||
|
it does not perform role switching. It supports environment variable ALICLOUD_ASSUME_ROLE_ARN.
|
||||||
|
ansible will execute with provided credentials.
|
||||||
|
aliases: ['assume_role_arn']
|
||||||
|
type: str
|
||||||
|
alicloud_assume_role_session_name:
|
||||||
|
description:
|
||||||
|
- The Alibaba Cloud session_name. The session name to use when assuming the role. If omitted,
|
||||||
|
'ansible' is passed to the AssumeRole call as session name. It supports environment variable
|
||||||
|
ALICLOUD_ASSUME_ROLE_SESSION_NAME
|
||||||
|
aliases: ['assume_role_session_name']
|
||||||
|
type: str
|
||||||
|
alicloud_assume_role_session_expiration:
|
||||||
|
description:
|
||||||
|
- The Alibaba Cloud session_expiration. The time after which the established session for assuming
|
||||||
|
role expires. Valid value range 900-3600 seconds. Default to 3600 (in this case Alicloud use own default
|
||||||
|
value). It supports environment variable ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION
|
||||||
|
aliases: ['assume_role_session_expiration']
|
||||||
|
type: int
|
||||||
|
ecs_role_name:
|
||||||
|
description:
|
||||||
|
- The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control'
|
||||||
|
section of the Alibaba Cloud console.
|
||||||
|
- If you're running Ansible from an ECS instance with RAM Instance using RAM Role, Ansible will just access the
|
||||||
|
metadata U(http://100.100.100.200/latest/meta-data/ram/security-credentials/<ecs_role_name>) to obtain the STS
|
||||||
|
credential. This is a preferred approach over any other when running in ECS as you can avoid hard coding
|
||||||
|
credentials. Instead these are leased on-the-fly by Ansible which reduces the chance of leakage.
|
||||||
|
aliases: ['role_name']
|
||||||
|
type: str
|
||||||
|
profile:
|
||||||
|
description:
|
||||||
|
- This is the Alicloud profile name as set in the shared credentials file. It can also be sourced from the
|
||||||
|
ALICLOUD_PROFILE environment variable.
|
||||||
|
type: str
|
||||||
|
shared_credentials_file:
|
||||||
|
description:
|
||||||
|
- This is the path to the shared credentials file. It can also be sourced from the ALICLOUD_SHARED_CREDENTIALS_FILE
|
||||||
|
environment variable.
|
||||||
|
- If this is not set and a profile is specified, ~/.aliyun/config.json will be used.
|
||||||
type: str
|
type: str
|
||||||
aliases: [ security_token ]
|
|
||||||
author:
|
author:
|
||||||
- He Guimin (@xiaozhu36)
|
- "He Guimin (@xiaozhu36)"
|
||||||
requirements:
|
requirements:
|
||||||
- python >= 2.6
|
- "python >= 3.6"
|
||||||
extends_documentation_fragment:
|
|
||||||
- community.general.alicloud
|
|
||||||
|
|
||||||
notes:
|
notes:
|
||||||
- If parameters are not set within the module, the following
|
- If parameters are not set within the module, the following
|
||||||
environment variables can be used in decreasing order of precedence
|
environment variables can be used in decreasing order of precedence
|
||||||
C(ALICLOUD_ACCESS_KEY) or C(ALICLOUD_ACCESS_KEY_ID),
|
C(ALICLOUD_ACCESS_KEY) or C(ALICLOUD_ACCESS_KEY_ID),
|
||||||
C(ALICLOUD_SECRET_KEY) or C(ALICLOUD_SECRET_ACCESS_KEY),
|
C(ALICLOUD_SECRET_KEY) or C(ALICLOUD_SECRET_ACCESS_KEY),
|
||||||
C(ALICLOUD_REGION) or C(ALICLOUD_REGION_ID),
|
C(ALICLOUD_REGION) or C(ALICLOUD_REGION_ID),
|
||||||
C(ALICLOUD_SECURITY_TOKEN)
|
C(ALICLOUD_SECURITY_TOKEN),
|
||||||
|
C(ALICLOUD_ECS_ROLE_NAME),
|
||||||
|
C(ALICLOUD_SHARED_CREDENTIALS_FILE),
|
||||||
|
C(ALICLOUD_PROFILE),
|
||||||
|
C(ALICLOUD_ASSUME_ROLE_ARN),
|
||||||
|
C(ALICLOUD_ASSUME_ROLE_SESSION_NAME),
|
||||||
|
C(ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION),
|
||||||
- C(ALICLOUD_REGION) or C(ALICLOUD_REGION_ID) can be typically be used to specify the
|
- C(ALICLOUD_REGION) or C(ALICLOUD_REGION_ID) can be typically be used to specify the
|
||||||
ALICLOUD region, when required, but this can also be configured in the footmark config file
|
ALICLOUD region, when required, but this can also be configured in the footmark config file
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# still belong to the author of the module, and may assign their own license
|
# still belong to the author of the module, and may assign their own license
|
||||||
# to the complete work.
|
# to the complete work.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2017 Alibaba Group Holding Limited. He Guimin <heguimin36@163.com>
|
# Copyright (c) 2017-present Alibaba Group Holding Limited. He Guimin <heguimin36@163.com>
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
# are permitted provided that the following conditions are met:
|
# are permitted provided that the following conditions are met:
|
||||||
|
@ -26,6 +26,8 @@
|
||||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
from ansible.module_utils.basic import env_fallback
|
from ansible.module_utils.basic import env_fallback
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -35,6 +37,10 @@ try:
|
||||||
import footmark.vpc
|
import footmark.vpc
|
||||||
import footmark.rds
|
import footmark.rds
|
||||||
import footmark.ess
|
import footmark.ess
|
||||||
|
import footmark.sts
|
||||||
|
import footmark.dns
|
||||||
|
import footmark.ram
|
||||||
|
import footmark.market
|
||||||
HAS_FOOTMARK = True
|
HAS_FOOTMARK = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_FOOTMARK = False
|
HAS_FOOTMARK = False
|
||||||
|
@ -46,12 +52,13 @@ class AnsibleACSError(Exception):
|
||||||
|
|
||||||
def acs_common_argument_spec():
|
def acs_common_argument_spec():
|
||||||
return dict(
|
return dict(
|
||||||
alicloud_access_key=dict(required=True, aliases=['access_key_id', 'access_key'], no_log=True,
|
alicloud_access_key=dict(aliases=['access_key_id', 'access_key'], no_log=True,
|
||||||
fallback=(env_fallback, ['ALICLOUD_ACCESS_KEY', 'ALICLOUD_ACCESS_KEY_ID'])),
|
fallback=(env_fallback, ['ALICLOUD_ACCESS_KEY', 'ALICLOUD_ACCESS_KEY_ID'])),
|
||||||
alicloud_secret_key=dict(required=True, aliases=['secret_access_key', 'secret_key'], no_log=True,
|
alicloud_secret_key=dict(aliases=['secret_access_key', 'secret_key'], no_log=True,
|
||||||
fallback=(env_fallback, ['ALICLOUD_SECRET_KEY', 'ALICLOUD_SECRET_ACCESS_KEY'])),
|
fallback=(env_fallback, ['ALICLOUD_SECRET_KEY', 'ALICLOUD_SECRET_ACCESS_KEY'])),
|
||||||
alicloud_security_token=dict(aliases=['security_token'], no_log=True,
|
alicloud_security_token=dict(aliases=['security_token'], no_log=True,
|
||||||
fallback=(env_fallback, ['ALICLOUD_SECURITY_TOKEN'])),
|
fallback=(env_fallback, ['ALICLOUD_SECURITY_TOKEN'])),
|
||||||
|
ecs_role_name=dict(aliases=['role_name'], fallback=(env_fallback, ['ALICLOUD_ECS_ROLE_NAME']))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,19 +68,30 @@ def ecs_argument_spec():
|
||||||
dict(
|
dict(
|
||||||
alicloud_region=dict(required=True, aliases=['region', 'region_id'],
|
alicloud_region=dict(required=True, aliases=['region', 'region_id'],
|
||||||
fallback=(env_fallback, ['ALICLOUD_REGION', 'ALICLOUD_REGION_ID'])),
|
fallback=(env_fallback, ['ALICLOUD_REGION', 'ALICLOUD_REGION_ID'])),
|
||||||
|
alicloud_assume_role_arn=dict(fallback=(env_fallback, ['ALICLOUD_ASSUME_ROLE_ARN']),
|
||||||
|
aliases=['assume_role_arn']),
|
||||||
|
alicloud_assume_role_session_name=dict(fallback=(env_fallback, ['ALICLOUD_ASSUME_ROLE_SESSION_NAME']),
|
||||||
|
aliases=['assume_role_session_name']),
|
||||||
|
alicloud_assume_role_session_expiration=dict(type='int',
|
||||||
|
fallback=(env_fallback,
|
||||||
|
['ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION']),
|
||||||
|
aliases=['assume_role_session_expiration']),
|
||||||
|
alicloud_assume_role=dict(type='dict', aliases=['assume_role']),
|
||||||
|
profile=dict(fallback=(env_fallback, ['ALICLOUD_PROFILE'])),
|
||||||
|
shared_credentials_file=dict(fallback=(env_fallback, ['ALICLOUD_SHARED_CREDENTIALS_FILE']))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return spec
|
return spec
|
||||||
|
|
||||||
|
|
||||||
def get_acs_connection_info(module):
|
def get_acs_connection_info(params):
|
||||||
|
|
||||||
ecs_params = dict(acs_access_key_id=module.params.get('alicloud_access_key'),
|
ecs_params = dict(acs_access_key_id=params.get('alicloud_access_key'),
|
||||||
acs_secret_access_key=module.params.get('alicloud_secret_key'),
|
acs_secret_access_key=params.get('alicloud_secret_key'),
|
||||||
security_token=module.params.get('alicloud_security_token'),
|
security_token=params.get('alicloud_security_token'),
|
||||||
|
ecs_role_name=params.get('ecs_role_name'),
|
||||||
user_agent='Ansible-Provider-Alicloud')
|
user_agent='Ansible-Provider-Alicloud')
|
||||||
|
return ecs_params
|
||||||
return module.params.get('alicloud_region'), ecs_params
|
|
||||||
|
|
||||||
|
|
||||||
def connect_to_acs(acs_module, region, **params):
|
def connect_to_acs(acs_module, region, **params):
|
||||||
|
@ -88,11 +106,80 @@ def connect_to_acs(acs_module, region, **params):
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
|
|
||||||
|
def get_assume_role(params):
|
||||||
|
""" Return new params """
|
||||||
|
sts_params = get_acs_connection_info(params)
|
||||||
|
assume_role = {}
|
||||||
|
if params.get('assume_role'):
|
||||||
|
assume_role['alicloud_assume_role_arn'] = params['assume_role'].get('role_arn')
|
||||||
|
assume_role['alicloud_assume_role_session_name'] = params['assume_role'].get('session_name')
|
||||||
|
assume_role['alicloud_assume_role_session_expiration'] = params['assume_role'].get('session_expiration')
|
||||||
|
assume_role['alicloud_assume_role_policy'] = params['assume_role'].get('policy')
|
||||||
|
|
||||||
|
assume_role_params = {
|
||||||
|
'role_arn': params.get('alicloud_assume_role_arn') if params.get('alicloud_assume_role_arn') else assume_role.get('alicloud_assume_role_arn'),
|
||||||
|
'role_session_name': params.get('alicloud_assume_role_session_name') if params.get('alicloud_assume_role_session_name')
|
||||||
|
else assume_role.get('alicloud_assume_role_session_name'),
|
||||||
|
'duration_seconds': params.get('alicloud_assume_role_session_expiration') if params.get('alicloud_assume_role_session_expiration')
|
||||||
|
else assume_role.get('alicloud_assume_role_session_expiration', 3600),
|
||||||
|
'policy': assume_role.get('alicloud_assume_role_policy', {})
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
sts = connect_to_acs(footmark.sts, params.get('alicloud_region'), **sts_params).assume_role(**assume_role_params).read()
|
||||||
|
sts_params['acs_access_key_id'], sts_params['acs_secret_access_key'], sts_params['security_token'] \
|
||||||
|
= sts['access_key_id'], sts['access_key_secret'], sts['security_token']
|
||||||
|
except AnsibleACSError as e:
|
||||||
|
params.fail_json(msg=str(e))
|
||||||
|
return sts_params
|
||||||
|
|
||||||
|
|
||||||
|
def get_profile(params):
|
||||||
|
if not params['alicloud_access_key'] and not params['ecs_role_name'] and params['profile']:
|
||||||
|
path = params['shared_credentials_file'] if params['shared_credentials_file'] else os.getenv('HOME') + '/.aliyun/config.json'
|
||||||
|
auth = {}
|
||||||
|
with open(path, 'r') as f:
|
||||||
|
for pro in json.load(f)['profiles']:
|
||||||
|
if params['profile'] == pro['name']:
|
||||||
|
auth = pro
|
||||||
|
if auth:
|
||||||
|
if auth['mode'] == 'AK' and auth.get('access_key_id') and auth.get('access_key_secret'):
|
||||||
|
params['alicloud_access_key'] = auth.get('access_key_id')
|
||||||
|
params['alicloud_secret_key'] = auth.get('access_key_secret')
|
||||||
|
params['alicloud_region'] = auth.get('region_id')
|
||||||
|
params = get_acs_connection_info(params)
|
||||||
|
elif auth['mode'] == 'StsToken' and auth.get('access_key_id') and auth.get('access_key_secret') and auth.get('sts_token'):
|
||||||
|
params['alicloud_access_key'] = auth.get('access_key_id')
|
||||||
|
params['alicloud_secret_key'] = auth.get('access_key_secret')
|
||||||
|
params['security_token'] = auth.get('sts_token')
|
||||||
|
params['alicloud_region'] = auth.get('region_id')
|
||||||
|
params = get_acs_connection_info(params)
|
||||||
|
elif auth['mode'] == 'EcsRamRole':
|
||||||
|
params['ecs_role_name'] = auth.get('ram_role_name')
|
||||||
|
params['alicloud_region'] = auth.get('region_id')
|
||||||
|
params = get_acs_connection_info(params)
|
||||||
|
elif auth['mode'] == 'RamRoleArn' and auth.get('ram_role_arn'):
|
||||||
|
params['alicloud_access_key'] = auth.get('access_key_id')
|
||||||
|
params['alicloud_secret_key'] = auth.get('access_key_secret')
|
||||||
|
params['security_token'] = auth.get('sts_token')
|
||||||
|
params['ecs_role_name'] = auth.get('ram_role_name')
|
||||||
|
params['alicloud_assume_role_arn'] = auth.get('ram_role_arn')
|
||||||
|
params['alicloud_assume_role_session_name'] = auth.get('ram_session_name')
|
||||||
|
params['alicloud_assume_role_session_expiration'] = auth.get('expired_seconds')
|
||||||
|
params['alicloud_region'] = auth.get('region_id')
|
||||||
|
params = get_assume_role(params)
|
||||||
|
elif params.get('alicloud_assume_role_arn') or params.get('assume_role'):
|
||||||
|
params = get_assume_role(params)
|
||||||
|
else:
|
||||||
|
params = get_acs_connection_info(params)
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
def ecs_connect(module):
|
def ecs_connect(module):
|
||||||
""" Return an ecs connection"""
|
""" Return an ecs connection"""
|
||||||
|
ecs_params = get_profile(module.params)
|
||||||
region, ecs_params = get_acs_connection_info(module)
|
|
||||||
# If we have a region specified, connect to its endpoint.
|
# If we have a region specified, connect to its endpoint.
|
||||||
|
region = module.params.get('alicloud_region')
|
||||||
if region:
|
if region:
|
||||||
try:
|
try:
|
||||||
ecs = connect_to_acs(footmark.ecs, region, **ecs_params)
|
ecs = connect_to_acs(footmark.ecs, region, **ecs_params)
|
||||||
|
@ -104,9 +191,9 @@ def ecs_connect(module):
|
||||||
|
|
||||||
def slb_connect(module):
|
def slb_connect(module):
|
||||||
""" Return an slb connection"""
|
""" Return an slb connection"""
|
||||||
|
slb_params = get_profile(module.params)
|
||||||
region, slb_params = get_acs_connection_info(module)
|
|
||||||
# If we have a region specified, connect to its endpoint.
|
# If we have a region specified, connect to its endpoint.
|
||||||
|
region = module.params.get('alicloud_region')
|
||||||
if region:
|
if region:
|
||||||
try:
|
try:
|
||||||
slb = connect_to_acs(footmark.slb, region, **slb_params)
|
slb = connect_to_acs(footmark.slb, region, **slb_params)
|
||||||
|
@ -116,11 +203,25 @@ def slb_connect(module):
|
||||||
return slb
|
return slb
|
||||||
|
|
||||||
|
|
||||||
|
def dns_connect(module):
|
||||||
|
""" Return an dns connection"""
|
||||||
|
dns_params = get_profile(module.params)
|
||||||
|
# If we have a region specified, connect to its endpoint.
|
||||||
|
region = module.params.get('alicloud_region')
|
||||||
|
if region:
|
||||||
|
try:
|
||||||
|
dns = connect_to_acs(footmark.dns, region, **dns_params)
|
||||||
|
except AnsibleACSError as e:
|
||||||
|
module.fail_json(msg=str(e))
|
||||||
|
# Otherwise, no region so we fallback to the old connection method
|
||||||
|
return dns
|
||||||
|
|
||||||
|
|
||||||
def vpc_connect(module):
|
def vpc_connect(module):
|
||||||
""" Return an vpc connection"""
|
""" Return an vpc connection"""
|
||||||
|
vpc_params = get_profile(module.params)
|
||||||
region, vpc_params = get_acs_connection_info(module)
|
|
||||||
# If we have a region specified, connect to its endpoint.
|
# If we have a region specified, connect to its endpoint.
|
||||||
|
region = module.params.get('alicloud_region')
|
||||||
if region:
|
if region:
|
||||||
try:
|
try:
|
||||||
vpc = connect_to_acs(footmark.vpc, region, **vpc_params)
|
vpc = connect_to_acs(footmark.vpc, region, **vpc_params)
|
||||||
|
@ -132,9 +233,9 @@ def vpc_connect(module):
|
||||||
|
|
||||||
def rds_connect(module):
|
def rds_connect(module):
|
||||||
""" Return an rds connection"""
|
""" Return an rds connection"""
|
||||||
|
rds_params = get_profile(module.params)
|
||||||
region, rds_params = get_acs_connection_info(module)
|
|
||||||
# If we have a region specified, connect to its endpoint.
|
# If we have a region specified, connect to its endpoint.
|
||||||
|
region = module.params.get('alicloud_region')
|
||||||
if region:
|
if region:
|
||||||
try:
|
try:
|
||||||
rds = connect_to_acs(footmark.rds, region, **rds_params)
|
rds = connect_to_acs(footmark.rds, region, **rds_params)
|
||||||
|
@ -146,9 +247,9 @@ def rds_connect(module):
|
||||||
|
|
||||||
def ess_connect(module):
|
def ess_connect(module):
|
||||||
""" Return an ess connection"""
|
""" Return an ess connection"""
|
||||||
|
ess_params = get_profile(module.params)
|
||||||
region, ess_params = get_acs_connection_info(module)
|
|
||||||
# If we have a region specified, connect to its endpoint.
|
# If we have a region specified, connect to its endpoint.
|
||||||
|
region = module.params.get('alicloud_region')
|
||||||
if region:
|
if region:
|
||||||
try:
|
try:
|
||||||
ess = connect_to_acs(footmark.ess, region, **ess_params)
|
ess = connect_to_acs(footmark.ess, region, **ess_params)
|
||||||
|
@ -156,3 +257,45 @@ def ess_connect(module):
|
||||||
module.fail_json(msg=str(e))
|
module.fail_json(msg=str(e))
|
||||||
# Otherwise, no region so we fallback to the old connection method
|
# Otherwise, no region so we fallback to the old connection method
|
||||||
return ess
|
return ess
|
||||||
|
|
||||||
|
|
||||||
|
def sts_connect(module):
|
||||||
|
""" Return an sts connection"""
|
||||||
|
sts_params = get_profile(module.params)
|
||||||
|
# If we have a region specified, connect to its endpoint.
|
||||||
|
region = module.params.get('alicloud_region')
|
||||||
|
if region:
|
||||||
|
try:
|
||||||
|
sts = connect_to_acs(footmark.sts, region, **sts_params)
|
||||||
|
except AnsibleACSError as e:
|
||||||
|
module.fail_json(msg=str(e))
|
||||||
|
# Otherwise, no region so we fallback to the old connection method
|
||||||
|
return sts
|
||||||
|
|
||||||
|
|
||||||
|
def ram_connect(module):
|
||||||
|
""" Return an ram connection"""
|
||||||
|
ram_params = get_profile(module.params)
|
||||||
|
# If we have a region specified, connect to its endpoint.
|
||||||
|
region = module.params.get('alicloud_region')
|
||||||
|
if region:
|
||||||
|
try:
|
||||||
|
ram = connect_to_acs(footmark.ram, region, **ram_params)
|
||||||
|
except AnsibleACSError as e:
|
||||||
|
module.fail_json(msg=str(e))
|
||||||
|
# Otherwise, no region so we fallback to the old connection method
|
||||||
|
return ram
|
||||||
|
|
||||||
|
|
||||||
|
def market_connect(module):
|
||||||
|
""" Return an market connection"""
|
||||||
|
market_params = get_profile(module.params)
|
||||||
|
# If we have a region specified, connect to its endpoint.
|
||||||
|
region = module.params.get('alicloud_region')
|
||||||
|
if region:
|
||||||
|
try:
|
||||||
|
market = connect_to_acs(footmark.market, region, **market_params)
|
||||||
|
except AnsibleACSError as e:
|
||||||
|
module.fail_json(msg=str(e))
|
||||||
|
# Otherwise, no region so we fallback to the old connection method
|
||||||
|
return market
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# Copyright (c) 2017 Alibaba Group Holding Limited. He Guimin <heguimin36@163.com>
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2017-present Alibaba Group Holding Limited. He Guimin <heguimin36@163.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
#
|
#
|
||||||
# This file is part of Ansible
|
# This file is part of Ansible
|
||||||
|
@ -17,51 +19,50 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Ansible. If not, see http://www.gnu.org/licenses/.
|
# along with Ansible. If not, see http://www.gnu.org/licenses/.
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
'metadata_version': '1.1',
|
|
||||||
'status': ['preview'],
|
'status': ['preview'],
|
||||||
'supported_by': 'community'
|
'supported_by': 'community'}
|
||||||
}
|
|
||||||
|
|
||||||
DOCUMENTATION = r'''
|
DOCUMENTATION = '''
|
||||||
---
|
---
|
||||||
module: ali_instance
|
module: ali_instance
|
||||||
short_description: Create, start, stop, restart or terminate an instance in ECS, add or remove an instance to/from a security group
|
short_description: Create, Start, Stop, Restart or Terminate an Instance in ECS. Add or Remove Instance to/from a Security Group.
|
||||||
description:
|
description:
|
||||||
- Create, start, stop, restart, modify or terminate ecs instances.
|
- Create, start, stop, restart, modify or terminate ecs instances.
|
||||||
- Add or remove ecs instances to/from security group.
|
- Add or remove ecs instances to/from security group.
|
||||||
options:
|
options:
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- The state of the instance after operating.
|
- The state of the instance after operating.
|
||||||
type: str
|
|
||||||
default: 'present'
|
default: 'present'
|
||||||
choices: ['absent', 'present', 'restarted', 'running', 'stopped']
|
choices: ['present', 'running', 'stopped', 'restarted', 'absent']
|
||||||
|
type: str
|
||||||
availability_zone:
|
availability_zone:
|
||||||
description:
|
description:
|
||||||
- Aliyun availability zone ID in which to launch the instance.
|
- Aliyun availability zone ID in which to launch the instance.
|
||||||
- If it is not specified, it will be allocated by system automatically.
|
If it is not specified, it will be allocated by system automatically.
|
||||||
aliases: ['alicloud_zone']
|
aliases: ['alicloud_zone', 'zone_id']
|
||||||
type: str
|
type: str
|
||||||
image_id:
|
image_id:
|
||||||
description:
|
description:
|
||||||
- Image ID used to launch instances.
|
- Image ID used to launch instances. Required when C(state=present) and creating new ECS instances.
|
||||||
- Required when I(state=present) and creating new ECS instances.
|
|
||||||
aliases: ['image']
|
aliases: ['image']
|
||||||
type: str
|
type: str
|
||||||
instance_type:
|
instance_type:
|
||||||
description:
|
description:
|
||||||
- Instance type used to launch instances.
|
- Instance type used to launch instances. Required when C(state=present) and creating new ECS instances.
|
||||||
- Required when I(state=present) and creating new ECS instances.
|
|
||||||
aliases: ['type']
|
aliases: ['type']
|
||||||
type: str
|
type: str
|
||||||
security_groups:
|
security_groups:
|
||||||
description:
|
description:
|
||||||
- A list of security group IDs.
|
- A list of security group IDs.
|
||||||
|
aliases: ['group_ids']
|
||||||
type: list
|
type: list
|
||||||
|
elements: str
|
||||||
vswitch_id:
|
vswitch_id:
|
||||||
description:
|
description:
|
||||||
- The subnet ID in which to launch the instances (VPC).
|
- The subnet ID in which to launch the instances (VPC).
|
||||||
|
@ -69,53 +70,57 @@ options:
|
||||||
type: str
|
type: str
|
||||||
instance_name:
|
instance_name:
|
||||||
description:
|
description:
|
||||||
- The name of ECS instance, which is a string of 2 to 128 Chinese or English characters.
|
- The name of ECS instance, which is a string of 2 to 128 Chinese or English characters. It must begin with an
|
||||||
- It must begin with an uppercase/lowercase letter or a Chinese character and
|
uppercase/lowercase letter or a Chinese character and can contain numerals, ".", "_" or "-".
|
||||||
can contain numerals, ".", "_" or "-". It cannot begin with http:// or https://.
|
It cannot begin with http:// or https://.
|
||||||
aliases: ['name']
|
aliases: ['name']
|
||||||
type: str
|
type: str
|
||||||
description:
|
description:
|
||||||
description:
|
description:
|
||||||
- The description of ECS instance, which is a string of 2 to 256 characters.
|
- The description of ECS instance, which is a string of 2 to 256 characters. It cannot begin with http:// or https://.
|
||||||
- It cannot begin with http:// or https://.
|
|
||||||
type: str
|
type: str
|
||||||
internet_charge_type:
|
internet_charge_type:
|
||||||
description:
|
description:
|
||||||
- Internet charge type of ECS instance.
|
- Internet charge type of ECS instance.
|
||||||
type: str
|
|
||||||
default: 'PayByBandwidth'
|
default: 'PayByBandwidth'
|
||||||
choices: ['PayByBandwidth', 'PayByTraffic']
|
choices: ['PayByBandwidth', 'PayByTraffic']
|
||||||
|
type: str
|
||||||
max_bandwidth_in:
|
max_bandwidth_in:
|
||||||
description:
|
description:
|
||||||
- Maximum incoming bandwidth from the public network,
|
- Maximum incoming bandwidth from the public network, measured in Mbps (Megabits per second).
|
||||||
measured in Mbps (Megabits per second).
|
|
||||||
default: 200
|
default: 200
|
||||||
type: int
|
type: int
|
||||||
max_bandwidth_out:
|
max_bandwidth_out:
|
||||||
description:
|
description:
|
||||||
- Maximum outgoing bandwidth to the public network, measured in Mbps (Megabits per second).
|
- Maximum outgoing bandwidth to the public network, measured in Mbps (Megabits per second).
|
||||||
type: int
|
Required when C(allocate_public_ip=True). Ignored when C(allocate_public_ip=False).
|
||||||
default: 0
|
default: 0
|
||||||
|
type: int
|
||||||
host_name:
|
host_name:
|
||||||
description:
|
description:
|
||||||
- Instance host name.
|
- Instance host name. Ordered hostname is not supported.
|
||||||
type: str
|
type: str
|
||||||
|
unique_suffix:
|
||||||
|
description:
|
||||||
|
- Specifies whether to add sequential suffixes to the host_name.
|
||||||
|
The sequential suffix ranges from 001 to 999.
|
||||||
|
default: False
|
||||||
|
type: bool
|
||||||
password:
|
password:
|
||||||
description:
|
description:
|
||||||
- The password to login instance.
|
- The password to login instance. After rebooting instances, modified password will take effect.
|
||||||
- After rebooting instances, modified password will take effect.
|
|
||||||
type: str
|
type: str
|
||||||
system_disk_category:
|
system_disk_category:
|
||||||
description:
|
description:
|
||||||
- Category of the system disk.
|
- Category of the system disk.
|
||||||
type: str
|
|
||||||
default: 'cloud_efficiency'
|
default: 'cloud_efficiency'
|
||||||
choices: ['cloud_efficiency', 'cloud_ssd']
|
choices: ['cloud_efficiency', 'cloud_ssd']
|
||||||
|
type: str
|
||||||
system_disk_size:
|
system_disk_size:
|
||||||
description:
|
description:
|
||||||
- Size of the system disk, in GB. The valid values are 40~500.
|
- Size of the system disk, in GB. The valid values are 40~500.
|
||||||
type: int
|
|
||||||
default: 40
|
default: 40
|
||||||
|
type: int
|
||||||
system_disk_name:
|
system_disk_name:
|
||||||
description:
|
description:
|
||||||
- Name of the system disk.
|
- Name of the system disk.
|
||||||
|
@ -126,37 +131,35 @@ options:
|
||||||
type: str
|
type: str
|
||||||
count:
|
count:
|
||||||
description:
|
description:
|
||||||
- The number of the new instance.
|
- The number of the new instance. An integer value which indicates how many instances that match I(count_tag)
|
||||||
- Indicates how many instances that match I(count_tag) should be running.
|
should be running. Instances are either created or terminated based on this value.
|
||||||
- Instances are either created or terminated based on this value.
|
|
||||||
type: int
|
|
||||||
default: 1
|
default: 1
|
||||||
|
type: int
|
||||||
count_tag:
|
count_tag:
|
||||||
description:
|
description:
|
||||||
- Determines how many instances based on a specific tag criteria should be present.
|
- I(count) determines how many instances based on a specific tag criteria should be present.
|
||||||
- This can be expressed in multiple ways and is shown in the EXAMPLES section.
|
This can be expressed in multiple ways and is shown in the EXAMPLES section.
|
||||||
- The specified count_tag must already exist or be passed in as the I(instance_tags) option.
|
The specified count_tag must already exist or be passed in as the I(tags) option.
|
||||||
- If it is not specified, it will be replaced by I(instance_name).
|
If it is not specified, it will be replaced by I(instance_name).
|
||||||
type: str
|
type: str
|
||||||
allocate_public_ip:
|
allocate_public_ip:
|
||||||
description:
|
description:
|
||||||
- Whether allocate a public ip for the new instance.
|
- Whether allocate a public ip for the new instance.
|
||||||
default: False
|
default: False
|
||||||
aliases: ['assign_public_ip']
|
aliases: [ 'assign_public_ip' ]
|
||||||
type: bool
|
type: bool
|
||||||
instance_charge_type:
|
instance_charge_type:
|
||||||
description:
|
description:
|
||||||
- The charge type of the instance.
|
- The charge type of the instance.
|
||||||
type: str
|
|
||||||
choices: ['PrePaid', 'PostPaid']
|
choices: ['PrePaid', 'PostPaid']
|
||||||
default: 'PostPaid'
|
default: 'PostPaid'
|
||||||
|
type: str
|
||||||
period:
|
period:
|
||||||
description:
|
description:
|
||||||
- The charge duration of the instance, in month.
|
- The charge duration of the instance, in month. Required when C(instance_charge_type=PrePaid).
|
||||||
- Required when I(instance_charge_type=PrePaid).
|
|
||||||
- The valid value are [1-9, 12, 24, 36].
|
- The valid value are [1-9, 12, 24, 36].
|
||||||
type: int
|
|
||||||
default: 1
|
default: 1
|
||||||
|
type: int
|
||||||
auto_renew:
|
auto_renew:
|
||||||
description:
|
description:
|
||||||
- Whether automate renew the charge of the instance.
|
- Whether automate renew the charge of the instance.
|
||||||
|
@ -164,31 +167,36 @@ options:
|
||||||
default: False
|
default: False
|
||||||
auto_renew_period:
|
auto_renew_period:
|
||||||
description:
|
description:
|
||||||
- The duration of the automatic renew the charge of the instance.
|
- The duration of the automatic renew the charge of the instance. Required when C(auto_renew=True).
|
||||||
- Required when I(auto_renew=True).
|
|
||||||
type: int
|
|
||||||
choices: [1, 2, 3, 6, 12]
|
choices: [1, 2, 3, 6, 12]
|
||||||
|
type: int
|
||||||
instance_ids:
|
instance_ids:
|
||||||
description:
|
description:
|
||||||
- A list of instance ids. It is required when need to operate existing instances.
|
- A list of instance ids. It is required when need to operate existing instances.
|
||||||
- If it is specified, I(count) will lose efficacy.
|
If it is specified, I(count) will lose efficacy.
|
||||||
type: list
|
type: list
|
||||||
|
elements: str
|
||||||
force:
|
force:
|
||||||
description:
|
description:
|
||||||
- Whether the current operation needs to be execute forcibly.
|
- Whether the current operation needs to be execute forcibly.
|
||||||
default: False
|
default: False
|
||||||
type: bool
|
type: bool
|
||||||
instance_tags:
|
tags:
|
||||||
description:
|
description:
|
||||||
- A hash/dictionaries of instance tags, to add to the new instance or
|
- A hash/dictionaries of instance tags, to add to the new instance or for starting/stopping instance by tag. C({"key":"value"})
|
||||||
for starting/stopping instance by tag (C({"key":"value"})).
|
aliases: ["instance_tags"]
|
||||||
aliases: ['tags']
|
|
||||||
type: dict
|
type: dict
|
||||||
|
purge_tags:
|
||||||
|
description:
|
||||||
|
- Delete any tags not specified in the task that are on the instance.
|
||||||
|
If True, it means you have to specify all the desired tags on each task affecting an instance.
|
||||||
|
default: False
|
||||||
|
type: bool
|
||||||
key_name:
|
key_name:
|
||||||
description:
|
description:
|
||||||
- The name of key pair which is used to access ECS instance in SSH.
|
- The name of key pair which is used to access ECS instance in SSH.
|
||||||
type: str
|
|
||||||
required: false
|
required: false
|
||||||
|
type: str
|
||||||
aliases: ['keypair']
|
aliases: ['keypair']
|
||||||
user_data:
|
user_data:
|
||||||
description:
|
description:
|
||||||
|
@ -196,17 +204,51 @@ options:
|
||||||
It only will take effect when launching the new ECS instances.
|
It only will take effect when launching the new ECS instances.
|
||||||
required: false
|
required: false
|
||||||
type: str
|
type: str
|
||||||
|
ram_role_name:
|
||||||
|
description:
|
||||||
|
- The name of the instance RAM role.
|
||||||
|
type: str
|
||||||
|
spot_price_limit:
|
||||||
|
description:
|
||||||
|
- The maximum hourly price for the preemptible instance. This parameter supports a maximum of three decimal
|
||||||
|
places and takes effect when the SpotStrategy parameter is set to SpotWithPriceLimit.
|
||||||
|
type: float
|
||||||
|
spot_strategy:
|
||||||
|
description:
|
||||||
|
- The bidding mode of the pay-as-you-go instance. This parameter is valid when InstanceChargeType is set to PostPaid.
|
||||||
|
choices: ['NoSpot', 'SpotWithPriceLimit', 'SpotAsPriceGo']
|
||||||
|
default: 'NoSpot'
|
||||||
|
type: str
|
||||||
|
period_unit:
|
||||||
|
description:
|
||||||
|
- The duration unit that you will buy the resource. It is valid when C(instance_charge_type=PrePaid)
|
||||||
|
choices: ['Month', 'Week']
|
||||||
|
default: 'Month'
|
||||||
|
type: str
|
||||||
|
dry_run:
|
||||||
|
description:
|
||||||
|
- Specifies whether to send a dry-run request.
|
||||||
|
- If I(dry_run=True), Only a dry-run request is sent and no instance is created. The system checks whether the
|
||||||
|
required parameters are set, and validates the request format, service permissions, and available ECS instances.
|
||||||
|
If the validation fails, the corresponding error code is returned. If the validation succeeds, the DryRunOperation error code is returned.
|
||||||
|
- If I(dry_run=False), A request is sent. If the validation succeeds, the instance is created.
|
||||||
|
default: False
|
||||||
|
type: bool
|
||||||
|
include_data_disks:
|
||||||
|
description:
|
||||||
|
- Whether to change instance disks charge type when changing instance charge type.
|
||||||
|
default: True
|
||||||
|
type: bool
|
||||||
author:
|
author:
|
||||||
- "He Guimin (@xiaozhu36)"
|
- "He Guimin (@xiaozhu36)"
|
||||||
requirements:
|
requirements:
|
||||||
- "python >= 2.6"
|
- "python >= 3.6"
|
||||||
- "footmark >= 1.1.16"
|
- "footmark >= 1.19.0"
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.general.alicloud
|
- community.general.alicloud
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = r'''
|
EXAMPLES = '''
|
||||||
# basic provisioning example vpc network
|
# basic provisioning example vpc network
|
||||||
- name: basic provisioning example
|
- name: basic provisioning example
|
||||||
hosts: localhost
|
hosts: localhost
|
||||||
|
@ -243,7 +285,7 @@ EXAMPLES = r'''
|
||||||
assign_public_ip: '{{ assign_public_ip }}'
|
assign_public_ip: '{{ assign_public_ip }}'
|
||||||
internet_charge_type: '{{ internet_charge_type }}'
|
internet_charge_type: '{{ internet_charge_type }}'
|
||||||
max_bandwidth_out: '{{ max_bandwidth_out }}'
|
max_bandwidth_out: '{{ max_bandwidth_out }}'
|
||||||
instance_tags:
|
tags:
|
||||||
Name: created_one
|
Name: created_one
|
||||||
host_name: '{{ host_name }}'
|
host_name: '{{ host_name }}'
|
||||||
password: '{{ password }}'
|
password: '{{ password }}'
|
||||||
|
@ -261,7 +303,7 @@ EXAMPLES = r'''
|
||||||
security_groups: '{{ security_groups }}'
|
security_groups: '{{ security_groups }}'
|
||||||
internet_charge_type: '{{ internet_charge_type }}'
|
internet_charge_type: '{{ internet_charge_type }}'
|
||||||
max_bandwidth_out: '{{ max_bandwidth_out }}'
|
max_bandwidth_out: '{{ max_bandwidth_out }}'
|
||||||
instance_tags:
|
tags:
|
||||||
Name: created_one
|
Name: created_one
|
||||||
Version: 0.1
|
Version: 0.1
|
||||||
count: 2
|
count: 2
|
||||||
|
@ -296,9 +338,9 @@ EXAMPLES = r'''
|
||||||
security_groups: '{{ security_groups }}'
|
security_groups: '{{ security_groups }}'
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = r'''
|
RETURN = '''
|
||||||
instances:
|
instances:
|
||||||
description: List of ECS instances.
|
description: List of ECS instances
|
||||||
returned: always
|
returned: always
|
||||||
type: complex
|
type: complex
|
||||||
contains:
|
contains:
|
||||||
|
@ -432,6 +474,11 @@ instances:
|
||||||
returned: always
|
returned: always
|
||||||
type: str
|
type: str
|
||||||
sample: ecs.sn1ne.xlarge
|
sample: ecs.sn1ne.xlarge
|
||||||
|
instance_type_family:
|
||||||
|
description: The instance type family of the instance belongs.
|
||||||
|
returned: always
|
||||||
|
type: str
|
||||||
|
sample: ecs.sn1ne
|
||||||
internet_charge_type:
|
internet_charge_type:
|
||||||
description: The billing method of the network bandwidth.
|
description: The billing method of the network bandwidth.
|
||||||
returned: always
|
returned: always
|
||||||
|
@ -493,7 +540,7 @@ instances:
|
||||||
type: str
|
type: str
|
||||||
sample: 10.0.0.1
|
sample: 10.0.0.1
|
||||||
public_ip_address:
|
public_ip_address:
|
||||||
description: The public IPv4 address assigned to the instance.
|
description: The public IPv4 address assigned to the instance or eip address
|
||||||
returned: always
|
returned: always
|
||||||
type: str
|
type: str
|
||||||
sample: 43.0.0.1
|
sample: 43.0.0.1
|
||||||
|
@ -528,6 +575,11 @@ instances:
|
||||||
returned: always
|
returned: always
|
||||||
type: dict
|
type: dict
|
||||||
sample:
|
sample:
|
||||||
|
user_data:
|
||||||
|
description: User-defined data.
|
||||||
|
returned: always
|
||||||
|
type: dict
|
||||||
|
sample:
|
||||||
vswitch_id:
|
vswitch_id:
|
||||||
description: The ID of the vswitch in which the instance is running.
|
description: The ID of the vswitch in which the instance is running.
|
||||||
returned: always
|
returned: always
|
||||||
|
@ -536,15 +588,28 @@ instances:
|
||||||
vpc_id:
|
vpc_id:
|
||||||
description: The ID of the VPC the instance is in.
|
description: The ID of the VPC the instance is in.
|
||||||
returned: always
|
returned: always
|
||||||
type: dict
|
type: str
|
||||||
sample: vpc-0011223344
|
sample: vpc-0011223344
|
||||||
|
spot_price_limit:
|
||||||
|
description:
|
||||||
|
- The maximum hourly price for the preemptible instance.
|
||||||
|
returned: always
|
||||||
|
type: float
|
||||||
|
sample: 0.97
|
||||||
|
spot_strategy:
|
||||||
|
description:
|
||||||
|
- The bidding mode of the pay-as-you-go instance.
|
||||||
|
returned: always
|
||||||
|
type: str
|
||||||
|
sample: NoSpot
|
||||||
ids:
|
ids:
|
||||||
description: List of ECS instance IDs.
|
description: List of ECS instance IDs
|
||||||
returned: always
|
returned: always
|
||||||
type: list
|
type: list
|
||||||
sample: [i-12345er, i-3245fs]
|
sample: [i-12345er, i-3245fs]
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
|
@ -562,14 +627,17 @@ except ImportError:
|
||||||
|
|
||||||
def get_instances_info(connection, ids):
|
def get_instances_info(connection, ids):
|
||||||
result = []
|
result = []
|
||||||
instances = connection.get_all_instances(instance_ids=ids)
|
instances = connection.describe_instances(instance_ids=ids)
|
||||||
if len(instances) > 0:
|
if len(instances) > 0:
|
||||||
for inst in instances:
|
for inst in instances:
|
||||||
|
volumes = connection.describe_disks(instance_id=inst.id)
|
||||||
|
setattr(inst, 'block_device_mappings', volumes)
|
||||||
|
setattr(inst, 'user_data', inst.describe_user_data())
|
||||||
result.append(inst.read())
|
result.append(inst.read())
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def create_instance(module, ecs, exact_count):
|
def run_instance(module, ecs, exact_count):
|
||||||
if exact_count <= 0:
|
if exact_count <= 0:
|
||||||
return None
|
return None
|
||||||
zone_id = module.params['availability_zone']
|
zone_id = module.params['availability_zone']
|
||||||
|
@ -581,7 +649,7 @@ def create_instance(module, ecs, exact_count):
|
||||||
description = module.params['description']
|
description = module.params['description']
|
||||||
internet_charge_type = module.params['internet_charge_type']
|
internet_charge_type = module.params['internet_charge_type']
|
||||||
max_bandwidth_out = module.params['max_bandwidth_out']
|
max_bandwidth_out = module.params['max_bandwidth_out']
|
||||||
max_bandwidth_in = module.params['max_bandwidth_out']
|
max_bandwidth_in = module.params['max_bandwidth_in']
|
||||||
host_name = module.params['host_name']
|
host_name = module.params['host_name']
|
||||||
password = module.params['password']
|
password = module.params['password']
|
||||||
system_disk_category = module.params['system_disk_category']
|
system_disk_category = module.params['system_disk_category']
|
||||||
|
@ -589,14 +657,16 @@ def create_instance(module, ecs, exact_count):
|
||||||
system_disk_name = module.params['system_disk_name']
|
system_disk_name = module.params['system_disk_name']
|
||||||
system_disk_description = module.params['system_disk_description']
|
system_disk_description = module.params['system_disk_description']
|
||||||
allocate_public_ip = module.params['allocate_public_ip']
|
allocate_public_ip = module.params['allocate_public_ip']
|
||||||
instance_tags = module.params['instance_tags']
|
|
||||||
period = module.params['period']
|
period = module.params['period']
|
||||||
auto_renew = module.params['auto_renew']
|
auto_renew = module.params['auto_renew']
|
||||||
instance_charge_type = module.params['instance_charge_type']
|
instance_charge_type = module.params['instance_charge_type']
|
||||||
auto_renew_period = module.params['auto_renew_period']
|
auto_renew_period = module.params['auto_renew_period']
|
||||||
user_data = module.params['user_data']
|
user_data = module.params['user_data']
|
||||||
key_name = module.params['key_name']
|
key_name = module.params['key_name']
|
||||||
|
ram_role_name = module.params['ram_role_name']
|
||||||
|
spot_price_limit = module.params['spot_price_limit']
|
||||||
|
spot_strategy = module.params['spot_strategy']
|
||||||
|
unique_suffix = module.params['unique_suffix']
|
||||||
# check whether the required parameter passed or not
|
# check whether the required parameter passed or not
|
||||||
if not image_id:
|
if not image_id:
|
||||||
module.fail_json(msg='image_id is required for new instance')
|
module.fail_json(msg='image_id is required for new instance')
|
||||||
|
@ -611,17 +681,17 @@ def create_instance(module, ecs, exact_count):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# call to create_instance method from footmark
|
# call to create_instance method from footmark
|
||||||
instances = ecs.create_instance(image_id=image_id, instance_type=instance_type, security_group_id=security_groups[0],
|
instances = ecs.run_instances(image_id=image_id, instance_type=instance_type, security_group_id=security_groups[0],
|
||||||
zone_id=zone_id, instance_name=instance_name, description=description,
|
zone_id=zone_id, instance_name=instance_name, description=description,
|
||||||
internet_charge_type=internet_charge_type, max_bandwidth_out=max_bandwidth_out,
|
internet_charge_type=internet_charge_type, internet_max_bandwidth_out=max_bandwidth_out,
|
||||||
max_bandwidth_in=max_bandwidth_in, host_name=host_name, password=password,
|
internet_max_bandwidth_in=max_bandwidth_in, host_name=host_name, password=password,
|
||||||
io_optimized='optimized', system_disk_category=system_disk_category,
|
io_optimized='optimized', system_disk_category=system_disk_category,
|
||||||
system_disk_size=system_disk_size, system_disk_name=system_disk_name,
|
system_disk_size=system_disk_size, system_disk_disk_name=system_disk_name,
|
||||||
system_disk_description=system_disk_description,
|
system_disk_description=system_disk_description, vswitch_id=vswitch_id,
|
||||||
vswitch_id=vswitch_id, count=exact_count, allocate_public_ip=allocate_public_ip,
|
amount=exact_count, instance_charge_type=instance_charge_type, period=period, period_unit="Month",
|
||||||
instance_charge_type=instance_charge_type, period=period, auto_renew=auto_renew,
|
auto_renew=auto_renew, auto_renew_period=auto_renew_period, key_pair_name=key_name,
|
||||||
auto_renew_period=auto_renew_period, instance_tags=instance_tags,
|
user_data=user_data, client_token=client_token, ram_role_name=ram_role_name,
|
||||||
key_pair_name=key_name, user_data=user_data, client_token=client_token)
|
spot_price_limit=spot_price_limit, spot_strategy=spot_strategy, unique_suffix=unique_suffix)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
module.fail_json(msg='Unable to create instance, error: {0}'.format(e))
|
module.fail_json(msg='Unable to create instance, error: {0}'.format(e))
|
||||||
|
@ -629,11 +699,69 @@ def create_instance(module, ecs, exact_count):
|
||||||
return instances
|
return instances
|
||||||
|
|
||||||
|
|
||||||
|
def modify_instance(module, instance):
|
||||||
|
# According to state to modify instance's some special attribute
|
||||||
|
state = module.params["state"]
|
||||||
|
name = module.params['instance_name']
|
||||||
|
unique_suffix = module.params['unique_suffix']
|
||||||
|
if not name:
|
||||||
|
name = instance.name
|
||||||
|
|
||||||
|
description = module.params['description']
|
||||||
|
if not description:
|
||||||
|
description = instance.description
|
||||||
|
|
||||||
|
host_name = module.params['host_name']
|
||||||
|
if unique_suffix and host_name:
|
||||||
|
suffix = instance.host_name[-3:]
|
||||||
|
host_name = host_name + suffix
|
||||||
|
|
||||||
|
if not host_name:
|
||||||
|
host_name = instance.host_name
|
||||||
|
|
||||||
|
# password can be modified only when restart instance
|
||||||
|
password = ""
|
||||||
|
if state == "restarted":
|
||||||
|
password = module.params['password']
|
||||||
|
|
||||||
|
# userdata can be modified only when instance is stopped
|
||||||
|
setattr(instance, "user_data", instance.describe_user_data())
|
||||||
|
user_data = instance.user_data
|
||||||
|
if state == "stopped":
|
||||||
|
user_data = module.params['user_data'].encode()
|
||||||
|
|
||||||
|
try:
|
||||||
|
return instance.modify(name=name, description=description, host_name=host_name, password=password, user_data=user_data)
|
||||||
|
except Exception as e:
|
||||||
|
module.fail_json(msg="Modify instance {0} attribute got an error: {1}".format(instance.id, e))
|
||||||
|
|
||||||
|
|
||||||
|
def wait_for_instance_modify_charge(ecs, instance_ids, charge_type, delay=10, timeout=300):
|
||||||
|
"""
|
||||||
|
To verify instance charge type has become expected after modify instance charge type
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
instances = ecs.describe_instances(instance_ids=instance_ids)
|
||||||
|
flag = True
|
||||||
|
for inst in instances:
|
||||||
|
if inst and inst.instance_charge_type != charge_type:
|
||||||
|
flag = False
|
||||||
|
if flag:
|
||||||
|
return
|
||||||
|
timeout -= delay
|
||||||
|
time.sleep(delay)
|
||||||
|
if timeout <= 0:
|
||||||
|
raise Exception("Timeout Error: Waiting for instance to {0}. ".format(charge_type))
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argument_spec = ecs_argument_spec()
|
argument_spec = ecs_argument_spec()
|
||||||
argument_spec.update(dict(
|
argument_spec.update(dict(
|
||||||
security_groups=dict(type='list'),
|
security_groups=dict(type='list', elements='str', aliases=['group_ids']),
|
||||||
availability_zone=dict(type='str', aliases=['alicloud_zone']),
|
availability_zone=dict(type='str', aliases=['alicloud_zone', 'zone_id']),
|
||||||
instance_type=dict(type='str', aliases=['type']),
|
instance_type=dict(type='str', aliases=['type']),
|
||||||
image_id=dict(type='str', aliases=['image']),
|
image_id=dict(type='str', aliases=['image']),
|
||||||
count=dict(type='int', default=1),
|
count=dict(type='int', default=1),
|
||||||
|
@ -650,17 +778,25 @@ def main():
|
||||||
system_disk_name=dict(type='str'),
|
system_disk_name=dict(type='str'),
|
||||||
system_disk_description=dict(type='str'),
|
system_disk_description=dict(type='str'),
|
||||||
force=dict(type='bool', default=False),
|
force=dict(type='bool', default=False),
|
||||||
instance_tags=dict(type='dict', aliases=['tags']),
|
tags=dict(type='dict', aliases=['instance_tags']),
|
||||||
|
purge_tags=dict(type='bool', default=False),
|
||||||
state=dict(default='present', choices=['present', 'running', 'stopped', 'restarted', 'absent']),
|
state=dict(default='present', choices=['present', 'running', 'stopped', 'restarted', 'absent']),
|
||||||
description=dict(type='str'),
|
description=dict(type='str'),
|
||||||
allocate_public_ip=dict(type='bool', aliases=['assign_public_ip'], default=False),
|
allocate_public_ip=dict(type='bool', aliases=['assign_public_ip'], default=False),
|
||||||
instance_charge_type=dict(type='str', default='PostPaid', choices=['PrePaid', 'PostPaid']),
|
instance_charge_type=dict(type='str', default='PostPaid', choices=['PrePaid', 'PostPaid']),
|
||||||
period=dict(type='int', default=1),
|
period=dict(type='int', default=1),
|
||||||
auto_renew=dict(type='bool', default=False),
|
auto_renew=dict(type='bool', default=False),
|
||||||
instance_ids=dict(type='list'),
|
instance_ids=dict(type='list', elements='str'),
|
||||||
auto_renew_period=dict(type='int', choices=[1, 2, 3, 6, 12]),
|
auto_renew_period=dict(type='int', choices=[1, 2, 3, 6, 12]),
|
||||||
key_name=dict(type='str', aliases=['keypair']),
|
key_name=dict(type='str', aliases=['keypair']),
|
||||||
user_data=dict(type='str')
|
user_data=dict(type='str'),
|
||||||
|
ram_role_name=dict(type='str'),
|
||||||
|
spot_price_limit=dict(type='float'),
|
||||||
|
spot_strategy=dict(type='str', default='NoSpot', choices=['NoSpot', 'SpotWithPriceLimit', 'SpotAsPriceGo']),
|
||||||
|
unique_suffix=dict(type='bool', default=False),
|
||||||
|
period_unit=dict(type='str', default='Month', choices=['Month', 'Week']),
|
||||||
|
dry_run=dict(type='bool', default=False),
|
||||||
|
include_data_disks=dict(type='bool', default=True)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
module = AnsibleModule(argument_spec=argument_spec)
|
module = AnsibleModule(argument_spec=argument_spec)
|
||||||
|
@ -669,6 +805,7 @@ def main():
|
||||||
module.fail_json(msg=missing_required_lib('footmark'), exception=FOOTMARK_IMP_ERR)
|
module.fail_json(msg=missing_required_lib('footmark'), exception=FOOTMARK_IMP_ERR)
|
||||||
|
|
||||||
ecs = ecs_connect(module)
|
ecs = ecs_connect(module)
|
||||||
|
host_name = module.params['host_name']
|
||||||
state = module.params['state']
|
state = module.params['state']
|
||||||
instance_ids = module.params['instance_ids']
|
instance_ids = module.params['instance_ids']
|
||||||
count_tag = module.params['count_tag']
|
count_tag = module.params['count_tag']
|
||||||
|
@ -677,22 +814,50 @@ def main():
|
||||||
force = module.params['force']
|
force = module.params['force']
|
||||||
zone_id = module.params['availability_zone']
|
zone_id = module.params['availability_zone']
|
||||||
key_name = module.params['key_name']
|
key_name = module.params['key_name']
|
||||||
|
tags = module.params['tags']
|
||||||
|
max_bandwidth_out = module.params['max_bandwidth_out']
|
||||||
|
instance_charge_type = module.params['instance_charge_type']
|
||||||
|
if instance_charge_type == "PrePaid":
|
||||||
|
module.params['spot_strategy'] = ''
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
instances = []
|
instances = []
|
||||||
if instance_ids:
|
if instance_ids:
|
||||||
if not isinstance(instance_ids, list):
|
if not isinstance(instance_ids, list):
|
||||||
module.fail_json(msg='The parameter instance_ids should be a list, aborting')
|
module.fail_json(msg='The parameter instance_ids should be a list, aborting')
|
||||||
instances = ecs.get_all_instances(zone_id=zone_id, instance_ids=instance_ids)
|
instances = ecs.describe_instances(zone_id=zone_id, instance_ids=instance_ids)
|
||||||
if not instances:
|
if not instances:
|
||||||
module.fail_json(msg="There are no instances in our record based on instance_ids {0}. "
|
module.fail_json(msg="There are no instances in our record based on instance_ids {0}. "
|
||||||
"Please check it and try again.".format(instance_ids))
|
"Please check it and try again.".format(instance_ids))
|
||||||
elif count_tag:
|
elif count_tag:
|
||||||
instances = ecs.get_all_instances(zone_id=zone_id, instance_tags=eval(count_tag))
|
instances = ecs.describe_instances(zone_id=zone_id, tags=eval(count_tag))
|
||||||
elif instance_name:
|
elif instance_name:
|
||||||
instances = ecs.get_all_instances(zone_id=zone_id, instance_name=instance_name)
|
instances = ecs.describe_instances(zone_id=zone_id, instance_name=instance_name)
|
||||||
|
|
||||||
ids = []
|
ids = []
|
||||||
|
if state == 'absent':
|
||||||
|
if len(instances) < 1:
|
||||||
|
module.fail_json(msg='Please specify ECS instances that you want to operate by using '
|
||||||
|
'parameters instance_ids, tags or instance_name, aborting')
|
||||||
|
try:
|
||||||
|
targets = []
|
||||||
|
for inst in instances:
|
||||||
|
if inst.status != 'stopped' and not force:
|
||||||
|
module.fail_json(msg="Instance is running, and please stop it or set 'force' as True.")
|
||||||
|
targets.append(inst.id)
|
||||||
|
if ecs.delete_instances(instance_ids=targets, force=force):
|
||||||
|
changed = True
|
||||||
|
ids.extend(targets)
|
||||||
|
|
||||||
|
module.exit_json(changed=changed, ids=ids, instances=[])
|
||||||
|
except Exception as e:
|
||||||
|
module.fail_json(msg='Delete instance got an error: {0}'.format(e))
|
||||||
|
|
||||||
|
if module.params['allocate_public_ip'] and max_bandwidth_out < 0:
|
||||||
|
module.fail_json(msg="'max_bandwidth_out' should be greater than 0 when 'allocate_public_ip' is True.")
|
||||||
|
if not module.params['allocate_public_ip']:
|
||||||
|
module.params['max_bandwidth_out'] = 0
|
||||||
|
|
||||||
if state == 'present':
|
if state == 'present':
|
||||||
if not instance_ids:
|
if not instance_ids:
|
||||||
if len(instances) > count:
|
if len(instances) > count:
|
||||||
|
@ -702,13 +867,17 @@ def main():
|
||||||
module.fail_json(msg="That to delete instance {0} is failed results from it is running, "
|
module.fail_json(msg="That to delete instance {0} is failed results from it is running, "
|
||||||
"and please stop it or set 'force' as True.".format(inst.id))
|
"and please stop it or set 'force' as True.".format(inst.id))
|
||||||
try:
|
try:
|
||||||
changed = inst.terminate(force=force)
|
if inst.terminate(force=force):
|
||||||
|
changed = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
module.fail_json(msg="Delete instance {0} got an error: {1}".format(inst.id, e))
|
module.fail_json(msg="Delete instance {0} got an error: {1}".format(inst.id, e))
|
||||||
instances.pop(len(instances) - 1)
|
instances.pop(len(instances) - 1)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
new_instances = create_instance(module, ecs, count - len(instances))
|
if re.search(r"-\[\d+,\d+\]-", host_name):
|
||||||
|
module.fail_json(msg='Ordered hostname is not supported, If you want to add an ordered '
|
||||||
|
'suffix to the hostname, you can set unique_suffix to True')
|
||||||
|
new_instances = run_instance(module, ecs, count - len(instances))
|
||||||
if new_instances:
|
if new_instances:
|
||||||
changed = True
|
changed = True
|
||||||
instances.extend(new_instances)
|
instances.extend(new_instances)
|
||||||
|
@ -717,9 +886,9 @@ def main():
|
||||||
|
|
||||||
# Security Group join/leave begin
|
# Security Group join/leave begin
|
||||||
security_groups = module.params['security_groups']
|
security_groups = module.params['security_groups']
|
||||||
|
if security_groups:
|
||||||
if not isinstance(security_groups, list):
|
if not isinstance(security_groups, list):
|
||||||
module.fail_json(msg='The parameter security_groups should be a list, aborting')
|
module.fail_json(msg='The parameter security_groups should be a list, aborting')
|
||||||
if len(security_groups) > 0:
|
|
||||||
for inst in instances:
|
for inst in instances:
|
||||||
existing = inst.security_group_ids['security_group_id']
|
existing = inst.security_group_ids['security_group_id']
|
||||||
remove = list(set(existing).difference(set(security_groups)))
|
remove = list(set(existing).difference(set(security_groups)))
|
||||||
|
@ -737,80 +906,102 @@ def main():
|
||||||
for inst in instances:
|
for inst in instances:
|
||||||
if key_name is not None and key_name != inst.key_name:
|
if key_name is not None and key_name != inst.key_name:
|
||||||
if key_name == "":
|
if key_name == "":
|
||||||
changed = inst.detach_key_pair()
|
if inst.detach_key_pair():
|
||||||
|
changed = True
|
||||||
else:
|
else:
|
||||||
inst_ids.append(inst.id)
|
inst_ids.append(inst.id)
|
||||||
if inst_ids:
|
if inst_ids:
|
||||||
changed = ecs.attach_key_pair(instance_ids=inst_ids, key_pair_name=key_name)
|
changed = ecs.attach_key_pair(instance_ids=inst_ids, key_pair_name=key_name)
|
||||||
|
|
||||||
# Modify instance attribute
|
# Modify instance attribute
|
||||||
description = module.params['description']
|
|
||||||
host_name = module.params['host_name']
|
|
||||||
password = module.params['password']
|
|
||||||
for inst in instances:
|
for inst in instances:
|
||||||
if not instance_name:
|
if modify_instance(module, inst):
|
||||||
instance_name = inst.name
|
|
||||||
if not description:
|
|
||||||
description = inst.description
|
|
||||||
if not host_name:
|
|
||||||
host_name = inst.host_name
|
|
||||||
try:
|
|
||||||
if inst.modify(name=instance_name, description=description, host_name=host_name, password=password):
|
|
||||||
changed = True
|
changed = True
|
||||||
except Exception as e:
|
|
||||||
module.fail_json(msg="Modify instance attribute {0} got an error: {1}".format(inst.id, e))
|
|
||||||
|
|
||||||
if inst.id not in ids:
|
if inst.id not in ids:
|
||||||
ids.append(inst.id)
|
ids.append(inst.id)
|
||||||
|
|
||||||
module.exit_json(changed=changed, ids=ids, instances=get_instances_info(ecs, ids))
|
# Modify instance charge type
|
||||||
|
ids = []
|
||||||
|
for inst in instances:
|
||||||
|
if inst.instance_charge_type != instance_charge_type:
|
||||||
|
ids.append(inst.id)
|
||||||
|
if ids:
|
||||||
|
params = {"instance_ids": ids, "instance_charge_type": instance_charge_type,
|
||||||
|
"include_data_disks": module.params['include_data_disks'], "dry_run": module.params['dry_run'],
|
||||||
|
"auto_pay": True}
|
||||||
|
if instance_charge_type == 'PrePaid':
|
||||||
|
params['period'] = module.params['period']
|
||||||
|
params['period_unit'] = module.params['period_unit']
|
||||||
|
|
||||||
|
if ecs.modify_instance_charge_type(**params):
|
||||||
|
changed = True
|
||||||
|
wait_for_instance_modify_charge(ecs, ids, instance_charge_type)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if len(instances) < 1:
|
if len(instances) < 1:
|
||||||
module.fail_json(msg='Please specify ECS instances that you want to operate by using '
|
module.fail_json(msg='Please specify ECS instances that you want to operate by using '
|
||||||
'parameters instance_ids, instance_tags or instance_name, aborting')
|
'parameters instance_ids, tags or instance_name, aborting')
|
||||||
force = module.params['force']
|
|
||||||
if state == 'running':
|
if state == 'running':
|
||||||
try:
|
try:
|
||||||
|
targets = []
|
||||||
for inst in instances:
|
for inst in instances:
|
||||||
if inst.start():
|
if modify_instance(module, inst):
|
||||||
changed = True
|
changed = True
|
||||||
|
if inst.status != "running":
|
||||||
|
targets.append(inst.id)
|
||||||
ids.append(inst.id)
|
ids.append(inst.id)
|
||||||
|
if targets and ecs.start_instances(instance_ids=targets):
|
||||||
module.exit_json(changed=changed, ids=ids, instances=get_instances_info(ecs, ids))
|
changed = True
|
||||||
|
ids.extend(targets)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
module.fail_json(msg='Start instances got an error: {0}'.format(e))
|
module.fail_json(msg='Start instances got an error: {0}'.format(e))
|
||||||
elif state == 'stopped':
|
elif state == 'stopped':
|
||||||
try:
|
try:
|
||||||
|
targets = []
|
||||||
for inst in instances:
|
for inst in instances:
|
||||||
if inst.stop(force=force):
|
if inst.status != "stopped":
|
||||||
|
targets.append(inst.id)
|
||||||
|
if targets and ecs.stop_instances(instance_ids=targets, force_stop=force):
|
||||||
|
changed = True
|
||||||
|
ids.extend(targets)
|
||||||
|
for inst in instances:
|
||||||
|
if modify_instance(module, inst):
|
||||||
changed = True
|
changed = True
|
||||||
ids.append(inst.id)
|
|
||||||
|
|
||||||
module.exit_json(changed=changed, ids=ids, instances=get_instances_info(ecs, ids))
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
module.fail_json(msg='Stop instances got an error: {0}'.format(e))
|
module.fail_json(msg='Stop instances got an error: {0}'.format(e))
|
||||||
elif state == 'restarted':
|
elif state == 'restarted':
|
||||||
try:
|
try:
|
||||||
|
targets = []
|
||||||
for inst in instances:
|
for inst in instances:
|
||||||
if inst.reboot(force=module.params['force']):
|
if modify_instance(module, inst):
|
||||||
changed = True
|
changed = True
|
||||||
ids.append(inst.id)
|
targets.append(inst.id)
|
||||||
|
if ecs.reboot_instances(instance_ids=targets, force_stop=module.params['force']):
|
||||||
module.exit_json(changed=changed, ids=ids, instances=get_instances_info(ecs, ids))
|
changed = True
|
||||||
|
ids.extend(targets)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
module.fail_json(msg='Reboot instances got an error: {0}'.format(e))
|
module.fail_json(msg='Reboot instances got an error: {0}'.format(e))
|
||||||
else:
|
|
||||||
try:
|
|
||||||
for inst in instances:
|
|
||||||
if inst.status != 'stopped' and not force:
|
|
||||||
module.fail_json(msg="Instance is running, and please stop it or set 'force' as True.")
|
|
||||||
if inst.terminate(force=module.params['force']):
|
|
||||||
changed = True
|
|
||||||
|
|
||||||
module.exit_json(changed=changed, ids=[], instances=[])
|
tags = module.params['tags']
|
||||||
|
if module.params['purge_tags']:
|
||||||
|
for inst in instances:
|
||||||
|
if not tags:
|
||||||
|
tags = inst.tags
|
||||||
|
try:
|
||||||
|
if inst.remove_tags(tags):
|
||||||
|
changed = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
module.fail_json(msg='Delete instance got an error: {0}'.format(e))
|
module.fail_json(msg="{0}".format(e))
|
||||||
|
module.exit_json(changed=changed, instances=get_instances_info(ecs, ids))
|
||||||
|
|
||||||
|
if tags:
|
||||||
|
for inst in instances:
|
||||||
|
try:
|
||||||
|
if inst.add_tags(tags):
|
||||||
|
changed = True
|
||||||
|
except Exception as e:
|
||||||
|
module.fail_json(msg="{0}".format(e))
|
||||||
|
module.exit_json(changed=changed, instances=get_instances_info(ecs, ids))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# Copyright (c) 2017 Alibaba Group Holding Limited. He Guimin <heguimin36@163.com>
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2017-present Alibaba Group Holding Limited. He Guimin <heguimin36@163.com>
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
#
|
#
|
||||||
# This file is part of Ansible
|
# This file is part of Ansible
|
||||||
|
@ -17,7 +19,8 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Ansible. If not, see http://www.gnu.org/licenses/.
|
# along with Ansible. If not, see http://www.gnu.org/licenses/.
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
|
@ -36,68 +39,70 @@ description:
|
||||||
options:
|
options:
|
||||||
availability_zone:
|
availability_zone:
|
||||||
description:
|
description:
|
||||||
- Aliyun availability zone ID in which to launch the instance
|
- (Deprecated) Aliyun availability zone ID in which to launch the instance. Please use filter item 'zone_id' instead.
|
||||||
aliases: ['alicloud_zone']
|
aliases: ['alicloud_zone']
|
||||||
|
type: str
|
||||||
instance_names:
|
instance_names:
|
||||||
description:
|
description:
|
||||||
- A list of ECS instance names.
|
- (Deprecated) A list of ECS instance names. Please use filter item 'instance_name' instead.
|
||||||
aliases: [ "names"]
|
aliases: ["names"]
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
instance_ids:
|
instance_ids:
|
||||||
description:
|
description:
|
||||||
- A list of ECS instance ids.
|
- A list of ECS instance ids.
|
||||||
aliases: ["ids"]
|
aliases: ["ids"]
|
||||||
instance_tags:
|
type: list
|
||||||
|
elements: str
|
||||||
|
name_prefix:
|
||||||
|
description:
|
||||||
|
- Use a instance name prefix to filter ecs instances.
|
||||||
|
type: str
|
||||||
|
tags:
|
||||||
description:
|
description:
|
||||||
- A hash/dictionaries of instance tags. C({"key":"value"})
|
- A hash/dictionaries of instance tags. C({"key":"value"})
|
||||||
aliases: ["tags"]
|
aliases: ["instance_tags"]
|
||||||
|
type: dict
|
||||||
|
filters:
|
||||||
|
description:
|
||||||
|
- A dict of filters to apply. Each dict item consists of a filter key and a filter value. The filter keys can be
|
||||||
|
all of request parameters. See U(https://www.alibabacloud.com/help/doc-detail/25506.htm) for parameter details.
|
||||||
|
Filter keys can be same as request parameter name or be lower case and use underscore ("_") or dash ("-") to
|
||||||
|
connect different words in one parameter. 'InstanceIds' should be a list and it will be appended to
|
||||||
|
I(instance_ids) automatically. 'Tag.n.Key' and 'Tag.n.Value' should be a dict and using I(tags) instead.
|
||||||
|
type: dict
|
||||||
author:
|
author:
|
||||||
- "He Guimin (@xiaozhu36)"
|
- "He Guimin (@xiaozhu36)"
|
||||||
requirements:
|
requirements:
|
||||||
- "python >= 2.6"
|
- "python >= 3.6"
|
||||||
- "footmark >= 1.1.16"
|
- "footmark >= 1.13.0"
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.general.alicloud
|
- community.general.alicloud
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
# Fetch instances details according to setting different filters
|
# Fetch instances details according to setting different filters
|
||||||
- name: fetch instances details example
|
|
||||||
hosts: localhost
|
|
||||||
vars:
|
|
||||||
alicloud_access_key: <your-alicloud-access-key>
|
|
||||||
alicloud_secret_key: <your-alicloud-secret-key>
|
|
||||||
alicloud_region: cn-beijing
|
|
||||||
availability_zone: cn-beijing-a
|
|
||||||
|
|
||||||
tasks:
|
- name: Find all instances in the specified region
|
||||||
- name: Find all instances in the specified region
|
|
||||||
ali_instance_info:
|
ali_instance_info:
|
||||||
alicloud_access_key: '{{ alicloud_access_key }}'
|
|
||||||
alicloud_secret_key: '{{ alicloud_secret_key }}'
|
|
||||||
alicloud_region: '{{ alicloud_region }}'
|
|
||||||
register: all_instances
|
register: all_instances
|
||||||
|
|
||||||
- name: Find all instances based on the specified ids
|
- name: Find all instances based on the specified ids
|
||||||
ali_instance_info:
|
ali_instance_info:
|
||||||
alicloud_access_key: '{{ alicloud_access_key }}'
|
|
||||||
alicloud_secret_key: '{{ alicloud_secret_key }}'
|
|
||||||
alicloud_region: '{{ alicloud_region }}'
|
|
||||||
instance_ids:
|
instance_ids:
|
||||||
- "i-35b333d9"
|
- "i-35b333d9"
|
||||||
- "i-ddav43kd"
|
- "i-ddav43kd"
|
||||||
register: instances_by_ids
|
register: instances_by_ids
|
||||||
|
|
||||||
- name: Find all instances based on the specified names/name-prefixes
|
- name: Find all instances based on the specified name_prefix
|
||||||
ali_instance_info:
|
ali_instance_info:
|
||||||
alicloud_access_key: '{{ alicloud_access_key }}'
|
name_prefix: "ecs_instance_"
|
||||||
alicloud_secret_key: '{{ alicloud_secret_key }}'
|
register: instances_by_name_prefix
|
||||||
alicloud_region: '{{ alicloud_region }}'
|
|
||||||
instance_names:
|
|
||||||
- "ecs_instance-1"
|
|
||||||
- "ecs_instance_2"
|
|
||||||
register: instances_by_ids
|
|
||||||
|
|
||||||
|
- name: Find instances based on tags
|
||||||
|
ali_instance_info:
|
||||||
|
tags:
|
||||||
|
Test: "add"
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = '''
|
RETURN = '''
|
||||||
|
@ -231,6 +236,11 @@ instances:
|
||||||
returned: always
|
returned: always
|
||||||
type: str
|
type: str
|
||||||
sample: my-ecs
|
sample: my-ecs
|
||||||
|
instance_type_family:
|
||||||
|
description: The instance type family of the instance belongs.
|
||||||
|
returned: always
|
||||||
|
type: str
|
||||||
|
sample: ecs.sn1ne
|
||||||
instance_type:
|
instance_type:
|
||||||
description: The instance type of the running instance.
|
description: The instance type of the running instance.
|
||||||
returned: always
|
returned: always
|
||||||
|
@ -297,7 +307,7 @@ instances:
|
||||||
type: str
|
type: str
|
||||||
sample: 10.0.0.1
|
sample: 10.0.0.1
|
||||||
public_ip_address:
|
public_ip_address:
|
||||||
description: The public IPv4 address assigned to the instance
|
description: The public IPv4 address assigned to the instance or eip address
|
||||||
returned: always
|
returned: always
|
||||||
type: str
|
type: str
|
||||||
sample: 43.0.0.1
|
sample: 43.0.0.1
|
||||||
|
@ -340,7 +350,7 @@ instances:
|
||||||
vpc_id:
|
vpc_id:
|
||||||
description: The ID of the VPC the instance is in.
|
description: The ID of the VPC the instance is in.
|
||||||
returned: always
|
returned: always
|
||||||
type: dict
|
type: str
|
||||||
sample: vpc-0011223344
|
sample: vpc-0011223344
|
||||||
ids:
|
ids:
|
||||||
description: List of ECS instance IDs
|
description: List of ECS instance IDs
|
||||||
|
@ -349,11 +359,9 @@ ids:
|
||||||
sample: [i-12345er, i-3245fs]
|
sample: [i-12345er, i-3245fs]
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# import time
|
|
||||||
# import sys
|
|
||||||
import traceback
|
import traceback
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
from ansible_collections.community.general.plugins.module_utils.alicloud_ecs import get_acs_connection_info, ecs_argument_spec, ecs_connect
|
from ansible_collections.community.general.plugins.module_utils.alicloud_ecs import ecs_argument_spec, ecs_connect
|
||||||
|
|
||||||
HAS_FOOTMARK = False
|
HAS_FOOTMARK = False
|
||||||
FOOTMARK_IMP_ERR = None
|
FOOTMARK_IMP_ERR = None
|
||||||
|
@ -369,9 +377,11 @@ def main():
|
||||||
argument_spec = ecs_argument_spec()
|
argument_spec = ecs_argument_spec()
|
||||||
argument_spec.update(dict(
|
argument_spec.update(dict(
|
||||||
availability_zone=dict(aliases=['alicloud_zone']),
|
availability_zone=dict(aliases=['alicloud_zone']),
|
||||||
instance_ids=dict(type='list', aliases=['ids']),
|
instance_ids=dict(type='list', elements='str', aliases=['ids']),
|
||||||
instance_names=dict(type='list', aliases=['names']),
|
instance_names=dict(type='list', elements='str', aliases=['names']),
|
||||||
instance_tags=dict(type='list', aliases=['tags']),
|
name_prefix=dict(type='str'),
|
||||||
|
tags=dict(type='dict', aliases=['instance_tags']),
|
||||||
|
filters=dict(type='dict')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
module = AnsibleModule(argument_spec=argument_spec)
|
module = AnsibleModule(argument_spec=argument_spec)
|
||||||
|
@ -386,21 +396,41 @@ def main():
|
||||||
instances = []
|
instances = []
|
||||||
instance_ids = []
|
instance_ids = []
|
||||||
ids = module.params['instance_ids']
|
ids = module.params['instance_ids']
|
||||||
|
name_prefix = module.params['name_prefix']
|
||||||
names = module.params['instance_names']
|
names = module.params['instance_names']
|
||||||
zone_id = module.params['availability_zone']
|
zone_id = module.params['availability_zone']
|
||||||
if ids and (not isinstance(ids, list) or len(ids) < 1):
|
if ids and (not isinstance(ids, list) or len(ids) < 1):
|
||||||
module.fail_json(msg='instance_ids should be a list of instances, aborting')
|
module.fail_json(msg='instance_ids should be a list of instances, aborting')
|
||||||
|
|
||||||
if names and (not isinstance(names, list) or len(names) < 1):
|
if names and (not isinstance(names, list) or len(names) < 1):
|
||||||
module.fail_json(msg='instance_ids should be a list of instances, aborting')
|
module.fail_json(msg='instance_names should be a list of instances, aborting')
|
||||||
|
|
||||||
|
filters = module.params['filters']
|
||||||
|
if not filters:
|
||||||
|
filters = {}
|
||||||
|
if not ids:
|
||||||
|
ids = []
|
||||||
|
for key, value in list(filters.items()):
|
||||||
|
if key in ["InstanceIds", "instance_ids", "instance-ids"] and isinstance(ids, list):
|
||||||
|
for id in value:
|
||||||
|
if id not in ids:
|
||||||
|
ids.append(value)
|
||||||
|
if ids:
|
||||||
|
filters['instance_ids'] = ids
|
||||||
|
if module.params['tags']:
|
||||||
|
filters['tags'] = module.params['tags']
|
||||||
|
if zone_id:
|
||||||
|
filters['zone_id'] = zone_id
|
||||||
if names:
|
if names:
|
||||||
for name in names:
|
filters['instance_name'] = names[0]
|
||||||
for inst in ecs.get_all_instances(zone_id=zone_id, instance_ids=ids, instance_name=name):
|
|
||||||
instances.append(inst.read())
|
for inst in ecs.describe_instances(**filters):
|
||||||
instance_ids.append(inst.id)
|
if name_prefix:
|
||||||
else:
|
if not str(inst.instance_name).startswith(name_prefix):
|
||||||
for inst in ecs.get_all_instances(zone_id=zone_id, instance_ids=ids):
|
continue
|
||||||
|
volumes = ecs.describe_disks(instance_id=inst.id)
|
||||||
|
setattr(inst, 'block_device_mappings', volumes)
|
||||||
|
setattr(inst, 'user_data', inst.describe_user_data())
|
||||||
instances.append(inst.read())
|
instances.append(inst.read())
|
||||||
instance_ids.append(inst.id)
|
instance_ids.append(inst.id)
|
||||||
|
|
||||||
|
|
|
@ -152,12 +152,6 @@ plugins/module_utils/univention_umc.py future-import-boilerplate
|
||||||
plugins/module_utils/univention_umc.py metaclass-boilerplate
|
plugins/module_utils/univention_umc.py metaclass-boilerplate
|
||||||
plugins/module_utils/vexata.py future-import-boilerplate
|
plugins/module_utils/vexata.py future-import-boilerplate
|
||||||
plugins/module_utils/vexata.py metaclass-boilerplate
|
plugins/module_utils/vexata.py metaclass-boilerplate
|
||||||
plugins/modules/cloud/alicloud/ali_instance.py validate-modules:doc-required-mismatch
|
|
||||||
plugins/modules/cloud/alicloud/ali_instance.py validate-modules:parameter-list-no-elements
|
|
||||||
plugins/modules/cloud/alicloud/ali_instance_info.py validate-modules:doc-missing-type
|
|
||||||
plugins/modules/cloud/alicloud/ali_instance_info.py validate-modules:doc-required-mismatch
|
|
||||||
plugins/modules/cloud/alicloud/ali_instance_info.py validate-modules:parameter-list-no-elements
|
|
||||||
plugins/modules/cloud/alicloud/ali_instance_info.py validate-modules:parameter-type-not-in-doc
|
|
||||||
plugins/modules/cloud/atomic/atomic_container.py validate-modules:doc-missing-type
|
plugins/modules/cloud/atomic/atomic_container.py validate-modules:doc-missing-type
|
||||||
plugins/modules/cloud/atomic/atomic_container.py validate-modules:doc-required-mismatch
|
plugins/modules/cloud/atomic/atomic_container.py validate-modules:doc-required-mismatch
|
||||||
plugins/modules/cloud/atomic/atomic_container.py validate-modules:no-default-for-required-parameter
|
plugins/modules/cloud/atomic/atomic_container.py validate-modules:no-default-for-required-parameter
|
||||||
|
|
Loading…
Reference in a new issue