Esempio n. 1
0
    def test_list_accounts(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ List all accounts that have been configured
            Given
            - Auth file contains multiple accounts

            When
            - list_auth is called

            Then
            - All the configured account credentials are listed
        """

        copy_typical_auth_contents = copy.deepcopy(TYPICAL_AUTH_CONTENTS)
        yaml_load_fixture_auth.return_value = copy_typical_auth_contents
        client = AuthConfigurationClient()
        with mocker.patch('f5cli.config.core.open',
                          new_callable=mocker.mock_open()):
            result = client.list_auth()
        assert len(result) == 5
        for index in range(0, 4):
            assert result[index].get('name') \
                   == TYPICAL_AUTH_CONTENTS[index].get('name')
Esempio n. 2
0
    def test_update_non_existing_account(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Update non-existing account
            Given
            - Auth file containing multiple accounts

            When
            - store_auth('update') is invoked with auth details

            Then
            - store_auth raises an exception when trying to update a non existing account
        """
        new_account = {'name': 'bigip4'}
        copy_typical_auth_contents = copy.deepcopy(TYPICAL_AUTH_CONTENTS)
        yaml_load_fixture_auth.return_value = copy_typical_auth_contents
        client = AuthConfigurationClient(auth=new_account)
        with pytest.raises(click.exceptions.ClickException) as error:
            with mocker.patch('f5cli.config.auth.open',
                              new_callable=mocker.mock_open()):
                client.store_auth('update')
        assert error.value.args[0] == f"Update command failed." \
                                      f" A account of bigip4 name does not exist."
Esempio n. 3
0
    def test_write_nonexist_config_directory(mocker, os_path_exists_fixture,
                                             os_path_isfile_fixture):
        """ Write Auth file into a non-exist directory
        Given
        - Config directory does not exist

        When
        - store_auth() is invoked

        Then
        - Config directory is created
        - Auth file is written to disk
        """

        mock_path_exist = os_path_exists_fixture
        mock_path_exist.return_value = False
        mock_path_is_file = os_path_isfile_fixture
        mock_path_is_file.return_value = False

        mock_make_dir = mocker.patch("f5cli.config.core.os.makedirs")
        auth = {'name': 'blah', 'username': '******', 'password': '******'}
        client = AuthConfigurationClient(auth=auth)

        mock_yaml_safe_dump = mocker.patch("f5cli.config.core.yaml.safe_dump")
        with mocker.patch('f5cli.config.core.open',
                          new_callable=mocker.mock_open()):
            client.store_auth('create')
        mock_yaml_safe_dump.assert_called_once()
        mock_make_dir.assert_called_once()
        assert mock_yaml_safe_dump.call_args_list[0][0][0][0] == auth
Esempio n. 4
0
    def test_create_pre_existing_account(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Attempt to perform crate auth account when an auth
            account of the same name has already been configured
            Given
            - Auth file containing multiple accounts

            When
            - store_auth('create') is invoked with auth details

            Then
            - store_auth raises an exception when trying to create a pre-existing account
        """
        new_account = {'name': 'cs1'}
        copy_typical_auth_contents = copy.deepcopy(TYPICAL_AUTH_CONTENTS)
        yaml_load_fixture_auth.return_value = copy_typical_auth_contents
        client = AuthConfigurationClient(auth=new_account)
        with pytest.raises(click.exceptions.ClickException) as error:
            with mocker.patch('f5cli.config.core.open',
                              new_callable=mocker.mock_open()):
                client.store_auth('create')
        assert error.value.args[0] == f"Create command failed. " \
                                      f"A account of cs1 name already exists."
Esempio n. 5
0
def auth_update(ctx,  # pylint: disable=too-many-arguments
                authentication_provider,
                host,
                port,
                name,
                set_default,
                api_endpoint,
                user,
                password):
    """ command """

    auth_info = {
        'name': name,
        'authentication-type': authentication_provider,
        'default': set_default,
        'host': host,
        'port': port,
        'api-endpoint': api_endpoint
    }

    if user:
        if password is None:
            password = click.prompt("Password", type=str, hide_input=True)
        auth_info.update({
            'user': user,
            'password': password})
    auth_client = AuthConfigurationClient(auth=auth_info)
    auth_client.store_auth('update')

    ctx.log('Authentication updated successfully')
Esempio n. 6
0
    def test_read_exist_auth(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Read an existing Auth file
        Given
        - Auth file exists

        When
        - read_auth() is invoked

        Then
        - The appropriate credentials are returned
        """
        client = AuthConfigurationClient()
        yaml_load_fixture_auth.return_value = [{
            'username': '******',
            'authentication-type': 'cs',
            'password': '******',
            'default': True
        }]

        with mocker.patch('f5cli.config.auth.open',
                          new_callable=mocker.mock_open()):
            result = client.read_auth('cs')
        assert result == yaml_load_fixture_auth.return_value[0]
        yaml_load_fixture_auth.assert_called_once()
Esempio n. 7
0
    def test_read_auth_without_key(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Attempt to read an Auth file that exists, but does not contain the required key
        Given
        - Auth file does exist
        - 'Group' key does not exist

        When
        - read_auth() is invoked

        Then
        - Exception is thrown
        """
        client = AuthConfigurationClient()

        group_name = 'CS'
        yaml_load_fixture_auth.return_value = [{
            'name': 'temp',
            'username': '******',
            'type': 'BIGIP',
            'password': '******'
        }]

        with pytest.raises(click.exceptions.ClickException) as error:
            with mocker.patch('f5cli.config.auth.open',
                              new_callable=mocker.mock_open()):
                client.read_auth(group_name)
        assert error.value.args[0] == f"Command failed. You must configure a default " \
                                      f"authentication for {group_name}!"
Esempio n. 8
0
def auth_delete(ctx, name):
    """ command """

    auth_client = AuthConfigurationClient()
    auth_client.delete_auth(name)

    ctx.log(f"Successfully deleted auth: {name} contents")
Esempio n. 9
0
def auth_create(ctx,  # pylint: disable=too-many-arguments
                authentication_provider,
                host,
                port,
                name,
                set_default,
                api_endpoint,
                user,
                password):
    """ command """
    auth_info = {
        'name': name,
        'authentication-type': authentication_provider,
        'default': set_default
    }
    if user:
        if password is None:
            password = click.prompt("Password", type=str, hide_input=True)
        auth_info.update({
            'user': user,
            'password': password})

    if authentication_provider == \
            constants.AUTHENTICATION_PROVIDERS.get(constants.CLOUD_SERVICES_GROUP_NAME):
        if api_endpoint is not None:
            auth_info['api_endpoint'] = api_endpoint
    else:
        if host is not None:
            auth_info['host'] = host
        auth_info['port'] = port

    auth_client = AuthConfigurationClient(auth=auth_info)
    auth_client.store_auth('create')

    ctx.log('Authentication configured successfully')
Esempio n. 10
0
    def test_deleting_non_exist_account(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Delete a account that is hasn't been configured
            Given
            - Auth file contains multiple accounts
            - The account name to be deleted that does not exist in the auth file

            When
            - delete_auth(account_name) is called

            Then
            - an exception should be thrown
        """

        copy_typical_auth_contents = copy.deepcopy(TYPICAL_AUTH_CONTENTS)
        yaml_load_fixture_auth.return_value = copy_typical_auth_contents
        client = AuthConfigurationClient()
        with pytest.raises(click.exceptions.ClickException) as error:
            with mocker.patch('f5cli.config.auth.open',
                              new_callable=mocker.mock_open()):
                client.delete_auth('blah')
            assert error.value.args[
                0] == f"Delete command failed. No account named blah found"
Esempio n. 11
0
    def test_deleting_default_account(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Delete a account that is configiured as a default account
            Given
            - Auth file contains multiple accounts
            - The account name to be deleted exists in the auth file and is a default account

            When
            - delete_auth(account_name) is called

            Then
            - The next available account of the same authentication provider
              is updated to be the new default account and the specified account is removed
        """

        mock_yaml_safe_dump = mocker.patch("f5cli.config.core.yaml.safe_dump")
        copy_typical_auth_contents = copy.deepcopy(TYPICAL_AUTH_CONTENTS)
        yaml_load_fixture_auth.return_value = copy_typical_auth_contents
        client = AuthConfigurationClient()
        with mocker.patch('f5cli.config.core.open',
                          new_callable=mocker.mock_open()):
            client.delete_auth('bigip2')
        mock_yaml_safe_dump.assert_called_once()
        mock_yaml_dump_wrote = mock_yaml_safe_dump.call_args_list[0][0][0]
        assert mock_yaml_dump_wrote[1].get('default')
        assert mock_yaml_dump_wrote[3].get('name') == 'bigip3'
Esempio n. 12
0
def auth_delete(ctx, name, auto_approve):
    """ command """
    approval_confirmation_map = {
        'delete': 'Auth contents named %s will be deleted.' % name
    }
    verify_approval('delete', approval_confirmation_map, auto_approve)
    auth_client = AuthConfigurationClient()
    auth_client.delete_auth(name)
    ctx.log(f"Successfully deleted auth: {name} contents")
Esempio n. 13
0
def get_mgmt_client():
    """ Get Management Client """

    auth_client = AuthConfigurationClient()
    auth = auth_client.read_auth(constants.AUTHENTICATION_PROVIDERS['BIGIP'])

    management_kwargs = dict(port=auth['port'],
                             user=auth['user'],
                             password=auth['password'])
    return ManagementClient(auth['host'], **management_kwargs)
Esempio n. 14
0
def get_mgmt_client():
    """ Get Management Client """

    auth_client = AuthConfigurationClient()
    auth = auth_client.read_auth(constants.AUTHENTICATION_PROVIDERS['CS'])

    management_kwargs = dict(user=auth['user'],
                             password=auth['password'],
                             api_endpoint=auth.pop('api_endpoint', None))
    return ManagementClient(**management_kwargs)
Esempio n. 15
0
    def test_write_to_existing_auth_file(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Write credentials to an existing Auth file
        Given
        - Config directory exists
        - Auth file exists with contents
        - Create action is invoked

        When
        - store_auth('create') is invoked

        Then
        - The existing Auth file is read
        - The Auth file is overwritten, containing merged credentials
        """
        bigip_auth = {
            'name': 'bigip_auth',
            'username': '******',
            'password': '******',
            'host': '1.2.3.4',
            'type': 'BIGIP',
            'default': 'true'
        }
        client = AuthConfigurationClient(auth=bigip_auth)
        cs_auth = {
            'name': 'cs_auth',
            'username': '******',
            'password': '******',
            'type': 'CS',
            'default': 'true'
        }
        yaml_load_fixture_auth.return_value = [cs_auth]

        mock_yaml_safe_dump = mocker.patch("f5cli.config.core.yaml.safe_dump")
        with mocker.patch('f5cli.config.core.open',
                          new_callable=mocker.mock_open()):
            client.store_auth('create')
        mock_yaml_safe_dump.assert_called_once()
        mock_yaml_dump_wrote = mock_yaml_safe_dump.call_args_list[0][0][0]
        assert mock_yaml_dump_wrote[0] == cs_auth
        assert mock_yaml_dump_wrote[1] == bigip_auth
Esempio n. 16
0
def subscription(ctx, action, subscription_id, declaration):
    """ Performs actions against a F5 Cloud Services subscription

    Parameters
    ----------
    action : str
        which action to perform
    subscription_id : str
        which subscription to perform the requested action on
    declaration : str
        file name or path to file of declaration to send to F5 Cloud Services

    Returns
    -------
    str
        the response for the requested action against the F5 Cloud Services subscription
    """
    # Additional option validation
    if action == 'update' and declaration is None:
        raise click.ClickException(
            'The --declaration option is required when updating a Cloud Services subscription'
        )

    auth = AuthConfigurationClient().read_auth(
        constants.AUTHENTICATION_PROVIDERS[
            constants.CLOUD_SERVICES_GROUP_NAME])
    mgmt_client = ManagementClient(user=auth['user'],
                                   password=auth['password'],
                                   api_endpoint=auth.pop('api_endpoint', None))

    subscription_client = SubscriptionClient(mgmt_client)
    if action == 'show':
        ctx.log(subscription_client.show(name=subscription_id))
    elif action == 'update':
        ctx.log(
            subscription_client.update(
                name=subscription_id,
                config_file=utils_core.convert_to_absolute(declaration)))
    else:
        raise click.ClickException(
            f"Action {action} not implemented for 'subscription' command")
Esempio n. 17
0
    def test_read_nonexist_auth(
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Attempt to read an Auth file that does not exist
        Given
        - Auth file does not exist

        When
        - read_auth() is invoked

        Then
        - Exception is thrown
        """
        client = AuthConfigurationClient()
        mock_path_is_file = os_path_isfile_fixture
        mock_path_is_file.return_value = False

        with pytest.raises(click.exceptions.ClickException) as error:
            client.read_auth('temp')
        assert error.value.args[0] == "Command failed. " \
                                      "You must configure a default authentication for temp!"
Esempio n. 18
0
def cli(ctx, authentication_provider, host, port, api_endpoint, user,
        password):
    """ command """

    if authentication_provider == \
            constants.AUTHENTICATION_PROVIDERS.get(constants.BIGIP_GROUP_NAME):
        if host is None:
            host = click.prompt("Host", type=str)
        auth_info = {
            'name': BIGIP_AUTH_ACCOUNT_NAME,
            'authentication-type': authentication_provider,
            'default': True,
            'host': host,
            'port': port
        }
    else:
        auth_info = {
            'name': CS_AUTH_ACCOUNT_NAME,
            'authentication-type': authentication_provider,
            'default': True
        }
        if api_endpoint is not None:
            auth_info['api_endpoint'] = api_endpoint

    if user is None:
        user = click.prompt("User", type=str)
    auth_info['user'] = user
    if password is None:
        password = click.prompt("Password", type=str, hide_input=True)
    auth_info['password'] = password

    # Validate credentials
    if authentication_provider == \
            constants.AUTHENTICATION_PROVIDERS.get(constants.BIGIP_GROUP_NAME):
        try:
            management_kwargs = dict(port=auth_info['port'],
                                     user=auth_info['user'],
                                     password=auth_info['password'])
            BigipManagementClient(auth_info['host'], **management_kwargs)
        except (DeviceReadyError, HTTPError) as error:
            raise click.ClickException(f"Failed to login to BIG-IP: {error}")
    else:
        try:
            CSManagementClient(user=auth_info['user'],
                               password=auth_info['password'],
                               api_endpoint=auth_info.pop(
                                   'api_endpoint', None))
        except HTTPError as error:
            raise click.ClickException(
                f"Failed to login to Cloud Services: {error}")

    # Store credentials in auth file
    auth_client = AuthConfigurationClient(auth=auth_info)
    try:
        auth_client.store_auth('create')
    except click.ClickException:
        auth_client.store_auth('update')

    ctx.log('Logged in successfully')
Esempio n. 19
0
    def test_update_existing_account(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Update an existing account
            Given
            - Auth file contains multiple accounts
            - The account name to the updated exists in the auth file

            When
            - store_auth('update')

            Then
            - Auth file is updated with the new account and the default
              account for the specific authentication provider is updated
        """

        new_account = {'name': 'bigip3', 'host': 'host2', 'default': True}

        mock_yaml_safe_dump = mocker.patch("f5cli.config.core.yaml.safe_dump")
        copy_typical_auth_contents = copy.deepcopy(TYPICAL_AUTH_CONTENTS)
        yaml_load_fixture_auth.return_value = copy_typical_auth_contents
        client = AuthConfigurationClient(auth=new_account)
        with mocker.patch('f5cli.config.core.open',
                          new_callable=mocker.mock_open()):
            client.store_auth('update')
        mock_yaml_safe_dump.assert_called_once()
        mock_yaml_dump_wrote = mock_yaml_safe_dump.call_args_list[0][0][0]
        assert not mock_yaml_dump_wrote[3].get('default')
        returned_account = mock_yaml_dump_wrote[4]
        expected_result = TYPICAL_AUTH_CONTENTS[4]
        assert returned_account.get('host') == new_account.get('host')
        assert returned_account.get('default') == new_account.get('default')
        assert returned_account.get('user') == expected_result.get('user')
        assert returned_account.get('password') == expected_result.get(
            'password')
        assert returned_account.get('type') == expected_result.get('type')
Esempio n. 20
0
    def test_write_exist_config_directory(
            mocker,
            os_path_exists_fixture,  # pylint: disable=unused-argument
            os_path_isfile_fixture):
        """ Write credentials to Auth file in an existing directory
        Given
        - Config directory exist
        - Auth file does not exist

        When
        - store_auth() is invoked

        Then
        - The credentials are written to the Auth file
        """
        client = AuthConfigurationClient(auth={'name': 'blah'})
        mock_path_isfile = os_path_isfile_fixture
        mock_path_isfile.return_value = False
        mock_yaml_safe_dump = mocker.patch("f5cli.config.core.yaml.safe_dump")
        with mocker.patch('f5cli.config.core.open',
                          new_callable=mocker.mock_open()):
            client.store_auth('create')
        mock_yaml_safe_dump.assert_called_once()
Esempio n. 21
0
    def test_update_no_auth_file(
        mocker,
        yaml_load_fixture_auth,
        os_path_exists_fixture,  # pylint: disable=unused-argument
        os_path_isfile_fixture):  # pylint: disable=unused-argument
        """ Attempt to perform update auth account when no auth accounts have been configured yet
            Given
            - No Auth file

            When
            - store_auth('update') is invoked with auth details

            Then
            - store_auth raises an exception
        """
        new_account = {'name': 'bigip4'}
        yaml_load_fixture_auth.return_value = None
        client = AuthConfigurationClient(auth=new_account)
        with pytest.raises(click.exceptions.ClickException) as error:
            with mocker.patch('f5cli.config.auth.open',
                              new_callable=mocker.mock_open()):
                client.store_auth('update')
            assert error.value.args[0] == f"Update command failed. " \
                                          f"No accounts have been configured yet"
Esempio n. 22
0
def service(ctx, action, component, version, declaration, install_component):
    """ command """
    auth = AuthConfigurationClient().read_auth(constants.AUTHENTICATION_PROVIDERS['BIGIP'])
    management_kwargs = dict(port=auth['port'], user=auth['user'], password=auth['password'])
    client = ManagementClient(auth['host'], **management_kwargs)
    kwargs = {}
    if version:
        kwargs['version'] = version
    extension_client = ExtensionClient(client, component, **kwargs)

    # intent based - support install in 'service' sub-command
    # install extension component if requested (and not installed)
    if install_component and not extension_client.package.is_installed()['installed']:
        extension_client.package.install()
        extension_client.service.is_available()

    try:
        if action == 'show':
            ctx.log(extension_client.service.show())
        elif action == 'create':
            ctx.log(_process_create(component, extension_client, declaration))
        elif action == 'delete':
            ctx.log(extension_client.service.delete())
        elif action == 'show-info':
            ctx.log(extension_client.service.show_info())
        elif action == 'show-failover':
            ctx.log(extension_client.service.show_trigger())
        elif action == 'trigger-failover':
            ctx.log(extension_client.service.trigger(
                config_file=utils_core.convert_to_absolute(declaration)))
        elif action == 'show-inspect':
            ctx.log(extension_client.service.show_inspect())
        elif action == 'reset':
            ctx.log(extension_client.service.reset(
                config_file=utils_core.convert_to_absolute(declaration)))
        else:
            raise click.ClickException('Action not implemented')
    except Exception as error:
        raise click.ClickException(error)
Esempio n. 23
0
def package(ctx, action, component, version, use_latest_metadata):
    """ command """
    auth = AuthConfigurationClient().read_auth(constants.AUTHENTICATION_PROVIDERS['BIGIP'])
    management_kwargs = dict(port=auth['port'], user=auth['user'], password=auth['password'])
    client = ManagementClient(auth['host'], **management_kwargs)

    kwargs = {}
    if version:
        kwargs['version'] = version
    if use_latest_metadata:
        kwargs['use_latest_metadata'] = use_latest_metadata

    if action == 'verify':
        ctx.log(extension_operations.verify_package(client, component, **kwargs))
    elif action == 'install':
        ctx.log(extension_operations.install_package(client, component, **kwargs))
    elif action == 'uninstall':
        ctx.log(extension_operations.uninstall_package(client, component, **kwargs))
    elif action == 'upgrade':
        ctx.log(extension_operations.upgrade_package(client, component, version))
    else:
        raise click.ClickException('Action {} not implemented'.format(action))
Esempio n. 24
0
def auth_list(ctx):
    """ command """

    ctx.log(AuthConfigurationClient().list_auth())