Merge "Add actions to operate on role entity"

This commit is contained in:
Jenkins
2015-03-10 11:42:06 +00:00
committed by Gerrit Code Review
6 changed files with 235 additions and 16 deletions

View File

@@ -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))

View File

@@ -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)

View File

@@ -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 != "",

View File

@@ -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()

View 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))

View 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)