Merge "Add actions to operate on role entity"
This commit is contained in:
@@ -14,9 +14,12 @@
|
||||
|
||||
|
||||
from fuelclient.cli.actions.base import Action
|
||||
from fuelclient.cli.actions.base import check_all
|
||||
import fuelclient.cli.arguments as Args
|
||||
from fuelclient.cli.arguments import group
|
||||
from fuelclient.cli.formatting import format_table
|
||||
from fuelclient.objects.release import Release
|
||||
from fuelclient.cli.serializers import FileFormatBasedSerializer
|
||||
from fuelclient.objects.role import Role
|
||||
|
||||
|
||||
class RoleAction(Action):
|
||||
@@ -25,30 +28,40 @@ class RoleAction(Action):
|
||||
action_name = "role"
|
||||
|
||||
def __init__(self):
|
||||
super(RoleAction, self).__init__()
|
||||
# NOTE(dshulyak) this serializers are really messed up
|
||||
# it gets overwritten in several places
|
||||
self.file_serializer = FileFormatBasedSerializer()
|
||||
self.args = [
|
||||
Args.get_list_arg("List all roles for specific release"),
|
||||
Args.get_release_arg("Release id", required=True)
|
||||
Args.get_list_arg("List all roles"),
|
||||
|
||||
Args.get_release_arg("Release id"),
|
||||
Args.get_str_arg("role", help="Name of the role"),
|
||||
Args.get_file_arg("File with role description"),
|
||||
|
||||
group(
|
||||
Args.get_create_arg("Create role from file"),
|
||||
Args.get_boolean_arg("update", help="Update role from file"),
|
||||
Args.get_delete_arg("Delete role from fuel")
|
||||
)
|
||||
]
|
||||
self.flag_func_map = (
|
||||
("delete", self.delete),
|
||||
("create", self.create),
|
||||
("update", self.update),
|
||||
("role", self.item),
|
||||
(None, self.list),
|
||||
)
|
||||
|
||||
@check_all('release')
|
||||
def list(self, params):
|
||||
"""Print all available roles and their
|
||||
conflicts for some release with id=1:
|
||||
"""Print all available roles
|
||||
|
||||
fuel role --rel 1
|
||||
"""
|
||||
release = Release(params.release, params=params)
|
||||
data = release.get_fresh_data()
|
||||
acceptable_keys = ("name", "conflicts")
|
||||
roles = [
|
||||
{
|
||||
"name": role_name,
|
||||
"conflicts": ", ".join(
|
||||
metadata.get("conflicts", ["-"])
|
||||
)
|
||||
} for role_name, metadata in data["roles_metadata"].iteritems()]
|
||||
roles = Role.get_all(params.release)
|
||||
|
||||
acceptable_keys = ("name", "id")
|
||||
|
||||
self.serializer.print_to_output(
|
||||
roles,
|
||||
format_table(
|
||||
@@ -56,3 +69,47 @@ class RoleAction(Action):
|
||||
acceptable_keys=acceptable_keys
|
||||
)
|
||||
)
|
||||
|
||||
@check_all('role', 'release', 'file')
|
||||
def item(self, params):
|
||||
"""Save full role description to file
|
||||
fuel role --rel 1 --role controller --file some.yaml
|
||||
"""
|
||||
role = Role.get_one(params.release, params.role)
|
||||
self.file_serializer.write_to_file(params.file, role)
|
||||
self.file_serializer.print_to_output(
|
||||
role,
|
||||
"Role successfully saved to {0}.".format(params.file))
|
||||
|
||||
@check_all('file', 'release')
|
||||
def create(self, params):
|
||||
"""Create a role from file description
|
||||
fuel role --rel 1 --create --file some.yaml
|
||||
"""
|
||||
role = self.file_serializer.read_from_file(params.file)
|
||||
role = Role.create(params.release, role)
|
||||
self.file_serializer.print_to_output(
|
||||
role,
|
||||
"Role {0} successfully created from {1}.".format(
|
||||
role['name'], params.file))
|
||||
|
||||
@check_all('file', 'release')
|
||||
def update(self, params):
|
||||
"""Update a role from file description
|
||||
fuel role --rel 1 --update --file some.yaml
|
||||
"""
|
||||
role = self.file_serializer.read_from_file(params.file)
|
||||
role = Role.update(params.release, role['name'], role)
|
||||
self.file_serializer.print_to_output(
|
||||
role,
|
||||
"Role successfully updated from {0}.".format(params.file))
|
||||
|
||||
@check_all('role', 'release')
|
||||
def delete(self, params):
|
||||
"""Delete role from fuel
|
||||
fuel role --delete --role controller --rel 1
|
||||
"""
|
||||
Role.delete(params.release, params.role)
|
||||
self.file_serializer.print_to_output(
|
||||
{},
|
||||
"Role with id {0} successfully deleted.".format(params.role))
|
||||
|
||||
@@ -372,6 +372,10 @@ def get_dir_arg(help_msg):
|
||||
return get_str_arg("dir", default=os.curdir, help=help_msg)
|
||||
|
||||
|
||||
def get_file_arg(help_msg):
|
||||
return get_str_arg("file", help=help_msg)
|
||||
|
||||
|
||||
def get_verify_arg(help_msg):
|
||||
return get_boolean_arg("verify", flags=("-v",), help=help_msg)
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ import os
|
||||
|
||||
import yaml
|
||||
|
||||
from fuelclient.cli import error
|
||||
|
||||
|
||||
class Serializer(object):
|
||||
"""Serializer class - contains all logic responsible for
|
||||
@@ -86,6 +88,27 @@ class Serializer(object):
|
||||
return self.serializer["r"](file_to_read.read())
|
||||
|
||||
|
||||
class FileFormatBasedSerializer(Serializer):
|
||||
|
||||
def get_serializer(self, path):
|
||||
extension = os.path.splitext(path)[1][1:]
|
||||
if extension not in self.serializers:
|
||||
raise error.BadDataException(
|
||||
'No serializer for provided file {0}'.format(path))
|
||||
return self.serializers[extension]
|
||||
|
||||
def write_to_file(self, full_path, data):
|
||||
serializer = self.get_serializer(full_path)
|
||||
with open(full_path, "w+") as f:
|
||||
f.write(serializer["w"](data))
|
||||
return full_path
|
||||
|
||||
def read_from_file(self, full_path):
|
||||
serializer = self.get_serializer(full_path)
|
||||
with open(full_path, "r") as f:
|
||||
return serializer["r"](f.read())
|
||||
|
||||
|
||||
def listdir_without_extensions(dir_path):
|
||||
return ifilter(
|
||||
lambda f: f != "",
|
||||
|
||||
@@ -145,6 +145,7 @@ class Client(object):
|
||||
|
||||
headers = {'x-auth-token': self.auth_token}
|
||||
params = params or {}
|
||||
|
||||
resp = requests.get(url, params=params, headers=headers)
|
||||
resp.raise_for_status()
|
||||
|
||||
|
||||
50
fuelclient/objects/role.py
Normal file
50
fuelclient/objects/role.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# 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 Role(BaseObject):
|
||||
|
||||
class_api_path = "releases/{release_id}/roles/"
|
||||
instance_api_path = "releases/{release_id}/roles/{role_name}/"
|
||||
|
||||
@classmethod
|
||||
def get_all(cls, release_id):
|
||||
return cls.connection.get_request(
|
||||
cls.class_api_path.format(release_id=release_id))
|
||||
|
||||
@classmethod
|
||||
def get_one(cls, release_id, role_name):
|
||||
return cls.connection.get_request(
|
||||
cls.instance_api_path.format(
|
||||
release_id=release_id, role_name=role_name))
|
||||
|
||||
@classmethod
|
||||
def update(cls, release_id, role_name, data):
|
||||
return cls.connection.put_request(
|
||||
cls.instance_api_path.format(
|
||||
release_id=release_id, role_name=role_name), data)
|
||||
|
||||
@classmethod
|
||||
def create(cls, release_id, data):
|
||||
return cls.connection.post_request(
|
||||
cls.class_api_path.format(release_id=release_id), data)
|
||||
|
||||
@classmethod
|
||||
def delete(cls, release_id, role_name):
|
||||
return cls.connection.delete_request(
|
||||
cls.instance_api_path.format(
|
||||
release_id=release_id, role_name=role_name))
|
||||
84
fuelclient/tests/test_roles.py
Normal file
84
fuelclient/tests/test_roles.py
Normal file
@@ -0,0 +1,84 @@
|
||||
# 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.
|
||||
|
||||
import json
|
||||
|
||||
from mock import patch
|
||||
import yaml
|
||||
|
||||
from fuelclient.tests import base
|
||||
|
||||
API_IN = """id: 2
|
||||
name: my_role
|
||||
"""
|
||||
|
||||
API_OUT = yaml.load(API_IN)
|
||||
|
||||
|
||||
@patch('fuelclient.client.requests')
|
||||
class TestRoleActions(base.UnitTestCase):
|
||||
|
||||
def test_list_roles(self, mreq):
|
||||
self.execute(['fuel', 'role', '--rel', '2'])
|
||||
role_call = mreq.get.call_args_list[-1]
|
||||
url = role_call[0][0]
|
||||
self.assertIn('/releases/2/roles/', url)
|
||||
|
||||
@patch('fuelclient.cli.serializers.open', create=True)
|
||||
def test_get_role(self, mopen, mreq):
|
||||
mreq.get().json.return_value = API_OUT
|
||||
self.execute(['fuel', 'role',
|
||||
'--role', 'my_role', '--file', 'myfile.yaml',
|
||||
'--rel', '2'])
|
||||
|
||||
mopen().__enter__().write.assert_called_once_with(API_IN)
|
||||
|
||||
call_args = mreq.get.call_args_list[1]
|
||||
url = call_args[0][0]
|
||||
self.assertIn('releases/2/roles/my_role', url)
|
||||
|
||||
@patch('fuelclient.cli.serializers.open', create=True)
|
||||
def test_create_role(self, mopen, mreq):
|
||||
mopen().__enter__().read.return_value = API_IN
|
||||
|
||||
self.execute(['fuel', 'role', '--create',
|
||||
'--file', 'myfile.yaml', '--rel', '2'])
|
||||
|
||||
call_args = mreq.post.call_args_list[0]
|
||||
url = call_args[0][0]
|
||||
kwargs = call_args[1]
|
||||
self.assertIn('releases/2/roles/', url)
|
||||
self.assertEqual(
|
||||
json.loads(kwargs['data']), API_OUT)
|
||||
|
||||
@patch('fuelclient.cli.serializers.open', create=True)
|
||||
def test_update_role(self, mopen, mreq):
|
||||
mopen().__enter__().read.return_value = API_IN
|
||||
|
||||
self.execute(['fuel', 'role', '--update',
|
||||
'--file', 'myfile.yaml', '--rel', '2'])
|
||||
|
||||
call_args = mreq.put.call_args_list[0]
|
||||
url = call_args[0][0]
|
||||
kwargs = call_args[1]
|
||||
self.assertIn('releases/2/roles/my_role', url)
|
||||
self.assertEqual(
|
||||
json.loads(kwargs['data']), API_OUT)
|
||||
|
||||
def test_delete_role(self, mreq):
|
||||
self.execute(['fuel', 'role',
|
||||
'--delete', '--role', '3', '--rel', '2'])
|
||||
role_call = mreq.delete.call_args_list[-1]
|
||||
url = role_call[0][0]
|
||||
self.assertIn('releases/2/roles/3', url)
|
||||
Reference in New Issue
Block a user