More explicit argspec tests (#72064)
* Add more explicit coverage of argspec functionality * fail_on_missing_params * ci_complete ci_coverage * Remove incidental_aws_step_functions_state_machine * ci_complete ci_coverage * Remove incidental_cs_service_offering * ci_complete ci_coverage
This commit is contained in:
parent
a7170da851
commit
ab2b339dd6
16 changed files with 45 additions and 1733 deletions
|
@ -42,6 +42,14 @@ def main():
|
|||
'another': {},
|
||||
}
|
||||
},
|
||||
'json': {
|
||||
'type': 'json',
|
||||
},
|
||||
'fail_on_missing_params': {
|
||||
'type': 'list',
|
||||
'default': [],
|
||||
},
|
||||
'needed_param': {},
|
||||
},
|
||||
required_if=(
|
||||
('state', 'present', ('path', 'content'), True),
|
||||
|
@ -51,6 +59,8 @@ def main():
|
|||
),
|
||||
)
|
||||
|
||||
module.fail_on_missing_params(module.params['fail_on_missing_params'])
|
||||
|
||||
module.exit_json(**module.params)
|
||||
|
||||
|
||||
|
|
|
@ -87,6 +87,31 @@
|
|||
register: argpsec_required_if_fail
|
||||
ignore_errors: true
|
||||
|
||||
- argspec:
|
||||
json: !!str '{"foo": "bar"}'
|
||||
register: argspec_good_json_string
|
||||
|
||||
- argspec:
|
||||
json:
|
||||
foo: bar
|
||||
register: argspec_good_json_dict
|
||||
|
||||
- argspec:
|
||||
json: 1
|
||||
register: argspec_bad_json
|
||||
ignore_errors: true
|
||||
|
||||
- argspec:
|
||||
fail_on_missing_params:
|
||||
- needed_param
|
||||
needed_param: whatever
|
||||
|
||||
- argspec:
|
||||
fail_on_missing_params:
|
||||
- needed_param
|
||||
register: argspec_fail_on_missing_params_bad
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- argspec_required_if_fail is failed
|
||||
|
@ -109,3 +134,13 @@
|
|||
- argspec_required_together_fail is failed
|
||||
|
||||
- argpsec_required_if_fail is failed
|
||||
|
||||
- argspec_good_json_string is successful
|
||||
- >
|
||||
argspec_good_json_string.json == '{"foo": "bar"}'
|
||||
- argspec_good_json_dict is successful
|
||||
- >
|
||||
argspec_good_json_dict.json == '{"foo": "bar"}'
|
||||
- argspec_bad_json is failed
|
||||
|
||||
- argspec_fail_on_missing_params_bad is failed
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
cloud/aws
|
||||
shippable/aws/incidental
|
|
@ -1,4 +0,0 @@
|
|||
# the random_num is generated in a set_fact task at the start of the testsuite
|
||||
state_machine_name: "{{ resource_prefix }}_step_functions_state_machine_ansible_test_{{ random_num }}"
|
||||
step_functions_role_name: "ansible-test-sts-{{ resource_prefix }}-step_functions-role"
|
||||
execution_name: "{{ resource_prefix }}_sfn_execution"
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
"StartAt": "HelloWorld",
|
||||
"States": {
|
||||
"HelloWorld": {
|
||||
"Type": "Pass",
|
||||
"Result": "Some other result",
|
||||
"Next": "Wait"
|
||||
},
|
||||
"Wait": {
|
||||
"Type": "Wait",
|
||||
"Seconds": 30,
|
||||
"End": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"StartAt": "HelloWorld",
|
||||
"States": {
|
||||
"HelloWorld": {
|
||||
"Type": "Pass",
|
||||
"Result": "Hello World!",
|
||||
"End": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Service": "states.amazonaws.com"
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,296 +0,0 @@
|
|||
---
|
||||
|
||||
- name: Integration test for AWS Step Function state machine module
|
||||
module_defaults:
|
||||
iam_role:
|
||||
aws_access_key: "{{ aws_access_key }}"
|
||||
aws_secret_key: "{{ aws_secret_key }}"
|
||||
security_token: "{{ security_token | default(omit) }}"
|
||||
region: "{{ aws_region }}"
|
||||
aws_step_functions_state_machine:
|
||||
aws_access_key: "{{ aws_access_key }}"
|
||||
aws_secret_key: "{{ aws_secret_key }}"
|
||||
security_token: "{{ security_token | default(omit) }}"
|
||||
region: "{{ aws_region }}"
|
||||
aws_step_functions_state_machine_execution:
|
||||
aws_access_key: "{{ aws_access_key }}"
|
||||
aws_secret_key: "{{ aws_secret_key }}"
|
||||
security_token: "{{ security_token | default(omit) }}"
|
||||
region: "{{ aws_region }}"
|
||||
block:
|
||||
|
||||
# ==== Setup ==================================================
|
||||
|
||||
- name: Create IAM service role needed for Step Functions
|
||||
iam_role:
|
||||
name: "{{ step_functions_role_name }}"
|
||||
description: Role with permissions for AWS Step Functions actions.
|
||||
assume_role_policy_document: "{{ lookup('file', 'state_machines_iam_trust_policy.json') }}"
|
||||
state: present
|
||||
register: step_functions_role
|
||||
|
||||
- name: Pause a few seconds to ensure IAM role is available to next task
|
||||
pause:
|
||||
seconds: 10
|
||||
|
||||
# ==== Tests ===================================================
|
||||
|
||||
- name: Create a random component for state machine name
|
||||
set_fact:
|
||||
random_num: "{{ 999999999 | random }}"
|
||||
|
||||
- name: Create a new state machine -- check_mode
|
||||
aws_step_functions_state_machine:
|
||||
name: "{{ state_machine_name }}"
|
||||
definition: "{{ lookup('file','state_machine.json') }}"
|
||||
role_arn: "{{ step_functions_role.iam_role.arn }}"
|
||||
tags:
|
||||
project: helloWorld
|
||||
state: present
|
||||
register: creation_check
|
||||
check_mode: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- creation_check.changed == True
|
||||
- creation_check.output == 'State machine would be created.'
|
||||
|
||||
- name: Create a new state machine
|
||||
aws_step_functions_state_machine:
|
||||
name: "{{ state_machine_name }}"
|
||||
definition: "{{ lookup('file','state_machine.json') }}"
|
||||
role_arn: "{{ step_functions_role.iam_role.arn }}"
|
||||
tags:
|
||||
project: helloWorld
|
||||
state: present
|
||||
register: creation_output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- creation_output.changed == True
|
||||
|
||||
- name: Pause a few seconds to ensure state machine role is available
|
||||
pause:
|
||||
seconds: 5
|
||||
|
||||
- name: Idempotent rerun of same state function -- check_mode
|
||||
aws_step_functions_state_machine:
|
||||
name: "{{ state_machine_name }}"
|
||||
definition: "{{ lookup('file','state_machine.json') }}"
|
||||
role_arn: "{{ step_functions_role.iam_role.arn }}"
|
||||
tags:
|
||||
project: helloWorld
|
||||
state: present
|
||||
register: result
|
||||
check_mode: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.changed == False
|
||||
- result.output == 'State is up-to-date.'
|
||||
|
||||
- name: Idempotent rerun of same state function
|
||||
aws_step_functions_state_machine:
|
||||
name: "{{ state_machine_name }}"
|
||||
definition: "{{ lookup('file','state_machine.json') }}"
|
||||
role_arn: "{{ step_functions_role.iam_role.arn }}"
|
||||
tags:
|
||||
project: helloWorld
|
||||
state: present
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.changed == False
|
||||
|
||||
- name: Update an existing state machine -- check_mode
|
||||
aws_step_functions_state_machine:
|
||||
name: "{{ state_machine_name }}"
|
||||
definition: "{{ lookup('file','alternative_state_machine.json') }}"
|
||||
role_arn: "{{ step_functions_role.iam_role.arn }}"
|
||||
tags:
|
||||
differentTag: different_tag
|
||||
state: present
|
||||
register: update_check
|
||||
check_mode: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_check.changed == True
|
||||
- "update_check.output == 'State machine would be updated: {{ creation_output.state_machine_arn }}'"
|
||||
|
||||
- name: Update an existing state machine
|
||||
aws_step_functions_state_machine:
|
||||
name: "{{ state_machine_name }}"
|
||||
definition: "{{ lookup('file','alternative_state_machine.json') }}"
|
||||
role_arn: "{{ step_functions_role.iam_role.arn }}"
|
||||
tags:
|
||||
differentTag: different_tag
|
||||
state: present
|
||||
register: update_output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_output.changed == True
|
||||
- update_output.state_machine_arn == creation_output.state_machine_arn
|
||||
|
||||
- name: Start execution of state machine -- check_mode
|
||||
aws_step_functions_state_machine_execution:
|
||||
name: "{{ execution_name }}"
|
||||
execution_input: "{}"
|
||||
state_machine_arn: "{{ creation_output.state_machine_arn }}"
|
||||
register: start_execution_output
|
||||
check_mode: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- start_execution_output.changed == True
|
||||
- "start_execution_output.output == 'State machine execution would be started.'"
|
||||
|
||||
- name: Start execution of state machine
|
||||
aws_step_functions_state_machine_execution:
|
||||
name: "{{ execution_name }}"
|
||||
execution_input: "{}"
|
||||
state_machine_arn: "{{ creation_output.state_machine_arn }}"
|
||||
register: start_execution_output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- start_execution_output.changed
|
||||
- "'execution_arn' in start_execution_output"
|
||||
- "'start_date' in start_execution_output"
|
||||
|
||||
- name: Start execution of state machine (check for idempotency) (check mode)
|
||||
aws_step_functions_state_machine_execution:
|
||||
name: "{{ execution_name }}"
|
||||
execution_input: "{}"
|
||||
state_machine_arn: "{{ creation_output.state_machine_arn }}"
|
||||
register: start_execution_output_idem_check
|
||||
check_mode: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not start_execution_output_idem_check.changed
|
||||
- "start_execution_output_idem_check.output == 'State machine execution already exists.'"
|
||||
|
||||
- name: Start execution of state machine (check for idempotency)
|
||||
aws_step_functions_state_machine_execution:
|
||||
name: "{{ execution_name }}"
|
||||
execution_input: "{}"
|
||||
state_machine_arn: "{{ creation_output.state_machine_arn }}"
|
||||
register: start_execution_output_idem
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not start_execution_output_idem.changed
|
||||
|
||||
- name: Stop execution of state machine -- check_mode
|
||||
aws_step_functions_state_machine_execution:
|
||||
action: stop
|
||||
execution_arn: "{{ start_execution_output.execution_arn }}"
|
||||
cause: "cause of the failure"
|
||||
error: "error code of the failure"
|
||||
register: stop_execution_output
|
||||
check_mode: yes
|
||||
|
||||
- name: Stop execution of state machine
|
||||
aws_step_functions_state_machine_execution:
|
||||
action: stop
|
||||
execution_arn: "{{ start_execution_output.execution_arn }}"
|
||||
cause: "cause of the failure"
|
||||
error: "error code of the failure"
|
||||
register: stop_execution_output
|
||||
|
||||
- name: Stop execution of state machine (check for idempotency)
|
||||
aws_step_functions_state_machine_execution:
|
||||
action: stop
|
||||
execution_arn: "{{ start_execution_output.execution_arn }}"
|
||||
cause: "cause of the failure"
|
||||
error: "error code of the failure"
|
||||
register: stop_execution_output
|
||||
|
||||
- name: Try stopping a non-running execution -- check_mode
|
||||
aws_step_functions_state_machine_execution:
|
||||
action: stop
|
||||
execution_arn: "{{ start_execution_output.execution_arn }}"
|
||||
cause: "cause of the failure"
|
||||
error: "error code of the failure"
|
||||
register: stop_execution_output
|
||||
check_mode: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not stop_execution_output.changed
|
||||
- "stop_execution_output.output == 'State machine execution is not running.'"
|
||||
|
||||
- name: Try stopping a non-running execution
|
||||
aws_step_functions_state_machine_execution:
|
||||
action: stop
|
||||
execution_arn: "{{ start_execution_output.execution_arn }}"
|
||||
cause: "cause of the failure"
|
||||
error: "error code of the failure"
|
||||
register: stop_execution_output
|
||||
check_mode: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not stop_execution_output.changed
|
||||
|
||||
- name: Start execution of state machine with the same execution name
|
||||
aws_step_functions_state_machine_execution:
|
||||
name: "{{ execution_name }}"
|
||||
state_machine_arn: "{{ creation_output.state_machine_arn }}"
|
||||
register: start_execution_output_again
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not start_execution_output_again.changed
|
||||
|
||||
- name: Remove state machine -- check_mode
|
||||
aws_step_functions_state_machine:
|
||||
name: "{{ state_machine_name }}"
|
||||
state: absent
|
||||
register: deletion_check
|
||||
check_mode: yes
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- deletion_check.changed == True
|
||||
- "deletion_check.output == 'State machine would be deleted: {{ creation_output.state_machine_arn }}'"
|
||||
|
||||
- name: Remove state machine
|
||||
aws_step_functions_state_machine:
|
||||
name: "{{ state_machine_name }}"
|
||||
state: absent
|
||||
register: deletion_output
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- deletion_output.changed == True
|
||||
- deletion_output.state_machine_arn == creation_output.state_machine_arn
|
||||
|
||||
- name: Non-existent state machine is absent
|
||||
aws_step_functions_state_machine:
|
||||
name: "non_existing_state_machine"
|
||||
state: absent
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result.changed == False
|
||||
|
||||
# ==== Cleanup ====================================================
|
||||
|
||||
always:
|
||||
|
||||
- name: Cleanup - delete state machine
|
||||
aws_step_functions_state_machine:
|
||||
name: "{{ state_machine_name }}"
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
|
||||
- name: Cleanup - delete IAM role needed for Step Functions test
|
||||
iam_role:
|
||||
name: "{{ step_functions_role_name }}"
|
||||
state: absent
|
||||
ignore_errors: true
|
|
@ -1,2 +0,0 @@
|
|||
cloud/cs
|
||||
shippable/cs/incidental
|
|
@ -1,3 +0,0 @@
|
|||
---
|
||||
dependencies:
|
||||
- incidental_cs_common
|
|
@ -1,223 +0,0 @@
|
|||
---
|
||||
- name: setup service offering
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
state: absent
|
||||
register: so
|
||||
- name: verify setup service offering
|
||||
assert:
|
||||
that:
|
||||
- so is successful
|
||||
|
||||
- name: create service offering in check mode
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
display_text: Micro 512mb 1cpu
|
||||
cpu_number: 1
|
||||
cpu_speed: 2198
|
||||
memory: 512
|
||||
host_tags: eco
|
||||
storage_tags:
|
||||
- eco
|
||||
- backup
|
||||
storage_type: local
|
||||
register: so
|
||||
check_mode: true
|
||||
- name: verify create service offering in check mode
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
|
||||
- name: create service offering
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
display_text: Micro 512mb 1cpu
|
||||
cpu_number: 1
|
||||
cpu_speed: 2198
|
||||
memory: 512
|
||||
host_tags: eco
|
||||
storage_tags:
|
||||
- eco
|
||||
- backup
|
||||
storage_type: local
|
||||
register: so
|
||||
- name: verify create service offering
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "Micro"
|
||||
- so.display_text == "Micro 512mb 1cpu"
|
||||
- so.cpu_number == 1
|
||||
- so.cpu_speed == 2198
|
||||
- so.memory == 512
|
||||
- so.host_tags == ['eco']
|
||||
- so.storage_tags == ['eco', 'backup']
|
||||
- so.storage_type == "local"
|
||||
|
||||
- name: create service offering idempotence
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
display_text: Micro 512mb 1cpu
|
||||
cpu_number: 1
|
||||
cpu_speed: 2198
|
||||
memory: 512
|
||||
host_tags: eco
|
||||
storage_tags:
|
||||
- eco
|
||||
- backup
|
||||
storage_type: local
|
||||
register: so
|
||||
- name: verify create service offering idempotence
|
||||
assert:
|
||||
that:
|
||||
- so is not changed
|
||||
- so.name == "Micro"
|
||||
- so.display_text == "Micro 512mb 1cpu"
|
||||
- so.cpu_number == 1
|
||||
- so.cpu_speed == 2198
|
||||
- so.memory == 512
|
||||
- so.host_tags == ['eco']
|
||||
- so.storage_tags == ['eco', 'backup']
|
||||
- so.storage_type == "local"
|
||||
|
||||
- name: update service offering in check mode
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
display_text: Micro RAM 512MB 1vCPU
|
||||
register: so
|
||||
check_mode: true
|
||||
- name: verify create update offering in check mode
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "Micro"
|
||||
- so.display_text == "Micro 512mb 1cpu"
|
||||
- so.cpu_number == 1
|
||||
- so.cpu_speed == 2198
|
||||
- so.memory == 512
|
||||
- so.host_tags == ['eco']
|
||||
- so.storage_tags == ['eco', 'backup']
|
||||
- so.storage_type == "local"
|
||||
|
||||
- name: update service offering
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
display_text: Micro RAM 512MB 1vCPU
|
||||
register: so
|
||||
- name: verify update service offerin
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "Micro"
|
||||
- so.display_text == "Micro RAM 512MB 1vCPU"
|
||||
- so.cpu_number == 1
|
||||
- so.cpu_speed == 2198
|
||||
- so.memory == 512
|
||||
- so.host_tags == ['eco']
|
||||
- so.storage_tags == ['eco', 'backup']
|
||||
- so.storage_type == "local"
|
||||
|
||||
- name: update service offering idempotence
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
display_text: Micro RAM 512MB 1vCPU
|
||||
register: so
|
||||
- name: verify update service offering idempotence
|
||||
assert:
|
||||
that:
|
||||
- so is not changed
|
||||
- so.name == "Micro"
|
||||
- so.display_text == "Micro RAM 512MB 1vCPU"
|
||||
- so.cpu_number == 1
|
||||
- so.cpu_speed == 2198
|
||||
- so.memory == 512
|
||||
- so.host_tags == ['eco']
|
||||
- so.storage_tags == ['eco', 'backup']
|
||||
- so.storage_type == "local"
|
||||
|
||||
- name: remove service offering in check mode
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
state: absent
|
||||
check_mode: true
|
||||
register: so
|
||||
- name: verify remove service offering in check mode
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "Micro"
|
||||
- so.display_text == "Micro RAM 512MB 1vCPU"
|
||||
- so.cpu_number == 1
|
||||
- so.cpu_speed == 2198
|
||||
- so.memory == 512
|
||||
- so.host_tags == ['eco']
|
||||
- so.storage_tags == ['eco', 'backup']
|
||||
- so.storage_type == "local"
|
||||
|
||||
- name: remove service offering
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
state: absent
|
||||
register: so
|
||||
- name: verify remove service offering
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "Micro"
|
||||
- so.display_text == "Micro RAM 512MB 1vCPU"
|
||||
- so.cpu_number == 1
|
||||
- so.cpu_speed == 2198
|
||||
- so.memory == 512
|
||||
- so.host_tags == ['eco']
|
||||
- so.storage_tags == ['eco', 'backup']
|
||||
- so.storage_type == "local"
|
||||
|
||||
- name: remove service offering idempotence
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
state: absent
|
||||
register: so
|
||||
- name: verify remove service offering idempotence
|
||||
assert:
|
||||
that:
|
||||
- so is not changed
|
||||
|
||||
- name: create custom service offering
|
||||
cs_service_offering:
|
||||
name: custom
|
||||
display_text: custom offer
|
||||
is_customized: yes
|
||||
host_tags: eco
|
||||
storage_tags:
|
||||
- eco
|
||||
- backup
|
||||
storage_type: local
|
||||
register: so
|
||||
- name: verify create custom service offering
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "custom"
|
||||
- so.display_text == "custom offer"
|
||||
- so.is_customized == True
|
||||
- so.cpu_number is not defined
|
||||
- so.cpu_speed is not defined
|
||||
- so.memory is not defined
|
||||
- so.host_tags == ['eco']
|
||||
- so.storage_tags == ['eco', 'backup']
|
||||
- so.storage_type == "local"
|
||||
|
||||
- name: remove custom service offering
|
||||
cs_service_offering:
|
||||
name: custom
|
||||
state: absent
|
||||
register: so
|
||||
- name: verify remove service offering
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "custom"
|
||||
- so.display_text == "custom offer"
|
||||
- so.host_tags == ['eco']
|
||||
- so.storage_tags == ['eco', 'backup']
|
||||
- so.storage_type == "local"
|
|
@ -1,3 +0,0 @@
|
|||
---
|
||||
- import_tasks: guest_vm_service_offering.yml
|
||||
- import_tasks: system_vm_service_offering.yml
|
|
@ -1,151 +0,0 @@
|
|||
---
|
||||
- name: setup system offering
|
||||
cs_service_offering:
|
||||
name: System Offering for Ansible
|
||||
is_system: true
|
||||
state: absent
|
||||
register: so
|
||||
- name: verify setup system offering
|
||||
assert:
|
||||
that:
|
||||
- so is successful
|
||||
|
||||
- name: fail missing storage type and is_system
|
||||
cs_service_offering:
|
||||
name: System Offering for Ansible
|
||||
cpu_number: 1
|
||||
cpu_speed: 500
|
||||
memory: 512
|
||||
host_tag: perf
|
||||
storage_tag: perf
|
||||
storage_type: shared
|
||||
offer_ha: true
|
||||
limit_cpu_usage: false
|
||||
is_system: true
|
||||
register: so
|
||||
ignore_errors: true
|
||||
- name: verify create system service offering in check mode
|
||||
assert:
|
||||
that:
|
||||
- so is failed
|
||||
- so.msg.startswith('missing required arguments:')
|
||||
|
||||
- name: create system service offering in check mode
|
||||
cs_service_offering:
|
||||
name: System Offering for Ansible
|
||||
cpu_number: 1
|
||||
cpu_speed: 500
|
||||
memory: 512
|
||||
host_tag: perf
|
||||
storage_tag: perf
|
||||
storage_type: shared
|
||||
offer_ha: true
|
||||
limit_cpu_usage: false
|
||||
system_vm_type: domainrouter
|
||||
is_system: true
|
||||
register: so
|
||||
check_mode: true
|
||||
- name: verify create system service offering in check mode
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
|
||||
- name: create system service offering
|
||||
cs_service_offering:
|
||||
name: System Offering for Ansible
|
||||
cpu_number: 1
|
||||
cpu_speed: 500
|
||||
memory: 512
|
||||
host_tag: perf
|
||||
storage_tag: perf
|
||||
storage_type: shared
|
||||
offer_ha: true
|
||||
limit_cpu_usage: false
|
||||
system_vm_type: domainrouter
|
||||
is_system: true
|
||||
register: so
|
||||
- name: verify create system service offering
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "System Offering for Ansible"
|
||||
- so.display_text == "System Offering for Ansible"
|
||||
- so.cpu_number == 1
|
||||
- so.cpu_speed == 500
|
||||
- so.memory == 512
|
||||
- so.host_tags == ['perf']
|
||||
- so.storage_tags == ['perf']
|
||||
- so.storage_type == "shared"
|
||||
- so.offer_ha == true
|
||||
- so.limit_cpu_usage == false
|
||||
- so.system_vm_type == "domainrouter"
|
||||
- so.is_system == true
|
||||
|
||||
- name: create system service offering idempotence
|
||||
cs_service_offering:
|
||||
name: System Offering for Ansible
|
||||
cpu_number: 1
|
||||
cpu_speed: 500
|
||||
memory: 512
|
||||
host_tag: perf
|
||||
storage_tag: perf
|
||||
storage_type: shared
|
||||
offer_ha: true
|
||||
limit_cpu_usage: false
|
||||
system_vm_type: domainrouter
|
||||
is_system: true
|
||||
register: so
|
||||
- name: verify create system service offering idempotence
|
||||
assert:
|
||||
that:
|
||||
- so is not changed
|
||||
- so.name == "System Offering for Ansible"
|
||||
- so.display_text == "System Offering for Ansible"
|
||||
- so.cpu_number == 1
|
||||
- so.cpu_speed == 500
|
||||
- so.memory == 512
|
||||
- so.host_tags == ['perf']
|
||||
- so.storage_tags == ['perf']
|
||||
- so.storage_type == "shared"
|
||||
- so.offer_ha == true
|
||||
- so.limit_cpu_usage == false
|
||||
- so.system_vm_type == "domainrouter"
|
||||
- so.is_system == true
|
||||
|
||||
- name: remove system service offering in check mode
|
||||
cs_service_offering:
|
||||
name: System Offering for Ansible
|
||||
is_system: true
|
||||
state: absent
|
||||
check_mode: true
|
||||
register: so
|
||||
- name: verify remove system service offering in check mode
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "System Offering for Ansible"
|
||||
- so.is_system == true
|
||||
|
||||
- name: remove system service offering
|
||||
cs_service_offering:
|
||||
name: System Offering for Ansible
|
||||
is_system: true
|
||||
state: absent
|
||||
register: so
|
||||
- name: verify remove system service offering
|
||||
assert:
|
||||
that:
|
||||
- so is changed
|
||||
- so.name == "System Offering for Ansible"
|
||||
- so.is_system == true
|
||||
|
||||
- name: remove system service offering idempotence
|
||||
cs_service_offering:
|
||||
name: System Offering for Ansible
|
||||
is_system: true
|
||||
state: absent
|
||||
register: so
|
||||
- name: verify remove system service offering idempotence
|
||||
assert:
|
||||
that:
|
||||
- so is not changed
|
|
@ -1,232 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright (c) 2019, Tom De Keyser (@tdekeyser)
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: aws_step_functions_state_machine
|
||||
|
||||
short_description: Manage AWS Step Functions state machines
|
||||
|
||||
version_added: "2.10"
|
||||
|
||||
description:
|
||||
- Create, update and delete state machines in AWS Step Functions.
|
||||
- Calling the module in C(state=present) for an existing AWS Step Functions state machine
|
||||
will attempt to update the state machine definition, IAM Role, or tags with the provided data.
|
||||
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- Name of the state machine
|
||||
required: true
|
||||
type: str
|
||||
definition:
|
||||
description:
|
||||
- The Amazon States Language definition of the state machine. See
|
||||
U(https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html) for more
|
||||
information on the Amazon States Language.
|
||||
- "This parameter is required when C(state=present)."
|
||||
type: json
|
||||
role_arn:
|
||||
description:
|
||||
- The ARN of the IAM Role that will be used by the state machine for its executions.
|
||||
- "This parameter is required when C(state=present)."
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- Desired state for the state machine
|
||||
default: present
|
||||
choices: [ present, absent ]
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- A hash/dictionary of tags to add to the new state machine or to add/remove from an existing one.
|
||||
type: dict
|
||||
purge_tags:
|
||||
description:
|
||||
- If yes, existing tags will be purged from the resource to match exactly what is defined by I(tags) parameter.
|
||||
If the I(tags) parameter is not set then tags will not be modified.
|
||||
default: yes
|
||||
type: bool
|
||||
|
||||
extends_documentation_fragment:
|
||||
- aws
|
||||
- ec2
|
||||
|
||||
author:
|
||||
- Tom De Keyser (@tdekeyser)
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Create a new AWS Step Functions state machine
|
||||
- name: Setup HelloWorld state machine
|
||||
aws_step_functions_state_machine:
|
||||
name: "HelloWorldStateMachine"
|
||||
definition: "{{ lookup('file','state_machine.json') }}"
|
||||
role_arn: arn:aws:iam::987654321012:role/service-role/invokeLambdaStepFunctionsRole
|
||||
tags:
|
||||
project: helloWorld
|
||||
|
||||
# Update an existing state machine
|
||||
- name: Change IAM Role and tags of HelloWorld state machine
|
||||
aws_step_functions_state_machine:
|
||||
name: HelloWorldStateMachine
|
||||
definition: "{{ lookup('file','state_machine.json') }}"
|
||||
role_arn: arn:aws:iam::987654321012:role/service-role/anotherStepFunctionsRole
|
||||
tags:
|
||||
otherTag: aDifferentTag
|
||||
|
||||
# Remove the AWS Step Functions state machine
|
||||
- name: Delete HelloWorld state machine
|
||||
aws_step_functions_state_machine:
|
||||
name: HelloWorldStateMachine
|
||||
state: absent
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
state_machine_arn:
|
||||
description: ARN of the AWS Step Functions state machine
|
||||
type: str
|
||||
returned: always
|
||||
'''
|
||||
|
||||
from ansible.module_utils.aws.core import AnsibleAWSModule
|
||||
from ansible.module_utils.ec2 import ansible_dict_to_boto3_tag_list, AWSRetry, compare_aws_tags, boto3_tag_list_to_ansible_dict
|
||||
|
||||
try:
|
||||
from botocore.exceptions import ClientError, BotoCoreError
|
||||
except ImportError:
|
||||
pass # caught by AnsibleAWSModule
|
||||
|
||||
|
||||
def manage_state_machine(state, sfn_client, module):
|
||||
state_machine_arn = get_state_machine_arn(sfn_client, module)
|
||||
|
||||
if state == 'present':
|
||||
if state_machine_arn is None:
|
||||
create(sfn_client, module)
|
||||
else:
|
||||
update(state_machine_arn, sfn_client, module)
|
||||
elif state == 'absent':
|
||||
if state_machine_arn is not None:
|
||||
remove(state_machine_arn, sfn_client, module)
|
||||
|
||||
check_mode(module, msg='State is up-to-date.')
|
||||
module.exit_json(changed=False)
|
||||
|
||||
|
||||
def create(sfn_client, module):
|
||||
check_mode(module, msg='State machine would be created.', changed=True)
|
||||
|
||||
tags = module.params.get('tags')
|
||||
sfn_tags = ansible_dict_to_boto3_tag_list(tags, tag_name_key_name='key', tag_value_key_name='value') if tags else []
|
||||
|
||||
state_machine = sfn_client.create_state_machine(
|
||||
name=module.params.get('name'),
|
||||
definition=module.params.get('definition'),
|
||||
roleArn=module.params.get('role_arn'),
|
||||
tags=sfn_tags
|
||||
)
|
||||
module.exit_json(changed=True, state_machine_arn=state_machine.get('stateMachineArn'))
|
||||
|
||||
|
||||
def remove(state_machine_arn, sfn_client, module):
|
||||
check_mode(module, msg='State machine would be deleted: {0}'.format(state_machine_arn), changed=True)
|
||||
|
||||
sfn_client.delete_state_machine(stateMachineArn=state_machine_arn)
|
||||
module.exit_json(changed=True, state_machine_arn=state_machine_arn)
|
||||
|
||||
|
||||
def update(state_machine_arn, sfn_client, module):
|
||||
tags_to_add, tags_to_remove = compare_tags(state_machine_arn, sfn_client, module)
|
||||
|
||||
if params_changed(state_machine_arn, sfn_client, module) or tags_to_add or tags_to_remove:
|
||||
check_mode(module, msg='State machine would be updated: {0}'.format(state_machine_arn), changed=True)
|
||||
|
||||
sfn_client.update_state_machine(
|
||||
stateMachineArn=state_machine_arn,
|
||||
definition=module.params.get('definition'),
|
||||
roleArn=module.params.get('role_arn')
|
||||
)
|
||||
sfn_client.untag_resource(
|
||||
resourceArn=state_machine_arn,
|
||||
tagKeys=tags_to_remove
|
||||
)
|
||||
sfn_client.tag_resource(
|
||||
resourceArn=state_machine_arn,
|
||||
tags=ansible_dict_to_boto3_tag_list(tags_to_add, tag_name_key_name='key', tag_value_key_name='value')
|
||||
)
|
||||
|
||||
module.exit_json(changed=True, state_machine_arn=state_machine_arn)
|
||||
|
||||
|
||||
def compare_tags(state_machine_arn, sfn_client, module):
|
||||
new_tags = module.params.get('tags')
|
||||
current_tags = sfn_client.list_tags_for_resource(resourceArn=state_machine_arn).get('tags')
|
||||
return compare_aws_tags(boto3_tag_list_to_ansible_dict(current_tags), new_tags if new_tags else {}, module.params.get('purge_tags'))
|
||||
|
||||
|
||||
def params_changed(state_machine_arn, sfn_client, module):
|
||||
"""
|
||||
Check whether the state machine definition or IAM Role ARN is different
|
||||
from the existing state machine parameters.
|
||||
"""
|
||||
current = sfn_client.describe_state_machine(stateMachineArn=state_machine_arn)
|
||||
return current.get('definition') != module.params.get('definition') or current.get('roleArn') != module.params.get('role_arn')
|
||||
|
||||
|
||||
def get_state_machine_arn(sfn_client, module):
|
||||
"""
|
||||
Finds the state machine ARN based on the name parameter. Returns None if
|
||||
there is no state machine with this name.
|
||||
"""
|
||||
target_name = module.params.get('name')
|
||||
all_state_machines = sfn_client.list_state_machines(aws_retry=True).get('stateMachines')
|
||||
|
||||
for state_machine in all_state_machines:
|
||||
if state_machine.get('name') == target_name:
|
||||
return state_machine.get('stateMachineArn')
|
||||
|
||||
|
||||
def check_mode(module, msg='', changed=False):
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=changed, output=msg)
|
||||
|
||||
|
||||
def main():
|
||||
module_args = dict(
|
||||
name=dict(type='str', required=True),
|
||||
definition=dict(type='json'),
|
||||
role_arn=dict(type='str'),
|
||||
state=dict(choices=['present', 'absent'], default='present'),
|
||||
tags=dict(default=None, type='dict'),
|
||||
purge_tags=dict(default=True, type='bool'),
|
||||
)
|
||||
module = AnsibleAWSModule(
|
||||
argument_spec=module_args,
|
||||
required_if=[('state', 'present', ['role_arn']), ('state', 'present', ['definition'])],
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
sfn_client = module.client('stepfunctions', retry_decorator=AWSRetry.jittered_backoff(retries=5))
|
||||
state = module.params.get('state')
|
||||
|
||||
try:
|
||||
manage_state_machine(state, sfn_client, module)
|
||||
except (BotoCoreError, ClientError) as e:
|
||||
module.fail_json_aws(e, msg='Failed to manage state machine')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,197 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright (c) 2019, Prasad Katti (@prasadkatti)
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'
|
||||
}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: aws_step_functions_state_machine_execution
|
||||
|
||||
short_description: Start or stop execution of an AWS Step Functions state machine.
|
||||
|
||||
version_added: "2.10"
|
||||
|
||||
description:
|
||||
- Start or stop execution of a state machine in AWS Step Functions.
|
||||
|
||||
options:
|
||||
action:
|
||||
description: Desired action (start or stop) for a state machine execution.
|
||||
default: start
|
||||
choices: [ start, stop ]
|
||||
type: str
|
||||
name:
|
||||
description: Name of the execution.
|
||||
type: str
|
||||
execution_input:
|
||||
description: The JSON input data for the execution.
|
||||
type: json
|
||||
default: {}
|
||||
state_machine_arn:
|
||||
description: The ARN of the state machine that will be executed.
|
||||
type: str
|
||||
execution_arn:
|
||||
description: The ARN of the execution you wish to stop.
|
||||
type: str
|
||||
cause:
|
||||
description: A detailed explanation of the cause for stopping the execution.
|
||||
type: str
|
||||
default: ''
|
||||
error:
|
||||
description: The error code of the failure to pass in when stopping the execution.
|
||||
type: str
|
||||
default: ''
|
||||
|
||||
extends_documentation_fragment:
|
||||
- aws
|
||||
- ec2
|
||||
|
||||
author:
|
||||
- Prasad Katti (@prasadkatti)
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Start an execution of a state machine
|
||||
aws_step_functions_state_machine_execution:
|
||||
name: an_execution_name
|
||||
execution_input: '{ "IsHelloWorldExample": true }'
|
||||
state_machine_arn: "arn:aws:states:us-west-2:682285639423:stateMachine:HelloWorldStateMachine"
|
||||
|
||||
- name: Stop an execution of a state machine
|
||||
aws_step_functions_state_machine_execution:
|
||||
action: stop
|
||||
execution_arn: "arn:aws:states:us-west-2:682285639423:execution:HelloWorldStateMachineCopy:a1e8e2b5-5dfe-d40e-d9e3-6201061047c8"
|
||||
cause: "cause of task failure"
|
||||
error: "error code of the failure"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
execution_arn:
|
||||
description: ARN of the AWS Step Functions state machine execution.
|
||||
type: str
|
||||
returned: if action == start and changed == True
|
||||
sample: "arn:aws:states:us-west-2:682285639423:execution:HelloWorldStateMachineCopy:a1e8e2b5-5dfe-d40e-d9e3-6201061047c8"
|
||||
start_date:
|
||||
description: The date the execution is started.
|
||||
type: str
|
||||
returned: if action == start and changed == True
|
||||
sample: "2019-11-02T22:39:49.071000-07:00"
|
||||
stop_date:
|
||||
description: The date the execution is stopped.
|
||||
type: str
|
||||
returned: if action == stop
|
||||
sample: "2019-11-02T22:39:49.071000-07:00"
|
||||
'''
|
||||
|
||||
|
||||
from ansible.module_utils.aws.core import AnsibleAWSModule
|
||||
from ansible.module_utils.ec2 import camel_dict_to_snake_dict
|
||||
|
||||
try:
|
||||
from botocore.exceptions import ClientError, BotoCoreError
|
||||
except ImportError:
|
||||
pass # caught by AnsibleAWSModule
|
||||
|
||||
|
||||
def start_execution(module, sfn_client):
|
||||
'''
|
||||
start_execution uses execution name to determine if a previous execution already exists.
|
||||
If an execution by the provided name exists, call client.start_execution will not be called.
|
||||
'''
|
||||
|
||||
state_machine_arn = module.params.get('state_machine_arn')
|
||||
name = module.params.get('name')
|
||||
execution_input = module.params.get('execution_input')
|
||||
|
||||
try:
|
||||
# list_executions is eventually consistent
|
||||
page_iterators = sfn_client.get_paginator('list_executions').paginate(stateMachineArn=state_machine_arn)
|
||||
|
||||
for execution in page_iterators.build_full_result()['executions']:
|
||||
if name == execution['name']:
|
||||
check_mode(module, msg='State machine execution already exists.', changed=False)
|
||||
module.exit_json(changed=False)
|
||||
|
||||
check_mode(module, msg='State machine execution would be started.', changed=True)
|
||||
res_execution = sfn_client.start_execution(
|
||||
stateMachineArn=state_machine_arn,
|
||||
name=name,
|
||||
input=execution_input
|
||||
)
|
||||
except (ClientError, BotoCoreError) as e:
|
||||
if e.response['Error']['Code'] == 'ExecutionAlreadyExists':
|
||||
# this will never be executed anymore
|
||||
module.exit_json(changed=False)
|
||||
module.fail_json_aws(e, msg="Failed to start execution.")
|
||||
|
||||
module.exit_json(changed=True, **camel_dict_to_snake_dict(res_execution))
|
||||
|
||||
|
||||
def stop_execution(module, sfn_client):
|
||||
|
||||
cause = module.params.get('cause')
|
||||
error = module.params.get('error')
|
||||
execution_arn = module.params.get('execution_arn')
|
||||
|
||||
try:
|
||||
# describe_execution is eventually consistent
|
||||
execution_status = sfn_client.describe_execution(executionArn=execution_arn)['status']
|
||||
if execution_status != 'RUNNING':
|
||||
check_mode(module, msg='State machine execution is not running.', changed=False)
|
||||
module.exit_json(changed=False)
|
||||
|
||||
check_mode(module, msg='State machine execution would be stopped.', changed=True)
|
||||
res = sfn_client.stop_execution(
|
||||
executionArn=execution_arn,
|
||||
cause=cause,
|
||||
error=error
|
||||
)
|
||||
except (ClientError, BotoCoreError) as e:
|
||||
module.fail_json_aws(e, msg="Failed to stop execution.")
|
||||
|
||||
module.exit_json(changed=True, **camel_dict_to_snake_dict(res))
|
||||
|
||||
|
||||
def check_mode(module, msg='', changed=False):
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=changed, output=msg)
|
||||
|
||||
|
||||
def main():
|
||||
module_args = dict(
|
||||
action=dict(choices=['start', 'stop'], default='start'),
|
||||
name=dict(type='str'),
|
||||
execution_input=dict(type='json', default={}),
|
||||
state_machine_arn=dict(type='str'),
|
||||
cause=dict(type='str', default=''),
|
||||
error=dict(type='str', default=''),
|
||||
execution_arn=dict(type='str')
|
||||
)
|
||||
module = AnsibleAWSModule(
|
||||
argument_spec=module_args,
|
||||
required_if=[('action', 'start', ['name', 'state_machine_arn']),
|
||||
('action', 'stop', ['execution_arn']),
|
||||
],
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
sfn_client = module.client('stepfunctions')
|
||||
|
||||
action = module.params.get('action')
|
||||
if action == "start":
|
||||
start_execution(module, sfn_client)
|
||||
else:
|
||||
stop_execution(module, sfn_client)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,583 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# (c) 2017, René Moser <mail@renemoser.net>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cs_service_offering
|
||||
description:
|
||||
- Create and delete service offerings for guest and system VMs.
|
||||
- Update display_text of existing service offering.
|
||||
short_description: Manages service offerings on Apache CloudStack based clouds.
|
||||
version_added: '2.5'
|
||||
author: René Moser (@resmo)
|
||||
options:
|
||||
disk_bytes_read_rate:
|
||||
description:
|
||||
- Bytes read rate of the disk offering.
|
||||
type: int
|
||||
aliases: [ bytes_read_rate ]
|
||||
disk_bytes_write_rate:
|
||||
description:
|
||||
- Bytes write rate of the disk offering.
|
||||
type: int
|
||||
aliases: [ bytes_write_rate ]
|
||||
cpu_number:
|
||||
description:
|
||||
- The number of CPUs of the service offering.
|
||||
type: int
|
||||
cpu_speed:
|
||||
description:
|
||||
- The CPU speed of the service offering in MHz.
|
||||
type: int
|
||||
limit_cpu_usage:
|
||||
description:
|
||||
- Restrict the CPU usage to committed service offering.
|
||||
type: bool
|
||||
deployment_planner:
|
||||
description:
|
||||
- The deployment planner heuristics used to deploy a VM of this offering.
|
||||
- If not set, the value of global config I(vm.deployment.planner) is used.
|
||||
type: str
|
||||
display_text:
|
||||
description:
|
||||
- Display text of the service offering.
|
||||
- If not set, I(name) will be used as I(display_text) while creating.
|
||||
type: str
|
||||
domain:
|
||||
description:
|
||||
- Domain the service offering is related to.
|
||||
- Public for all domains and subdomains if not set.
|
||||
type: str
|
||||
host_tags:
|
||||
description:
|
||||
- The host tags for this service offering.
|
||||
type: list
|
||||
aliases:
|
||||
- host_tag
|
||||
hypervisor_snapshot_reserve:
|
||||
description:
|
||||
- Hypervisor snapshot reserve space as a percent of a volume.
|
||||
- Only for managed storage using Xen or VMware.
|
||||
type: int
|
||||
is_iops_customized:
|
||||
description:
|
||||
- Whether compute offering iops is custom or not.
|
||||
type: bool
|
||||
aliases: [ disk_iops_customized ]
|
||||
disk_iops_read_rate:
|
||||
description:
|
||||
- IO requests read rate of the disk offering.
|
||||
type: int
|
||||
disk_iops_write_rate:
|
||||
description:
|
||||
- IO requests write rate of the disk offering.
|
||||
type: int
|
||||
disk_iops_max:
|
||||
description:
|
||||
- Max. iops of the compute offering.
|
||||
type: int
|
||||
disk_iops_min:
|
||||
description:
|
||||
- Min. iops of the compute offering.
|
||||
type: int
|
||||
is_system:
|
||||
description:
|
||||
- Whether it is a system VM offering or not.
|
||||
type: bool
|
||||
default: no
|
||||
is_volatile:
|
||||
description:
|
||||
- Whether the virtual machine needs to be volatile or not.
|
||||
- Every reboot of VM the root disk is detached then destroyed and a fresh root disk is created and attached to VM.
|
||||
type: bool
|
||||
memory:
|
||||
description:
|
||||
- The total memory of the service offering in MB.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Name of the service offering.
|
||||
type: str
|
||||
required: true
|
||||
network_rate:
|
||||
description:
|
||||
- Data transfer rate in Mb/s allowed.
|
||||
- Supported only for non-system offering and system offerings having I(system_vm_type=domainrouter).
|
||||
type: int
|
||||
offer_ha:
|
||||
description:
|
||||
- Whether HA is set for the service offering.
|
||||
type: bool
|
||||
default: no
|
||||
provisioning_type:
|
||||
description:
|
||||
- Provisioning type used to create volumes.
|
||||
type: str
|
||||
choices:
|
||||
- thin
|
||||
- sparse
|
||||
- fat
|
||||
service_offering_details:
|
||||
description:
|
||||
- Details for planner, used to store specific parameters.
|
||||
- A list of dictionaries having keys C(key) and C(value).
|
||||
type: list
|
||||
state:
|
||||
description:
|
||||
- State of the service offering.
|
||||
type: str
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
default: present
|
||||
storage_type:
|
||||
description:
|
||||
- The storage type of the service offering.
|
||||
type: str
|
||||
choices:
|
||||
- local
|
||||
- shared
|
||||
system_vm_type:
|
||||
description:
|
||||
- The system VM type.
|
||||
- Required if I(is_system=yes).
|
||||
type: str
|
||||
choices:
|
||||
- domainrouter
|
||||
- consoleproxy
|
||||
- secondarystoragevm
|
||||
storage_tags:
|
||||
description:
|
||||
- The storage tags for this service offering.
|
||||
type: list
|
||||
aliases:
|
||||
- storage_tag
|
||||
is_customized:
|
||||
description:
|
||||
- Whether the offering is customizable or not.
|
||||
type: bool
|
||||
version_added: '2.8'
|
||||
extends_documentation_fragment: cloudstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Create a non-volatile compute service offering with local storage
|
||||
cs_service_offering:
|
||||
name: Micro
|
||||
display_text: Micro 512mb 1cpu
|
||||
cpu_number: 1
|
||||
cpu_speed: 2198
|
||||
memory: 512
|
||||
host_tags: eco
|
||||
storage_type: local
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Create a volatile compute service offering with shared storage
|
||||
cs_service_offering:
|
||||
name: Tiny
|
||||
display_text: Tiny 1gb 1cpu
|
||||
cpu_number: 1
|
||||
cpu_speed: 2198
|
||||
memory: 1024
|
||||
storage_type: shared
|
||||
is_volatile: yes
|
||||
host_tags: eco
|
||||
storage_tags: eco
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Create or update a volatile compute service offering with shared storage
|
||||
cs_service_offering:
|
||||
name: Tiny
|
||||
display_text: Tiny 1gb 1cpu
|
||||
cpu_number: 1
|
||||
cpu_speed: 2198
|
||||
memory: 1024
|
||||
storage_type: shared
|
||||
is_volatile: yes
|
||||
host_tags: eco
|
||||
storage_tags: eco
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Create or update a custom compute service offering
|
||||
cs_service_offering:
|
||||
name: custom
|
||||
display_text: custom compute offer
|
||||
is_customized: yes
|
||||
storage_type: shared
|
||||
host_tags: eco
|
||||
storage_tags: eco
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Remove a compute service offering
|
||||
cs_service_offering:
|
||||
name: Tiny
|
||||
state: absent
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Create or update a system offering for the console proxy
|
||||
cs_service_offering:
|
||||
name: System Offering for Console Proxy 2GB
|
||||
display_text: System Offering for Console Proxy 2GB RAM
|
||||
is_system: yes
|
||||
system_vm_type: consoleproxy
|
||||
cpu_number: 1
|
||||
cpu_speed: 2198
|
||||
memory: 2048
|
||||
storage_type: shared
|
||||
storage_tags: perf
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Remove a system offering
|
||||
cs_service_offering:
|
||||
name: System Offering for Console Proxy 2GB
|
||||
is_system: yes
|
||||
state: absent
|
||||
delegate_to: localhost
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
---
|
||||
id:
|
||||
description: UUID of the service offering
|
||||
returned: success
|
||||
type: str
|
||||
sample: a6f7a5fc-43f8-11e5-a151-feff819cdc9f
|
||||
cpu_number:
|
||||
description: Number of CPUs in the service offering
|
||||
returned: success
|
||||
type: int
|
||||
sample: 4
|
||||
cpu_speed:
|
||||
description: Speed of CPUs in MHz in the service offering
|
||||
returned: success
|
||||
type: int
|
||||
sample: 2198
|
||||
disk_iops_max:
|
||||
description: Max iops of the disk offering
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1000
|
||||
disk_iops_min:
|
||||
description: Min iops of the disk offering
|
||||
returned: success
|
||||
type: int
|
||||
sample: 500
|
||||
disk_bytes_read_rate:
|
||||
description: Bytes read rate of the service offering
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1000
|
||||
disk_bytes_write_rate:
|
||||
description: Bytes write rate of the service offering
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1000
|
||||
disk_iops_read_rate:
|
||||
description: IO requests per second read rate of the service offering
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1000
|
||||
disk_iops_write_rate:
|
||||
description: IO requests per second write rate of the service offering
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1000
|
||||
created:
|
||||
description: Date the offering was created
|
||||
returned: success
|
||||
type: str
|
||||
sample: 2017-11-19T10:48:59+0000
|
||||
display_text:
|
||||
description: Display text of the offering
|
||||
returned: success
|
||||
type: str
|
||||
sample: Micro 512mb 1cpu
|
||||
domain:
|
||||
description: Domain the offering is into
|
||||
returned: success
|
||||
type: str
|
||||
sample: ROOT
|
||||
host_tags:
|
||||
description: List of host tags
|
||||
returned: success
|
||||
type: list
|
||||
sample: [ 'eco' ]
|
||||
storage_tags:
|
||||
description: List of storage tags
|
||||
returned: success
|
||||
type: list
|
||||
sample: [ 'eco' ]
|
||||
is_system:
|
||||
description: Whether the offering is for system VMs or not
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
is_iops_customized:
|
||||
description: Whether the offering uses custom IOPS or not
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
is_volatile:
|
||||
description: Whether the offering is volatile or not
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
limit_cpu_usage:
|
||||
description: Whether the CPU usage is restricted to committed service offering
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
memory:
|
||||
description: Memory of the system offering
|
||||
returned: success
|
||||
type: int
|
||||
sample: 512
|
||||
name:
|
||||
description: Name of the system offering
|
||||
returned: success
|
||||
type: str
|
||||
sample: Micro
|
||||
offer_ha:
|
||||
description: Whether HA support is enabled in the offering or not
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
provisioning_type:
|
||||
description: Provisioning type used to create volumes
|
||||
returned: success
|
||||
type: str
|
||||
sample: thin
|
||||
storage_type:
|
||||
description: Storage type used to create volumes
|
||||
returned: success
|
||||
type: str
|
||||
sample: shared
|
||||
system_vm_type:
|
||||
description: System VM type of this offering
|
||||
returned: success
|
||||
type: str
|
||||
sample: consoleproxy
|
||||
service_offering_details:
|
||||
description: Additioanl service offering details
|
||||
returned: success
|
||||
type: dict
|
||||
sample: "{'vgpuType': 'GRID K180Q','pciDevice':'Group of NVIDIA Corporation GK107GL [GRID K1] GPUs'}"
|
||||
network_rate:
|
||||
description: Data transfer rate in megabits per second allowed
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1000
|
||||
is_customized:
|
||||
description: Whether the offering is customizable or not
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
version_added: '2.8'
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.cloudstack import (
|
||||
AnsibleCloudStack,
|
||||
cs_argument_spec,
|
||||
cs_required_together,
|
||||
)
|
||||
|
||||
|
||||
class AnsibleCloudStackServiceOffering(AnsibleCloudStack):
|
||||
|
||||
def __init__(self, module):
|
||||
super(AnsibleCloudStackServiceOffering, self).__init__(module)
|
||||
self.returns = {
|
||||
'cpunumber': 'cpu_number',
|
||||
'cpuspeed': 'cpu_speed',
|
||||
'deploymentplanner': 'deployment_planner',
|
||||
'diskBytesReadRate': 'disk_bytes_read_rate',
|
||||
'diskBytesWriteRate': 'disk_bytes_write_rate',
|
||||
'diskIopsReadRate': 'disk_iops_read_rate',
|
||||
'diskIopsWriteRate': 'disk_iops_write_rate',
|
||||
'maxiops': 'disk_iops_max',
|
||||
'miniops': 'disk_iops_min',
|
||||
'hypervisorsnapshotreserve': 'hypervisor_snapshot_reserve',
|
||||
'iscustomized': 'is_customized',
|
||||
'iscustomizediops': 'is_iops_customized',
|
||||
'issystem': 'is_system',
|
||||
'isvolatile': 'is_volatile',
|
||||
'limitcpuuse': 'limit_cpu_usage',
|
||||
'memory': 'memory',
|
||||
'networkrate': 'network_rate',
|
||||
'offerha': 'offer_ha',
|
||||
'provisioningtype': 'provisioning_type',
|
||||
'serviceofferingdetails': 'service_offering_details',
|
||||
'storagetype': 'storage_type',
|
||||
'systemvmtype': 'system_vm_type',
|
||||
'tags': 'storage_tags',
|
||||
}
|
||||
|
||||
def get_service_offering(self):
|
||||
args = {
|
||||
'name': self.module.params.get('name'),
|
||||
'domainid': self.get_domain(key='id'),
|
||||
'issystem': self.module.params.get('is_system'),
|
||||
'systemvmtype': self.module.params.get('system_vm_type'),
|
||||
}
|
||||
service_offerings = self.query_api('listServiceOfferings', **args)
|
||||
if service_offerings:
|
||||
return service_offerings['serviceoffering'][0]
|
||||
|
||||
def present_service_offering(self):
|
||||
service_offering = self.get_service_offering()
|
||||
if not service_offering:
|
||||
service_offering = self._create_offering(service_offering)
|
||||
else:
|
||||
service_offering = self._update_offering(service_offering)
|
||||
|
||||
return service_offering
|
||||
|
||||
def absent_service_offering(self):
|
||||
service_offering = self.get_service_offering()
|
||||
if service_offering:
|
||||
self.result['changed'] = True
|
||||
if not self.module.check_mode:
|
||||
args = {
|
||||
'id': service_offering['id'],
|
||||
}
|
||||
self.query_api('deleteServiceOffering', **args)
|
||||
return service_offering
|
||||
|
||||
def _create_offering(self, service_offering):
|
||||
self.result['changed'] = True
|
||||
|
||||
system_vm_type = self.module.params.get('system_vm_type')
|
||||
is_system = self.module.params.get('is_system')
|
||||
|
||||
required_params = []
|
||||
if is_system and not system_vm_type:
|
||||
required_params.append('system_vm_type')
|
||||
self.module.fail_on_missing_params(required_params=required_params)
|
||||
|
||||
args = {
|
||||
'name': self.module.params.get('name'),
|
||||
'displaytext': self.get_or_fallback('display_text', 'name'),
|
||||
'bytesreadrate': self.module.params.get('disk_bytes_read_rate'),
|
||||
'byteswriterate': self.module.params.get('disk_bytes_write_rate'),
|
||||
'cpunumber': self.module.params.get('cpu_number'),
|
||||
'cpuspeed': self.module.params.get('cpu_speed'),
|
||||
'customizediops': self.module.params.get('is_iops_customized'),
|
||||
'deploymentplanner': self.module.params.get('deployment_planner'),
|
||||
'domainid': self.get_domain(key='id'),
|
||||
'hosttags': self.module.params.get('host_tags'),
|
||||
'hypervisorsnapshotreserve': self.module.params.get('hypervisor_snapshot_reserve'),
|
||||
'iopsreadrate': self.module.params.get('disk_iops_read_rate'),
|
||||
'iopswriterate': self.module.params.get('disk_iops_write_rate'),
|
||||
'maxiops': self.module.params.get('disk_iops_max'),
|
||||
'miniops': self.module.params.get('disk_iops_min'),
|
||||
'issystem': is_system,
|
||||
'isvolatile': self.module.params.get('is_volatile'),
|
||||
'memory': self.module.params.get('memory'),
|
||||
'networkrate': self.module.params.get('network_rate'),
|
||||
'offerha': self.module.params.get('offer_ha'),
|
||||
'provisioningtype': self.module.params.get('provisioning_type'),
|
||||
'serviceofferingdetails': self.module.params.get('service_offering_details'),
|
||||
'storagetype': self.module.params.get('storage_type'),
|
||||
'systemvmtype': system_vm_type,
|
||||
'tags': self.module.params.get('storage_tags'),
|
||||
'limitcpuuse': self.module.params.get('limit_cpu_usage'),
|
||||
'customized': self.module.params.get('is_customized')
|
||||
}
|
||||
if not self.module.check_mode:
|
||||
res = self.query_api('createServiceOffering', **args)
|
||||
service_offering = res['serviceoffering']
|
||||
return service_offering
|
||||
|
||||
def _update_offering(self, service_offering):
|
||||
args = {
|
||||
'id': service_offering['id'],
|
||||
'name': self.module.params.get('name'),
|
||||
'displaytext': self.get_or_fallback('display_text', 'name'),
|
||||
}
|
||||
if self.has_changed(args, service_offering):
|
||||
self.result['changed'] = True
|
||||
|
||||
if not self.module.check_mode:
|
||||
res = self.query_api('updateServiceOffering', **args)
|
||||
service_offering = res['serviceoffering']
|
||||
return service_offering
|
||||
|
||||
def get_result(self, service_offering):
|
||||
super(AnsibleCloudStackServiceOffering, self).get_result(service_offering)
|
||||
if service_offering:
|
||||
if 'hosttags' in service_offering:
|
||||
self.result['host_tags'] = service_offering['hosttags'].split(',') or [service_offering['hosttags']]
|
||||
|
||||
# Prevent confusion, the api returns a tags key for storage tags.
|
||||
if 'tags' in service_offering:
|
||||
self.result['storage_tags'] = service_offering['tags'].split(',') or [service_offering['tags']]
|
||||
if 'tags' in self.result:
|
||||
del self.result['tags']
|
||||
|
||||
return self.result
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = cs_argument_spec()
|
||||
argument_spec.update(dict(
|
||||
name=dict(required=True),
|
||||
display_text=dict(),
|
||||
cpu_number=dict(type='int'),
|
||||
cpu_speed=dict(type='int'),
|
||||
limit_cpu_usage=dict(type='bool'),
|
||||
deployment_planner=dict(),
|
||||
domain=dict(),
|
||||
host_tags=dict(type='list', aliases=['host_tag']),
|
||||
hypervisor_snapshot_reserve=dict(type='int'),
|
||||
disk_bytes_read_rate=dict(type='int', aliases=['bytes_read_rate']),
|
||||
disk_bytes_write_rate=dict(type='int', aliases=['bytes_write_rate']),
|
||||
disk_iops_read_rate=dict(type='int'),
|
||||
disk_iops_write_rate=dict(type='int'),
|
||||
disk_iops_max=dict(type='int'),
|
||||
disk_iops_min=dict(type='int'),
|
||||
is_system=dict(type='bool', default=False),
|
||||
is_volatile=dict(type='bool'),
|
||||
is_iops_customized=dict(type='bool', aliases=['disk_iops_customized']),
|
||||
memory=dict(type='int'),
|
||||
network_rate=dict(type='int'),
|
||||
offer_ha=dict(type='bool'),
|
||||
provisioning_type=dict(choices=['thin', 'sparse', 'fat']),
|
||||
service_offering_details=dict(type='list'),
|
||||
storage_type=dict(choices=['local', 'shared']),
|
||||
system_vm_type=dict(choices=['domainrouter', 'consoleproxy', 'secondarystoragevm']),
|
||||
storage_tags=dict(type='list', aliases=['storage_tag']),
|
||||
state=dict(choices=['present', 'absent'], default='present'),
|
||||
is_customized=dict(type='bool'),
|
||||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
required_together=cs_required_together(),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
acs_so = AnsibleCloudStackServiceOffering(module)
|
||||
|
||||
state = module.params.get('state')
|
||||
if state == "absent":
|
||||
service_offering = acs_so.absent_service_offering()
|
||||
else:
|
||||
service_offering = acs_so.present_service_offering()
|
||||
|
||||
result = acs_so.get_result(service_offering)
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in a new issue