#!/usr/bin/python
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
ANSIBLE_METADATA = {'status': ['preview'],
                    'supported_by': 'community',
                    'metadata_version': '1.1'}

DOCUMENTATION = '''
---
module: ssm_parameter_store
short_description: Manage key-value pairs in aws parameter store.
description:
  - Manage key-value pairs in aws parameter store.
version_added: "2.5"
options:
  name:
    description:
      - parameter key name.
    required: true
  description:
    description:
      - parameter key desciption.
    required: false
  value:
    description:
      - Parameter value.
    required: false
  state:
    description:
      - Creates or modifies an existing parameter
      - Deletes a parameter
    required: false
    choices: ['present', 'absent']
    default: present
  string_type:
    description:
      - Parameter String type
    required: false
    choices: ['String', 'StringList', 'SecureString']
    default: String
  decryption:
    description:
      - Work with SecureString type to get plain text secrets
      - Boolean
    required: false
    default: True
  key_id:
    description:
      - aws KMS key to decrypt the secrets.
    required: false
    default: aws/ssm (this key is automatically generated at the first parameter created).
  overwrite:
    description:
      - Overwrite the value when create or update parameter
      - Boolean
    required: false
    default: True
  region:
    description:
      - region.
    required: false
author: Bill Wang (ozbillwang@gmail.com)
extends_documentation_fragment: aws
requirements: [ botocore, boto3 ]
'''

EXAMPLES = '''
- name: Create or update key/value pair in aws parameter store
  ssm_parameter_store:
    name: "Hello"
    description: "This is your first key"
    value: "World"

- name: Delete the key
  ssm_parameter_store:
    name: "Hello"
    state: absent

- name: Create or update secure key/value pair with default kms key (aws/ssm)
  ssm_parameter_store:
    name: "Hello"
    description: "This is your first key"
    string_type: "SecureString"
    value: "World"

- name: Create or update secure key/value pair with nominated kms key
  ssm_parameter_store:
    name: "Hello"
    description: "This is your first key"
    string_type: "SecureString"
    key_id: "alias/demo"
    value: "World"

- name: recommend to use with ssm lookup plugin
  debug: msg="{{ lookup('ssm', 'hello') }}"
'''

RETURN = '''
put_parameter:
    description: Add one or more paramaters to the system.
    returned: success
    type: dictionary
delete_parameter:
    description: Delete a parameter from the system.
    returned: success
    type: dictionary
'''

import traceback
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ec2 import HAS_BOTO3, camel_dict_to_snake_dict
from ansible.module_utils.ec2 import boto3_conn, ec2_argument_spec, get_aws_connection_info

try:
    from botocore.exceptions import ClientError, NoCredentialsError
except ImportError:
    pass  # will be captured by imported HAS_BOTO3


def create_update_parameter(client, module):
    changed = False
    response = {}

    args = dict(
        Name=module.params.get('name'),
        Value=module.params.get('value'),
        Type=module.params.get('string_type'),
        Overwrite=module.params.get('overwrite')
    )

    if module.params.get('description'):
        args.update(Description=module.params.get('description'))

    if module.params.get('string_type') == 'SecureString':
        args.update(KeyId=module.params.get('key_id'))

    try:
        response = client.put_parameter(**args)
        changed = True
    except ClientError as e:
        module.fail_json(msg=e.message, exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))

    return changed, response


def delete_parameter(client, module):
    changed = False
    response = {}

    try:
        get_response = client.get_parameters(
            Names=[module.params.get('name')]
        )
    except ClientError as e:
        module.fail_json(msg=e.message, exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))

    if get_response['Parameters']:
        try:
            response = client.delete_parameter(
                Name=module.params.get('name')
            )
            changed = True
        except ClientError as e:
            module.fail_json(msg=e.message, exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))

    return changed, response


def main():

    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(
            name=dict(required=True),
            description=dict(),
            value=dict(required=False),
            state=dict(default='present', choices=['present', 'absent']),
            string_type=dict(default='String', choices=['String', 'StringList', 'SecureString']),
            decryption=dict(default=True, type='bool'),
            key_id=dict(default="alias/aws/ssm"),
            overwrite=dict(default=True, type='bool'),
            region=dict(required=False),
        )
    )

    module = AnsibleModule(argument_spec=argument_spec)

    if not HAS_BOTO3:
        module.fail_json(msg='boto3 are required.')
    state = module.params.get('state')
    try:
        region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
        client = boto3_conn(module, conn_type='client', resource='ssm', region=region, endpoint=ec2_url, **aws_connect_kwargs)
    except NoCredentialsError as e:
        module.fail_json(msg="Can't authorize connection - %s" % str(e))

    invocations = {
        "present": create_update_parameter,
        "absent": delete_parameter,
    }
    (changed, response) = invocations[state](client, module)
    module.exit_json(changed=changed, response=response)

if __name__ == '__main__':
    main()
