Merge "Revert "Add tags support in CLI""

This commit is contained in:
Jenkins 2016-11-09 13:45:07 +00:00 committed by Gerrit Code Review
commit 735ec78c4c
17 changed files with 42 additions and 810 deletions

View File

@ -78,7 +78,6 @@ def get_client(resource, version='v1', connection=None):
'sequence': v1.sequence,
'snapshot': v1.snapshot,
'task': v1.task,
'tag': v1.tag,
'vip': v1.vip
}
}

View File

@ -168,22 +168,16 @@ class BaseDownloadCommand(NodeMixIn, base.BaseCommand):
class NodeList(NodeMixIn, base.BaseListCommand):
"""Show list of all available nodes."""
_columns = (
'id',
'name',
'status',
'os_platform',
'ip',
'mac',
'cluster',
'platform_name',
'online')
@property
def columns(self):
if self.app.is_advanced_mode:
return self._columns + ('tags',)
return self._columns + ('pending_roles', 'roles')
columns = ('id',
'name',
'status',
'os_platform',
'roles',
'ip',
'mac',
'cluster',
'platform_name',
'online')
def get_parser(self, prog_name):
parser = super(NodeList, self).get_parser(prog_name)
@ -193,6 +187,7 @@ class NodeList(NodeMixIn, base.BaseListCommand):
'--env',
type=int,
help='Show only nodes that are in the specified environment')
parser.add_argument(
'-l',
'--labels',
@ -207,40 +202,35 @@ class NodeList(NodeMixIn, base.BaseListCommand):
environment_id=parsed_args.env, labels=parsed_args.labels)
data = data_utils.get_display_data_multi(self.columns, data)
return self.columns, data
return (self.columns, data)
class NodeShow(NodeMixIn, base.BaseShowCommand):
"""Show info about node with given id."""
_columns = (
'id',
'name',
'status',
'os_platform',
'kernel_params',
'ip',
'mac',
'error_type',
'pending_addition',
'hostname',
'fqdn',
'platform_name',
'cluster',
'online',
'progress',
'pending_deletion',
'group_id',
# TODO(romcheg): network_data mostly never fits the screen
# 'network_data',
'manufacturer')
_columns += NodeMixIn.numa_fields
@property
def columns(self):
if self.app.is_advanced_mode:
return self._columns + ('tags',)
return self._columns + ('pending_roles', 'roles')
columns = ('id',
'name',
'status',
'os_platform',
'roles',
'kernel_params',
'pending_roles',
'ip',
'mac',
'error_type',
'pending_addition',
'hostname',
'fqdn',
'platform_name',
'cluster',
'online',
'progress',
'pending_deletion',
'group_id',
# TODO(romcheg): network_data mostly never fits the screen
# 'network_data',
'manufacturer')
columns += NodeMixIn.numa_fields
def take_action(self, parsed_args):
data = self.client.get_by_id(parsed_args.id)
@ -250,8 +240,9 @@ class NodeShow(NodeMixIn, base.BaseShowCommand):
return self.columns, data
class NodeUpdate(NodeShow):
class NodeUpdate(NodeMixIn, base.BaseShowCommand):
"""Change given attributes for a node."""
columns = NodeShow.columns
def get_parser(self, prog_name):

View File

