# Copyright 2014 - Rackspace Hosting.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from keystoneauth1 import identity
from keystoneauth1 import loading as ka_loading
from keystoneauth1 import session as ks_session
import keystoneclient.exceptions as kc_exception
from keystoneclient.v3 import client as kc_v3
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import importutils

from solum.common import context
from solum.common import exception
from solum.i18n import _

LOG = logging.getLogger(__name__)

trust_opts = [
    cfg.ListOpt('trusts_delegated_roles',
                default=['solum_assembly_update'],
                help=_('Subset of trustor roles to be delegated to solum.')),
]
cfg.CONF.register_opts(trust_opts)
cfg.CONF.import_opt('www_authenticate_uri', 'keystonemiddleware.auth_token',
                    group='keystone_authtoken')

AUTH_OPTS = [
    cfg.StrOpt('keystone_version',
               default='3',
               help='The keystone version to use with Solum'),
]


def list_opts():
    yield None, AUTH_OPTS
    yield None, trust_opts


cfg.CONF.register_opts(AUTH_OPTS)

cfg.CONF.import_opt('lp_operator_user', 'solum.worker.config', group='worker')
cfg.CONF.import_opt('lp_operator_password',
                    'solum.worker.config', group='worker')
cfg.CONF.import_opt('lp_operator_tenant_name',
                    'solum.worker.config', group='worker')


class KeystoneClient(object):
    """Keystone client wrapper to initialize the right version of the client.

       The version to use is specified in solum.conf
       """

    def __new__(self, context):
        ks_version = cfg.CONF.get('keystone_version')
        if ks_version == '3':
            return KeystoneClientV3(context)
        else:
            msg = 'Unsupported version of keystone: %s', ks_version
            LOG.error(msg)
            raise exception.AuthorizationFailure(client='keystone',
                                                 message=msg)


class KeystoneClientV3(object):
    """Keystone client wrapper so we can encapsulate logic in one place."""

    def __init__(self, context):
        # If a trust_id is specified in the context, we immediately
        # authenticate so we can populate the context with a trust token
        # otherwise, we delay client authentication until needed to avoid
        # unnecessary calls to keystone.
        #
        # Note that when you obtain a token using a trust, it cannot be
        # used to reauthenticate and get another token, so we have to
        # get a new trust-token even if context.auth_token is set.
        #
        # - context.auth_url is expected to contain a versioned keystone
        #   path, we will work with either a v2.0 or v3 path
        self.context = context
        self._client = None
        self._admin_client = None
        self._lp_admin_client = None

        if self.context and self.context.auth_url:
            self.endpoint = self.context.auth_url.replace('v2.0', 'v3')