# -*- coding: utf-8 -*-
# Copyright (c) 2020, Adam Migus <adam@migus.org>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function

__metaclass__ = type

DOCUMENTATION = r"""
name: dsv
author: Adam Migus (@amigus) <adam@migus.org>
short_description: Get secrets from Thycotic DevOps Secrets Vault
version_added: 1.0.0
description:
    - Uses the Thycotic DevOps Secrets Vault Python SDK to get Secrets from a
      DSV O(tenant) using a O(client_id) and O(client_secret).
requirements:
    - python-dsv-sdk - https://pypi.org/project/python-dsv-sdk/
options:
    _terms:
        description: The path to the secret, for example V(/staging/servers/web1).
        required: true
    tenant:
        description: The first format parameter in the default O(url_template).
        env:
            - name: DSV_TENANT
        ini:
            - section: dsv_lookup
              key: tenant
        required: true
    tld:
        default: com
        description: The top-level domain of the tenant; the second format
            parameter in the default O(url_template).
        env:
            - name: DSV_TLD
        ini:
            - section: dsv_lookup
              key: tld
        required: false
    client_id:
        description: The client_id with which to request the Access Grant.
        env:
            - name: DSV_CLIENT_ID
        ini:
            - section: dsv_lookup
              key: client_id
        required: true
    client_secret:
        description: The client secret associated with the specific O(client_id).
        env:
            - name: DSV_CLIENT_SECRET
        ini:
            - section: dsv_lookup
              key: client_secret
        required: true
    url_template:
        default: https://{}.secretsvaultcloud.{}/v1
        description: The path to prepend to the base URL to form a valid REST
            API request.
        env:
            - name: DSV_URL_TEMPLATE
        ini:
            - section: dsv_lookup
              key: url_template
        required: false
"""

RETURN = r"""
_list:
    description:
        - One or more JSON responses to C(GET /secrets/{path}).
        - See U(https://dsv.thycotic.com/api/index.html#operation/getSecret).
    type: list
    elements: dict
"""

EXAMPLES = r"""
- hosts: localhost
  vars:
      secret: "{{ lookup('community.general.dsv', '/test/secret') }}"
  tasks:
      - ansible.builtin.debug:
          msg: 'the password is {{ secret["data"]["password"] }}'
"""

from ansible.errors import AnsibleError, AnsibleOptionsError

sdk_is_missing = False

try:
    from thycotic.secrets.vault import (
        SecretsVault,
        SecretsVaultError,
    )
except ImportError:
    sdk_is_missing = True

from ansible.utils.display import Display
from ansible.plugins.lookup import LookupBase


display = Display()


class LookupModule(LookupBase):
    @staticmethod
    def Client(vault_parameters):
        try:
            vault = SecretsVault(**vault_parameters)
            return vault
        except TypeError:
            raise AnsibleError("python-dsv-sdk==0.0.1 must be installed to use this plugin")

    def run(self, terms, variables, **kwargs):
        if sdk_is_missing:
            raise AnsibleError("python-dsv-sdk==0.0.1 must be installed to use this plugin")

        self.set_options(var_options=variables, direct=kwargs)

        vault = LookupModule.Client(
            {
                "tenant": self.get_option("tenant"),
                "client_id": self.get_option("client_id"),
                "client_secret": self.get_option("client_secret"),
                "tld": self.get_option("tld"),
                "url_template": self.get_option("url_template"),
            }
        )
        result = []

        for term in terms:
            display.debug("dsv_lookup term: %s" % term)
            try:
                path = term.lstrip("[/:]")

                if path == "":
                    raise AnsibleOptionsError("Invalid secret path: %s" % term)

                display.vvv(u"DevOps Secrets Vault GET /secrets/%s" % path)
                result.append(vault.get_secret_json(path))
            except SecretsVaultError as error:
                raise AnsibleError(
                    "DevOps Secrets Vault lookup failure: %s" % error.message
                )
        return result