@ -1,296 +0,0 @@
# -*- coding: utf-8 -*-
#
# 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 abc
import argparse
from cliff import show
import os
from oslo_utils import fileutils
import six
from fuelclient.cli import error
from fuelclient.commands import base
from fuelclient.common import data_utils
from fuelclient import utils
class TagMixIn(object):
entity_name = 'tag'
supported_file_formats = ('json', 'yaml')
fields_mapper = (
('env', 'clusters'),
('release', 'releases'),
('plugin', 'plugins'),
)
def parse_model(self, args):
for param, tag_class in self.fields_mapper:
model_id = getattr(args, param)
if model_id:
return tag_class, model_id
@staticmethod
def check_file_path(file_path):
if not utils.file_exists(file_path):
raise argparse.ArgumentTypeError(
'File "{0}" does not exist.'.format(file_path))
return file_path
@staticmethod
def get_file_path(directory, tag_id, file_format):
return os.path.join(os.path.abspath(directory),
'tag_{}.{}'.format(tag_id, file_format))
@staticmethod
def read_tag_data(file_format, file_path):
try:
with open(file_path, 'r') as stream:
data = data_utils.safe_load(file_format, stream)
except (OSError, IOError):
msg = "Could not read tag's description at {}.".format(file_path)
raise error.InvalidFileException(msg)
return data
class TagShow(TagMixIn, base.BaseShowCommand):
"""Show single tag by id."""
columns = ("id", "tag", "has_primary")
class TagList(TagMixIn, base.BaseListCommand):
"""Show list of available tags for release, cluster or plugin."""
columns = TagShow.columns
def get_parser(self, prog_name):
parser = super(TagList, self).get_parser(prog_name)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
'-r',
'--release',
type=int,
help='release id')
group.add_argument(
'-e',
'--env',
type=int,
help='environment id')
group.add_argument(
'-p',
'--plugin',
type=int,
help='plugin id')
return parser
def take_action(self, parsed_args):
model, model_id = self.parse_model(parsed_args)
data = self.client.get_all(model, model_id)
display_data = data_utils.get_display_data_multi(self.columns, data)
return self.columns, display_data
class TagDownload(TagMixIn, base.BaseCommand):
"""Download full tag description to file."""
def get_parser(self, prog_name):
parser = super(TagDownload, self).get_parser(prog_name)
parser.add_argument('-t',
'--tag_id',
type=int,
required=True,
help='Id of the tag.')
parser.add_argument('-f',
'--format',
required=True,
choices=self.supported_file_formats,
help='Format of serialized tag description.')
parser.add_argument('-d',
'--directory',
required=False,
default=os.path.curdir,
help='Destination. Defaults to '
'the current directory.')
return parser
def take_action(self, parsed_args):
file_path = self.get_file_path(parsed_args.directory,
parsed_args.tag_id,
parsed_args.format)
data = self.client.get_by_id(parsed_args.tag_id)
try:
fileutils.ensure_tree(os.path.dirname(file_path))
fileutils.delete_if_exists(file_path)
with open(file_path, 'w') as stream:
data_utils.safe_dump(parsed_args.format, stream, data)
except (OSError, IOError):
msg = ("Could not store description data "
"for tag {} at {}".format(parsed_args.tag_id, file_path))
raise error.InvalidFileException(msg)
msg = ("Description data of tag with id '{}'"
" was stored in {}\n".format(parsed_args.tag_id,
file_path))
self.app.stdout.write(msg)
@six.add_metaclass(abc.ABCMeta)
class BaseTagUploader(TagMixIn, base.BaseShowCommand):
"""Upload a tag data from file."""
columns = TagShow.columns
@abc.abstractmethod
def upload(self, parsed_args, data):
"""String with the name of the action."""
pass
def get_parser(self, prog_name):
parser = show.ShowOne.get_parser(self, prog_name)
parser.add_argument(
'--file_path',
required=True,
type=self.check_file_path,
help="Full path to the file in {} format that contains tag's "
"data.".format("/".join(self.supported_file_formats)))
return parser
def take_action(self, parsed_args):
file_path = parsed_args.file_path
file_format = os.path.splitext(file_path)[1].lstrip('.')
data = self.read_tag_data(file_format, file_path)
display_data = data_utils.get_display_data_single(
self.columns,
self.upload(parsed_args, data))
return self.columns, display_data
class TagUpdate(BaseTagUploader):
"""Update a tag from file."""
def upload(self, parsed_args, data):
return self.client.update(parsed_args.tag_id, data)
def get_parser(self, prog_name):
parser = super(TagUpdate, self).get_parser(prog_name)
parser.add_argument(
'-t',
'--tag_id',
type=int,
required=True,
help='Id of the tag.')
return parser
class TagCreate(BaseTagUploader):
"""Create a tag from file."""
def upload(self, parsed_args, data):
model, model_id = self.parse_model(parsed_args)
return self.client.create(model, model_id, data)
def get_parser(self, prog_name):
parser = super(TagCreate, self).get_parser(prog_name)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
'-r',
'--release',
type=int,
help='release id')
group.add_argument(
'-e',
'--env',
type=int,
help='environment id')
group.add_argument(
'-p',
'--plugin',
type=int,
help='plugin id')
return parser
class TagDelete(base.BaseDeleteCommand):
"""Delete a tag by id."""
entity_name = 'tag'
@six.add_metaclass(abc.ABCMeta)
class BaseTagAssignee(TagMixIn, base.BaseCommand):
"""Base class for tags assignment."""
@abc.abstractproperty
def action(self):
"""String with the name of the action."""
pass
@abc.abstractproperty
def assignment_method(self):
"""Assignment method."""
pass
def get_parser(self, prog_name):
parser = super(BaseTagAssignee, self).get_parser(prog_name)
parser.add_argument('-t',
'--tags',
type=str,
nargs='+',
required=True,
help='List of tags to be {} '
'node.'.format(self.action))
parser.add_argument('-n',
'--node',
type=int,
required=True,
help='Id of the node.')
return parser
def take_action(self, parsed_args):
self.assignment_method(node=parsed_args.node,
tag_ids=parsed_args.tags)
self.app.stdout.write('Tags {t} were {a} the node {n}.'
'\n'.format(t=parsed_args.tags,
a=self.action,
n=parsed_args.node))
class TagAssign(BaseTagAssignee):
"""Assign tags to the node."""
action = 'assigned to'
@property
def assignment_method(self):
return self.client.assign
class TagUnassign(BaseTagAssignee):
"""Unassign tags from the node."""
action = 'unassigned from'
@property
def assignment_method(self):
return self.client.unassign

