#    Copyright 2016 Mirantis, Inc.
#
#    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.

import pytest

from tcp_tests import logger
from tcp_tests.helpers import ext
from tcp_tests.managers import saltmanager

LOG = logger.logger


@pytest.fixture(scope='session')
def salt_actions(config, underlay_actions):
    """Fixture that provides various actions for salt

    :param config: fixture provides oslo.config
    :param underlay: fixture provides underlay manager
    :rtype: SaltManager
    """
    return saltmanager.SaltManager(config, underlay_actions)


@pytest.mark.revert_snapshot(ext.SNAPSHOT.salt_deployed)
@pytest.fixture(scope='function')
def salt_deployed(revert_snapshot, request, config,
                  hardware, underlay, salt_actions, snapshot, grab_versions):
    """Fixture to get or install salt service on environment

    :param revert_snapshot: fixture that reverts snapshot that is specified
                            in test with @pytest.mark.revert_snapshot(<name>)
    :param request: fixture provides pytest data
    :param config: fixture provides oslo.config
    :param hardware: fixture provides enviromnet manager
    :param underlay: fixture provides underlay manager
    :param salt_actions: fixture provides SaltManager instance
    :rtype: SaltManager

    If config.salt.salt_master_host is not set, this fixture assumes that
    the salt was not installed, and do the following:
    - install salt master and salt minions
    - make snapshot with name 'salt_deployed'
    - return SaltManager

    If config.salt.salt_master_host was set, this fixture assumes that the
    salt was already deployed, and do the following:
    - return SaltManager instance

    If you want to revert 'salt_deployed' snapshot, please use mark:
    @pytest.mark.revert_snapshot("salt_deployed")
    """
    # Create Salt cluster
    if config.salt.salt_master_host == '0.0.0.0':
        # Temporary workaround. Underlay should be extended with roles
        config.salt.salt_master_host = \
            underlay.host_by_node_role(
                node_role=ext.UNDERLAY_NODE_ROLES.salt_master)

        commands = underlay.read_template(config.salt_deploy.salt_steps_path)
        LOG.info("############ Executing command ####### {0}".format(commands))
        salt_actions.install(commands)

        salt_actions.update_ssh_data_from_minions()

        hardware.create_snapshot(ext.SNAPSHOT.salt_deployed)
        salt_actions.sync_time()

    else:
        # 1. hardware environment created and powered on
        # 2. config.underlay.ssh contains SSH access to provisioned nodes
        #    (can be passed from external config with TESTS_CONFIGS variable)
        # 3. config.tcp.* options contain access credentials to the already
        #    installed TCP API endpoint
        pass

    salt_actions.sync_time()

    return salt_actions
