-
Notifications
You must be signed in to change notification settings - Fork 397
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add codedeploy_application module
- Loading branch information
Showing
5 changed files
with
315 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright: (c) 2023, JIHUN KIM <[email protected]> | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
DOCUMENTATION = r""" | ||
--- | ||
module: codedeploy_application | ||
version_added: 6.4.0 | ||
short_description: Manage applications in AWS CodeDeploy | ||
description: | ||
- The M(community.aws.codedeploy_application) module allows you to create, update, and delete of CodeDeploy applications. | ||
author: | ||
- JIHUN KIM (@shblue21) | ||
options: | ||
application_name: | ||
description: The name of the application. | ||
required: true | ||
type: str | ||
new_application_name: | ||
description: The new name of the application, if you want to update the application name. | ||
required: false | ||
type: str | ||
state: | ||
description: Create (C(present)) or delete (C(absent)) application. | ||
required: true | ||
choices: ['present', 'absent'] | ||
default: 'present' | ||
type: str | ||
extends_documentation_fragment: | ||
- amazon.aws.common.modules | ||
- amazon.aws.region.modules | ||
- amazon.aws.boto3 | ||
""" | ||
|
||
EXAMPLES = r""" | ||
# Create a new codedeploy application | ||
- community.aws.codedeploy_application: | ||
application_name: codedeploy-app | ||
state: present | ||
# Update a codedeploy application name | ||
- community.aws.codedeploy_application: | ||
application_name: codedeploy-app | ||
new_application_name: codedeploy-app-new | ||
state: present | ||
# Delete a codedeploy application | ||
- community.aws.codedeploy_application: | ||
application_name: codedeploy-app | ||
state: absent | ||
""" | ||
|
||
RETURN = r""" | ||
application: | ||
description: Returns information about the application. | ||
returned: When I(state) is C(present) | ||
type: complex | ||
contains: | ||
application_id: | ||
description: The application ID. | ||
type: str | ||
sample: 970e1389-d1c3-4c3e-8d31-1e1a5ad47d54 | ||
returned: always | ||
application_name: | ||
description: The application name. | ||
type: str | ||
sample: codedeploy-app | ||
returned: always | ||
compute_platform: | ||
description: The destination platform type for deployment of the application. | ||
type: str | ||
sample: Server | ||
returned: always | ||
create_time: | ||
description: The time at which the application was created. | ||
type: str | ||
sample: 2023-09-15T11:25:34.943000+09:00 | ||
returned: always | ||
linked_to_git_hub: | ||
description: True if the user has authenticated with GitHub for the specified application. | ||
type: bool | ||
sample: False | ||
returned: always | ||
github_account_name: | ||
description: The name for a connection to a GitHub account. | ||
type: str | ||
sample: github-account-name | ||
""" | ||
|
||
try: | ||
import botocore | ||
except ImportError: | ||
pass # Handled by AnsibleAWSModule | ||
|
||
from ansible_collections.amazon.aws.plugins.module_utils.arn import validate_aws_arn | ||
from ansible_collections.amazon.aws.plugins.module_utils.botocore import is_boto3_error_code | ||
from ansible_collections.amazon.aws.plugins.module_utils.exceptions import AnsibleAWSError | ||
|
||
from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule | ||
from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict | ||
|
||
|
||
class CodeDeployAnsibleAWSError(AnsibleAWSError): | ||
pass | ||
|
||
|
||
def _get_application(client, applicationName): | ||
try: | ||
response = client.get_application(applicationName=applicationName) | ||
return response | ||
except is_boto3_error_code("ApplicationDoesNotExistException"): | ||
return None | ||
except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: | ||
raise CodeDeployAnsibleAWSError(exception=e, message="couldn't get application") | ||
|
||
|
||
def _create_application(client, module): | ||
try: | ||
response = client.create_application( | ||
applicationName=module.params["application_name"], | ||
computePlatform=module.params["compute_platform"], | ||
) | ||
return response | ||
except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: | ||
raise CodeDeployAnsibleAWSError(exception=e, message="couldn't create application") | ||
|
||
|
||
def _update_application(client, module): | ||
parmas = {} | ||
parmas["applicationName"] = module.params["application_name"] | ||
if module.params["new_application_name"]: | ||
parmas["newApplicationName"] = module.params["new_application_name"] | ||
try: | ||
response = client.update_application(parmas) | ||
return response # It'll be None | ||
except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: | ||
raise CodeDeployAnsibleAWSError(exception=e, message="couldn't update application") | ||
|
||
|
||
def _delete_application(client, module): | ||
try: | ||
response = client.delete_application(applicationName=module.params["application_name"]) | ||
return response # It'll be None | ||
except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: | ||
raise CodeDeployAnsibleAWSError(exception=e, message="couldn't delete application") | ||
|
||
|
||
def ensure_application_present(client, module): | ||
changed = False | ||
state = None | ||
application_name = module.params["application_name"] | ||
if _get_application(client, module.params["application_name"]) is None: | ||
state = "create" | ||
module.debug("application does not exist, create application") | ||
if not module.check_mode: | ||
_response = _create_application(client, module) | ||
changed = True | ||
else: | ||
module.debug("application already exists, update application") | ||
state = "update" | ||
if not module.check_mode: | ||
_response = _update_application(client, module) | ||
application_name = module.params.get("new_application_name") if module.params.get("new_application_name") else module.params["application_name"] | ||
changed = True | ||
result = {"changed": changed} | ||
|
||
if module.check_mode and state == "create": | ||
result["application"] = None | ||
return result | ||
else: | ||
application = _get_application(client, application_name) | ||
application_result = camel_dict_to_snake_dict(application) | ||
result.update(application_result) | ||
return result | ||
|
||
|
||
def ensure_application_absent(client, module): | ||
changed = False | ||
if _get_application(client, module.params["application_name"]) is None: | ||
module.debug("application does not exist, so it is already absent") | ||
return {"changed": changed} | ||
else: | ||
module.debug("application exists, delete application") | ||
if not module.check_mode: | ||
_response = _delete_application(client, module) | ||
changed = True | ||
return {"changed": changed} | ||
|
||
|
||
def main(): | ||
argument_spec = dict( | ||
application_name=dict(type="str", required=True), | ||
new_application_name=dict(type="str", required=False), | ||
state=dict(type="str", choices=["present", "absent"], default="present"), | ||
compute_platform=dict(type="str", required=False, choices=["Lambda", "Server", "ECS"]), | ||
) | ||
|
||
module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) | ||
|
||
client = module.client("codedeploy") | ||
|
||
try: | ||
if module.params["state"] == "present": | ||
result = ensure_application_present(client, module) | ||
elif module.params["state"] == "absent": | ||
result = ensure_application_absent(client, module) | ||
except botocore.exceptions.ClientError as e: | ||
module.fail_json_aws(e) | ||
|
||
module.exit_json(**result) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
cloud/aws |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
dependencies: [] |
95 changes: 95 additions & 0 deletions
95
tests/integration/targets/codedeploy_application/tasks/main.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
--- | ||
- module_defaults: | ||
group/aws: | ||
access_key: "{{ aws_access_key }}" | ||
secret_key: "{{ aws_secret_key }}" | ||
session_token: "{{ security_token | default(omit) }}" | ||
region: "{{ aws_region }}" | ||
block: | ||
# ============================================================ | ||
- name: Create a application (CHECK MODE) | ||
codedeploy_application: | ||
application_name: "{{ resource_prefix }}_app" | ||
compute_platform: Lambda | ||
state: present | ||
register: output | ||
check_mode: yes | ||
- assert: | ||
that: | ||
- output is changed | ||
|
||
- name: Create a application | ||
codedeploy_application: | ||
application_name: "{{ resource_prefix }}_app" | ||
compute_platform: Lambda | ||
state: present | ||
register: output | ||
- assert: | ||
that: | ||
- output is changed | ||
- output.application.application_name == '{{ resource_prefix }}_app' | ||
|
||
- name: Update application name (CHECK MODE) | ||
codedeploy_application: | ||
application_name: "{{ resource_prefix }}_app" | ||
new_application_name: "{{ resource_prefix }}_app2" | ||
state: present | ||
register: output | ||
check_mode: yes | ||
- assert: | ||
that: | ||
- output is changed | ||
|
||
- name: Update application name | ||
codedeploy_application: | ||
application_name: "{{ resource_prefix }}_app" | ||
new_application_name: "{{ resource_prefix }}_app2" | ||
state: present | ||
register: output | ||
- assert: | ||
that: | ||
- output is changed | ||
- output.application.application_name == '{{ resource_prefix }}_app2' | ||
|
||
# ============================================================ | ||
|
||
- name: Delete a application (CHECK MODE) | ||
codedeploy_application: | ||
application_name: "{{ resource_prefix }}_app2" | ||
state: absent | ||
register: output | ||
check_mode: yes | ||
- assert: | ||
that: | ||
- output is changed | ||
|
||
- name: Delete a application | ||
codedeploy_application: | ||
application_name: "{{ resource_prefix }}_app2" | ||
state: absent | ||
register: output | ||
- assert: | ||
that: | ||
- output is changed | ||
|
||
- name: Delete a non-existent application | ||
codedeploy_application: | ||
application_name: "{{ resource_prefix }}_app2" | ||
state: absent | ||
register: output | ||
- assert: | ||
that: | ||
- output is not changed | ||
|
||
always: | ||
- name: Delete a application | ||
codedeploy_application: | ||
application_name: "{{ resource_prefix }}_app" | ||
state: absent | ||
ignore_errors: yes | ||
|
||
- name: Delete a application_2 | ||
codedeploy_application: | ||
application_name: "{{ resource_prefix }}_app2" | ||
state: absent | ||
ignore_errors: yes |