View File

@ -32,8 +32,3 @@ TASK_STATUSES = Enum(
'ready',
'running'
)
CLIENT_MODES = Enum(
'advanced',
'simple'
)

View File

@ -9,9 +9,6 @@ OS_PASSWORD:
OS_TENANT_NAME: "admin"
HTTP_PROXY: null
HTTP_TIMEOUT: 10
# application mode
# possible options: 'advanced', 'simple'
MODE: 'simple'
# Performance tests settings
PERFORMANCE_PROFILING_TESTS: 0

View File

@ -18,8 +18,6 @@ import sys
from cliff import app
from cliff.commandmanager import CommandManager
from fuelclient.cli import error
from fuelclient import consts
from fuelclient import fuelclient_settings
from fuelclient import utils
@ -34,19 +32,6 @@ class FuelClient(app.App):
configuration of basic engines.
"""
_is_advanced_mode = None
@property
def is_advanced_mode(self):
if self._is_advanced_mode is None:
self._is_advanced_mode = False
settings = fuelclient_settings.get_settings()
try:
if settings.MODE == consts.CLIENT_MODES.advanced:
self._is_advanced_mode = True
except error.SettingsException:
pass
return self._is_advanced_mode
def build_option_parser(self, description, version, argparse_kwargs=None):
"""Overrides default options for backwards compatibility."""

View File

@ -28,7 +28,6 @@ from fuelclient.objects.role import Role
from fuelclient.objects.task import DeployTask
from fuelclient.objects.task import SnapshotTask
from fuelclient.objects.task import Task
from fuelclient.objects.tag import Tag
from fuelclient.objects.fuelversion import FuelVersion
from fuelclient.objects.network_group import NetworkGroup
from fuelclient.objects.plugins import Plugins

View File

@ -1,59 +0,0 @@
# Copyright 2015 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.
from fuelclient.objects.base import BaseObject
class Tag(BaseObject):
class_api_path = "{}/{}/tags/"
instance_api_path = "tags/{}/"
assign_api_path = "nodes/{}/tags/"
def get_tag(self):
return self.connection.get_request(
self.instance_api_path.format(self.id))
def update_tag(self, data):
return self.connection.put_request(
self.instance_api_path.format(self.id), data)
def delete_tag(self):
return self.connection.delete_request(
self.instance_api_path.format(self.id))
@classmethod
def get_all(cls, owner_type, owner_id):
return cls.connection.get_request(
cls.class_api_path.format(owner_type, owner_id))
@classmethod
def create_tag(cls, owner_type, owner_id, data):
return cls.connection.post_request(
cls.class_api_path.format(owner_type, owner_id),
data)
@classmethod
def assign_tags(cls, tag_ids, node_id):
return cls.connection.post_request(
cls.assign_api_path.format(node_id), tag_ids)
@classmethod
def unassign_tags(cls, tag_ids, node_id):
url = '{0}?tags={1}'.format(
cls.assign_api_path.format(node_id),
','.join(map(str, tag_ids))
)
return cls.connection.delete_request(url)

View File

@ -194,9 +194,7 @@ node-4 ansible_host=10.20.0.5
node.NodeClient._updatable_attributes
node_id = 42
hostname = 'test-name'
expected_field_data = cmd_node.NodeShow(
mock.Mock(is_advanced_mode=False), []).columns
expected_field_data = cmd_node.NodeShow.columns
self.m_client.update.return_value = \
fake_node.get_fake_node(node_id=node_id,
@ -211,7 +209,7 @@ node-4 ansible_host=10.20.0.5
mock.ANY,
mock.ANY)
self.m_get_client.assert_called_with('node', mock.ANY)
self.m_get_client.assert_called_once_with('node', mock.ANY)
self.m_client.update.assert_called_once_with(
node_id, hostname=hostname)
@ -220,9 +218,7 @@ node-4 ansible_host=10.20.0.5
self.m_client._updatable_attributes = \
node.NodeClient._updatable_attributes
node_id = 37
expected_field_data = cmd_node.NodeShow(
mock.Mock(is_advanced_mode=False), []).columns
expected_field_data = cmd_node.NodeShow.columns
test_cases = ('new-name', 'New Name', 'śćż∑ Pó', '你一定是无聊')
for name in test_cases:
@ -242,7 +238,7 @@ node-4 ansible_host=10.20.0.5
mock.ANY,
mock.ANY,
mock.ANY)
self.m_get_client.assert_called_with('node', mock.ANY)
self.m_get_client.assert_called_once_with('node', mock.ANY)
self.m_client.update.assert_called_once_with(
node_id, name=name)
self.m_get_client.reset_mock()

View File

@ -1,160 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright 2016 Vitalii Kulanov
#
# 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 json
import mock
import yaml
from fuelclient.tests.unit.v2.cli import test_engine
from fuelclient.tests.utils import fake_tag
class TestTagCommand(test_engine.BaseCLITest):
"""Tests for fuel2 tag * commands."""
def test_tag_list(self):
self.m_client.get_all.return_value = fake_tag.get_fake_tags(10)
args = 'tag list -r 2'
self.exec_command(args)
self.m_client.get_all.assert_called_once_with('releases', 2)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
@mock.patch('json.dump')
def test_tag_download_json(self, m_dump):
tag_data = fake_tag.get_fake_tag()
tag_id = tag_data['id']
args = 'tag download -t {} -f json -d /tmp'.format(tag_id)
expected_path = '/tmp/tag_{}.json'.format(tag_id)
self.m_client.get_by_id.return_value = tag_data
m_open = mock.mock_open()
with mock.patch('fuelclient.commands.tag.open', m_open, create=True):
self.exec_command(args)
m_open.assert_called_once_with(expected_path, 'w')
m_dump.assert_called_once_with(tag_data, mock.ANY, indent=4)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
self.m_client.get_by_id.assert_called_once_with(tag_id)
@mock.patch('yaml.safe_dump')
def test_tag_download_yaml(self, m_safe_dump):
tag_data = fake_tag.get_fake_tag()
tag_id = tag_data['id']
args = 'tag download -t {} -f yaml -d /tmp'.format(tag_id)
expected_path = '/tmp/tag_{}.yaml'.format(tag_id)
self.m_client.get_by_id.return_value = tag_data
m_open = mock.mock_open()
with mock.patch('fuelclient.commands.tag.open', m_open, create=True):
self.exec_command(args)
m_open.assert_called_once_with(expected_path, 'w')
m_safe_dump.assert_called_once_with(tag_data, mock.ANY,
default_flow_style=False)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
self.m_client.get_by_id.assert_called_once_with(tag_id)
@mock.patch('fuelclient.utils.file_exists', return_value=True)
def test_tag_update_json(self, m_file_exists):
tag_data = fake_tag.get_fake_tag()
tag_id = tag_data['id']
file_path = '/tmp/tag_{}.yaml'.format(tag_id)
args = 'tag update -t {} --file_path {}'.format(tag_id, file_path)
m_open = mock.mock_open(read_data=json.dumps(tag_data))
with mock.patch('fuelclient.commands.tag.open', m_open, create=True):
self.exec_command(args)
m_open.assert_called_once_with(file_path, 'r')
m_file_exists.assert_called_once_with(file_path)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
self.m_client.update.assert_called_once_with(tag_id, tag_data)
@mock.patch('fuelclient.utils.file_exists', return_value=True)
def test_tag_update_yaml(self, m_file_exists):
tag_data = fake_tag.get_fake_tag()
tag_id = tag_data['id']
file_path = '/tmp/tag_{}.yaml'.format(tag_id)
args = 'tag update -t {} --file_path {}'.format(tag_id, file_path)
m_open = mock.mock_open(read_data=yaml.safe_dump(tag_data))
with mock.patch('fuelclient.commands.tag.open', m_open, create=True):
self.exec_command(args)
m_open.assert_called_once_with(file_path, 'r')
m_file_exists.assert_called_once_with(file_path)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
self.m_client.update.assert_called_once_with(tag_id, tag_data)
@mock.patch('fuelclient.utils.file_exists', return_value=True)
def test_tag_create_json(self, m_file_exists):
tag_data = fake_tag.get_fake_tag()
tag_path = "/tmp/tag22.json"
args = 'tag create -r 2 --file_path {}'.format(tag_path)
m_open = mock.mock_open(read_data=json.dumps(tag_data))
with mock.patch('fuelclient.commands.tag.open', m_open, create=True):
self.exec_command(args)
m_open.assert_called_once_with(tag_path, 'r')
m_file_exists.assert_called_once_with(tag_path)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
self.m_client.create.assert_called_once_with('releases', 2, tag_data)
@mock.patch('fuelclient.utils.file_exists', return_value=True)
def test_tag_create_yaml(self, m_file_exists):
tag_data = fake_tag.get_fake_tag()
tag_path = "/tmp/tag22.yaml"
args = 'tag create -r 2 --file_path {}'.format(tag_path)
m_open = mock.mock_open(read_data=yaml.safe_dump(tag_data))
with mock.patch('fuelclient.commands.tag.open', m_open, create=True):
self.exec_command(args)
m_open.assert_called_once_with(tag_path, 'r')
m_file_exists.assert_called_once_with(tag_path)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
self.m_client.create.assert_called_once_with('releases', 2, tag_data)
def test_tag_delete(self):
tag_id = 1
args = 'tag delete {}'.format(tag_id)
self.exec_command(args)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
self.m_client.delete_by_id.assert_called_once_with(tag_id)
def test_tag_assign(self):
node_id = 1
tag_ids = ['4', '5', '6']
args = 'tag assign -n {} -t {}'.format(node_id, " ".join(tag_ids))
self.exec_command(args)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
self.m_client.assign.assert_called_once_with(node=node_id,
tag_ids=tag_ids)
def test_tag_unassign(self):
node_id = 1
tag_ids = ['4', '5', '6']
args = 'tag unassign -n {} -t {}'.format(node_id, " ".join(tag_ids))
self.exec_command(args)
self.m_get_client.assert_called_once_with('tag', mock.ANY)
self.m_client.unassign.assert_called_once_with(node=node_id,
tag_ids=tag_ids)

View File

@ -1,111 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright 2016 Vitalii Kulanov
#
# 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 fuelclient
from fuelclient.tests.unit.v2.lib import test_api
from fuelclient.tests import utils
class TestTagFacade(test_api.BaseLibTest):
def setUp(self):
super(TestTagFacade, self).setUp()
self.owner_map = {
'release': 'releases',
'cluster': 'clusters',
'plugin': 'plugins'
}
self.version = 'v1'
self.res_uri = '/api/{version}/'.format(
version=self.version)
self.fake_tag = utils.get_fake_tag('fake_tag')
self.fake_tags = utils.get_fake_tags(10)
self.instance_uri = (self.res_uri +
'tags/{}/'.format(self.fake_tag['id']))
self.client = fuelclient.get_client('tag', self.version)
def _get_class_uri_path(self, tag):
owner_type = self.owner_map[tag['owner_type']]
return self.res_uri + "{}/{}/tags/".format(owner_type,
tag['owner_id'])
def test_tag_list(self):
expected_uri = self._get_class_uri_path(self.fake_tag)
matcher = self.m_request.get(expected_uri, json=self.fake_tags)
self.client.get_all(self.owner_map[self.fake_tag['owner_type']],
self.fake_tag['owner_id'])
self.assertTrue(matcher.called)
def test_tag_download(self):
expected_uri = self.instance_uri
tag_matcher = self.m_request.get(expected_uri, json=self.fake_tag)
tag = self.client.get_by_id(self.fake_tag['id'])
self.assertTrue(expected_uri, tag_matcher.called)
self.assertEqual(tag, self.fake_tag)
def test_tag_upload(self):
expected_uri = self.instance_uri
upd_matcher = self.m_request.put(expected_uri, json=self.fake_tag)
self.client.update(self.fake_tag['id'], self.fake_tag)
self.assertTrue(upd_matcher.called)
self.assertEqual(self.fake_tag, upd_matcher.last_request.json())
def test_tag_create(self):
expected_uri = self._get_class_uri_path(self.fake_tag)
post_matcher = self.m_request.post(expected_uri, json=self.fake_tag)
self.client.create(self.owner_map[self.fake_tag['owner_type']],
self.fake_tag['owner_id'],
self.fake_tag)
self.assertTrue(post_matcher.called)
self.assertEqual(self.fake_tag, post_matcher.last_request.json())
def test_tag_delete(self):
expected_uri = self.instance_uri
delete_matcher = self.m_request.delete(expected_uri, json={})
self.client.delete_by_id(self.fake_tag['id'])
self.assertTrue(delete_matcher.called)
def test_tag_assign(self):
node_id = 1
expected_uri = (self.res_uri +
'nodes/{}/tags/'.format(node_id))
tag_ids = [self.fake_tag['id']]
post_matcher = self.m_request.post(expected_uri, json=tag_ids)
self.client.assign(tag_ids, node_id)
self.assertTrue(post_matcher.called)
self.assertEqual(tag_ids, post_matcher.last_request.json())
def test_tag_unassign(self):
node_id = 1
tag_ids = [self.fake_tag['id']]
expected_uri = '{0}?tags={1}'.format(
self.res_uri + 'nodes/{}/tags/'.format(node_id),
','.join(map(str, tag_ids))
)
delete_matcher = self.m_request.delete(expected_uri, json={})
self.client.unassign(tag_ids, node_id)
self.assertTrue(delete_matcher.called)

View File

@ -54,8 +54,6 @@ from fuelclient.tests.utils.fake_release import get_fake_release_component
from fuelclient.tests.utils.fake_release import get_fake_release_components
from fuelclient.tests.utils.fake_role import get_fake_role
from fuelclient.tests.utils.fake_role import get_fake_roles
from fuelclient.tests.utils.fake_tag import get_fake_tag
from fuelclient.tests.utils.fake_tag import get_fake_tags
__all__ = (get_fake_deployment_history,
@ -87,6 +85,4 @@ __all__ = (get_fake_deployment_history,
get_fake_node_groups,
get_fake_openstack_config,
get_fake_plugin,
get_fake_plugins,
get_fake_tag,
get_fake_tags)
get_fake_plugins)

View File

@ -1,37 +0,0 @@
# -*- coding: utf-8 -*-
#
# 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.
def get_fake_tag(tag_name=None, has_primary=False, owner_id=None,
owner_type=None):
"""Create a random fake tag
Returns the serialized and parametrized representation of a dumped Fuel
tag. Represents the average amount of data.
"""
return {
"id": 1,
"tag": tag_name or "controller",
"has_primary": has_primary,
"owner_id": owner_id or 1,
"owner_type": owner_type or 'release'
}
def get_fake_tags(tag_count, **kwargs):
"""Create a random fake list of tags."""
return [get_fake_tag(**kwargs) for _ in range(tag_count)]

View File

@ -27,7 +27,6 @@ from distutils.version import StrictVersion
from fnmatch import fnmatch
from fuelclient.cli import error
from fuelclient import consts
def _wait_and_check_exit_code(cmd, child):
@ -213,8 +212,3 @@ def add_os_cli_parameters(parser):
parser.add_argument(
'--os-password', metavar='<auth-password>',
help='Authentication password, defaults to env[OS_PASSWORD].')
parser.add_argument(
'--mode',
choices=list(consts.CLIENT_MODES),
help="Application mode, defaults to 'simple'.")

View File

@ -30,7 +30,6 @@ from fuelclient.v1 import plugins
from fuelclient.v1 import sequence
from fuelclient.v1 import snapshot
from fuelclient.v1 import task
from fuelclient.v1 import tag
from fuelclient.v1 import vip
# Please keeps the list in alphabetical order
@ -52,5 +51,4 @@ __all__ = ('cluster_settings',
'sequence',
'snapshot',
'task',
'tag',
'vip')

View File

@ -1,47 +0,0 @@
# -*- coding: utf-8 -*-
#
# 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.
from fuelclient import objects
from fuelclient.v1 import base_v1
class TagClient(base_v1.BaseV1Client):
_entity_wrapper = objects.Tag
def get_all(self, tag_owner, owner_id):
return self._entity_wrapper.get_all(tag_owner, owner_id)
def update(self, tag_id, data):
tag = self._entity_wrapper(obj_id=tag_id)
return tag.update_tag(data)
def create(self, tag_owner, owner_id, data):
return self._entity_wrapper.create_tag(tag_owner, owner_id, data)
def delete_by_id(self, tag_id):
tag = self._entity_wrapper(obj_id=tag_id)
return tag.delete_tag()
def assign(self, tag_ids, node):
return self._entity_wrapper.assign_tags(tag_ids, node)
def unassign(self, tag_ids, node):
return self._entity_wrapper.unassign_tags(tag_ids, node)
def get_client(connection):
return TagClient(connection)

View File

@ -114,14 +114,6 @@ fuelclient =
role_download=fuelclient.commands.role:RoleDownload
role_list=fuelclient.commands.role:RoleList
role_update=fuelclient.commands.role:RoleUpdate
tag_assign=fuelclient.commands.tag:TagAssign
tag_create=fuelclient.commands.tag:TagCreate
tag_delete=fuelclient.commands.tag:TagDelete
tag_download=fuelclient.commands.tag:TagDownload
tag_list=fuelclient.commands.tag:TagList
tag_show=fuelclient.commands.tag:TagShow
tag_unassign=fuelclient.commands.tag:TagUnassign
tag_update=fuelclient.commands.tag:TagUpdate
task_delete=fuelclient.commands.task:TaskDelete
task_deployment-info_download=fuelclient.commands.task:TaskDeploymentInfoDownload
task_history_show=fuelclient.commands.task:TaskHistoryShow