Merge "Respect format when printing Fuel's VERSION"
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
|
||||
import argparse
|
||||
|
||||
from fuelclient.cli import serializers
|
||||
from fuelclient import client
|
||||
|
||||
|
||||
@@ -23,4 +24,6 @@ class FuelVersionAction(argparse._VersionAction):
|
||||
:returns: prints fuel server version
|
||||
"""
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
parser.exit(message=client.APIClient.get_fuel_version())
|
||||
serializer = serializers.Serializer.from_params(namespace)
|
||||
version = client.APIClient.get_fuel_version()
|
||||
parser.exit(message=serializer.serialize(version))
|
||||
|
||||
@@ -17,6 +17,7 @@ from itertools import chain
|
||||
import os
|
||||
|
||||
from fuelclient import __version__
|
||||
from fuelclient.actions import fuel_version
|
||||
from fuelclient.cli.error import ArgumentException
|
||||
from fuelclient.client import APIClient
|
||||
|
||||
@@ -92,15 +93,6 @@ class NodeAction(argparse.Action):
|
||||
setattr(namespace, self.dest, map(int, only_ids))
|
||||
|
||||
|
||||
class FuelVersionAction(argparse._VersionAction):
|
||||
"""Custom argparse._VersionAction subclass to compute fuel server version
|
||||
|
||||
:returns: prints fuel server version
|
||||
"""
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
parser.exit(message=APIClient.get_fuel_version())
|
||||
|
||||
|
||||
class SetAction(argparse.Action):
|
||||
"""Custom argparse.Action subclass to store distinct values
|
||||
|
||||
@@ -139,7 +131,7 @@ def get_fuel_version_arg():
|
||||
return {
|
||||
"args": ["--fuel-version"],
|
||||
"params": {
|
||||
"action": FuelVersionAction,
|
||||
"action": fuel_version.FuelVersionAction,
|
||||
"help": "show Fuel server's version number and exit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ from fuelclient.cli.arguments import substitutions
|
||||
from fuelclient.cli.error import exceptions_decorator
|
||||
from fuelclient.cli.error import ParserException
|
||||
from fuelclient.cli.serializers import Serializer
|
||||
from fuelclient import consts
|
||||
from fuelclient import profiler
|
||||
|
||||
|
||||
@@ -157,13 +158,15 @@ class Parser:
|
||||
prof.save_data()
|
||||
|
||||
def add_serializers_args(self):
|
||||
serializers = self.parser.add_mutually_exclusive_group()
|
||||
for format_name in Serializer.serializers.keys():
|
||||
serialization_flag = "--{0}".format(format_name)
|
||||
self.universal_flags.append(serialization_flag)
|
||||
self.parser.add_argument(
|
||||
serializers.add_argument(
|
||||
serialization_flag,
|
||||
dest=format_name,
|
||||
action="store_true",
|
||||
dest=consts.SERIALIZATION_FORMAT_FLAG,
|
||||
action="store_const",
|
||||
const=format_name,
|
||||
help="prints only {0} to stdout".format(format_name),
|
||||
default=False
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ import os
|
||||
import yaml
|
||||
|
||||
from fuelclient.cli import error
|
||||
from fuelclient import consts
|
||||
|
||||
|
||||
class Serializer(object):
|
||||
@@ -42,21 +43,33 @@ class Serializer(object):
|
||||
default_format = "yaml"
|
||||
format = default_format
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
for f in self.serializers:
|
||||
if kwargs.get(f, False):
|
||||
self.format = f
|
||||
self.format_flags = True
|
||||
break
|
||||
def __init__(self, format=None):
|
||||
if format and format in self.serializers:
|
||||
self.format = format
|
||||
self.format_flags = True
|
||||
|
||||
@property
|
||||
def serializer(self):
|
||||
"""Returns dicts with methods for loadin/dumping current fromat.
|
||||
|
||||
Returned dict's keys:
|
||||
* 'w' - from 'writing', method for serializing/dumping data
|
||||
* 'r' - from 'reading', method for deserializing/loading data
|
||||
"""
|
||||
return self.serializers[self.format]
|
||||
|
||||
def serialize(self, data):
|
||||
"""Shortcut for serializing data with current format."""
|
||||
return self.serializer['w'](data)
|
||||
|
||||
def deserialize(self, data):
|
||||
"""Shortcut for deserializing data with current format."""
|
||||
return self.serializer['r'](data)
|
||||
|
||||
@classmethod
|
||||
def from_params(cls, params):
|
||||
kwargs = dict((key, getattr(params, key)) for key in cls.serializers)
|
||||
return cls(**kwargs)
|
||||
return cls(format=getattr(params,
|
||||
consts.SERIALIZATION_FORMAT_FLAG, None))
|
||||
|
||||
def print_formatted(self, data):
|
||||
print(self.serializer["w"](data))
|
||||
|
||||
@@ -18,7 +18,6 @@ import requests
|
||||
|
||||
from keystoneclient.v2_0 import client as auth_client
|
||||
from six.moves.urllib import parse as urlparse
|
||||
import yaml
|
||||
|
||||
from fuelclient.cli.error import exceptions_decorator
|
||||
from fuelclient import fuelclient_settings
|
||||
@@ -188,10 +187,7 @@ class Client(object):
|
||||
|
||||
@exceptions_decorator
|
||||
def get_fuel_version(self):
|
||||
return yaml.safe_dump(
|
||||
self.get_request("version"),
|
||||
default_flow_style=False
|
||||
)
|
||||
return self.get_request("version")
|
||||
|
||||
# This line is single point of instantiation for 'Client' class,
|
||||
# which intended to implement Singleton design pattern.
|
||||
|
||||
17
fuelclient/consts.py
Normal file
17
fuelclient/consts.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
SERIALIZATION_FORMAT_FLAG = 'serialization_format'
|
||||
@@ -30,7 +30,7 @@ class BaseObject(object):
|
||||
|
||||
def __init__(self, obj_id, **kwargs):
|
||||
self.connection = APIClient
|
||||
self.serializer = Serializer(**kwargs)
|
||||
self.serializer = Serializer.from_params(kwargs.get('params'))
|
||||
self.id = obj_id
|
||||
self._data = None
|
||||
|
||||
|
||||
58
fuelclient/tests/common/unit/test_serializers.py
Normal file
58
fuelclient/tests/common/unit/test_serializers.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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
|
||||
|
||||
import mock
|
||||
import six
|
||||
import yaml
|
||||
|
||||
from fuelclient.cli.serializers import Serializer
|
||||
from fuelclient.tests import base
|
||||
|
||||
|
||||
class TestSerializers(base.UnitTestCase):
|
||||
|
||||
DATA = {
|
||||
'a': 1,
|
||||
'b': {
|
||||
'c': [2, 3, 4],
|
||||
'd': 'string',
|
||||
}
|
||||
}
|
||||
|
||||
def test_get_from_params(self):
|
||||
params_to_formats = (
|
||||
('yaml', 'yaml'),
|
||||
('json', 'json'),
|
||||
('xyz', Serializer.default_format),
|
||||
)
|
||||
for param, format in params_to_formats:
|
||||
params = mock.Mock(serialization_format=format)
|
||||
serializer = Serializer.from_params(params)
|
||||
self.assertEqual(serializer.format, format)
|
||||
|
||||
def test_serialize(self):
|
||||
deserializers = {'json': json.loads, 'yaml': yaml.load}
|
||||
for format, deserialize in six.iteritems(deserializers):
|
||||
serialized = Serializer(format).serialize(self.DATA)
|
||||
self.assertEqual(self.DATA, deserialize(serialized))
|
||||
|
||||
def test_deserialize(self):
|
||||
serializers = {'json': json.dumps, 'yaml': yaml.safe_dump}
|
||||
for format, serialize in six.iteritems(serializers):
|
||||
serialized = serialize(self.DATA)
|
||||
deserialized = Serializer(format).deserialize(serialized)
|
||||
self.assertEqual(self.DATA, deserialized)
|
||||
@@ -22,7 +22,7 @@ from fuelclient.tests import base
|
||||
class TestHandlers(base.BaseTestCase):
|
||||
|
||||
def test_env_action(self):
|
||||
#check env help
|
||||
# check env help
|
||||
help_msgs = ["usage: fuel environment [-h]",
|
||||
"[--list | --set | --delete | --create | --update]",
|
||||
"optional arguments:", "--help", "--list", "--set",
|
||||
@@ -31,13 +31,13 @@ class TestHandlers(base.BaseTestCase):
|
||||
"--network-mode", "--nst", "--net-segment-type",
|
||||
"--deployment-mode", "--update", "--env-update"]
|
||||
self.check_all_in_msg("env --help", help_msgs)
|
||||
#no clusters
|
||||
# no clusters
|
||||
self.check_for_rows_in_table("env")
|
||||
|
||||
for action in ("set", "create", "delete"):
|
||||
self.check_if_required("env {0}".format(action))
|
||||
|
||||
#list of tuples (<fuel CLI command>, <expected output of a command>)
|
||||
# list of tuples (<fuel CLI command>, <expected output of a command>)
|
||||
expected_stdout = \
|
||||
[(
|
||||
"env --create --name=TestEnv --release=1",
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
|
||||
import mock
|
||||
import requests_mock
|
||||
import yaml
|
||||
|
||||
from fuelclient.cli.actions import base
|
||||
from fuelclient.cli import error
|
||||
@@ -62,3 +66,63 @@ class TestBaseAction(base_tests.UnitTestCase):
|
||||
m_os.path.exists.return_value = True
|
||||
self.action.full_path_directory('/base/path', 'subdir')
|
||||
self.assertEqual(m_os.mkdir.call_count, 0)
|
||||
|
||||
|
||||
@requests_mock.mock()
|
||||
class TestFuelVersion(base_tests.UnitTestCase):
|
||||
|
||||
VERSION = {
|
||||
"astute_sha": "16b252d93be6aaa73030b8100cf8c5ca6a970a91",
|
||||
"release": "6.0",
|
||||
"build_id": "2014-12-26_14-25-46",
|
||||
"build_number": "58",
|
||||
"auth_required": True,
|
||||
"fuellib_sha": "fde8ba5e11a1acaf819d402c645c731af450aff0",
|
||||
"production": "docker",
|
||||
"nailgun_sha": "5f91157daa6798ff522ca9f6d34e7e135f150a90",
|
||||
"release_versions": {
|
||||
"2014.2-6.0": {
|
||||
"VERSION": {
|
||||
"ostf_sha": "a9afb68710d809570460c29d6c3293219d3624d4",
|
||||
"astute_sha": "16b252d93be6aaa73030b8100cf8c5ca6a970a91",
|
||||
"release": "6.0",
|
||||
"build_id": "2014-12-26_14-25-46",
|
||||
"build_number": "58",
|
||||
"fuellib_sha": "fde8ba5e11a1acaf819d402c645c731af450aff0",
|
||||
"production": "docker",
|
||||
"nailgun_sha": "5f91157daa6798ff522ca9f6d34e7e135f150a90",
|
||||
"api": "1.0",
|
||||
"fuelmain_sha": "81d38d6f2903b5a8b4bee79ca45a54b76c1361b8",
|
||||
"feature_groups": [
|
||||
"mirantis"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"api": "1.0",
|
||||
"fuelmain_sha": "81d38d6f2903b5a8b4bee79ca45a54b76c1361b8",
|
||||
"feature_groups": [
|
||||
"mirantis"
|
||||
]
|
||||
}
|
||||
|
||||
def test_return_yaml(self, mrequests):
|
||||
mrequests.get('/api/v1/version', json=self.VERSION)
|
||||
|
||||
with mock.patch('sys.stderr') as mstderr:
|
||||
with self.assertRaises(SystemExit):
|
||||
self.execute_wo_auth(['fuel', '--fuel-version', '--yaml'])
|
||||
args, _ = mstderr.write.call_args
|
||||
with self.assertRaisesRegexp(
|
||||
ValueError, 'No JSON object could be decoded'):
|
||||
json.loads(args[0])
|
||||
yaml.load(args[0])
|
||||
|
||||
def test_return_json(self, mrequests):
|
||||
mrequests.get('/api/v1/version', json=self.VERSION)
|
||||
|
||||
with mock.patch('sys.stderr') as mstderr:
|
||||
with self.assertRaises(SystemExit):
|
||||
self.execute_wo_auth(['fuel', '--fuel-version', '--json'])
|
||||
args, _ = mstderr.write.call_args
|
||||
json.loads(args[0])
|
||||
|
||||
32
fuelclient/tests/v1/unit/test_parser.py
Normal file
32
fuelclient/tests/v1/unit/test_parser.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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 mock
|
||||
|
||||
from fuelclient.tests import base
|
||||
|
||||
|
||||
class TestParser(base.UnitTestCase):
|
||||
|
||||
def test_choose_only_one_format(self):
|
||||
with mock.patch('sys.stderr') as mstderr:
|
||||
with self.assertRaises(SystemExit):
|
||||
self.execute_wo_auth(['fuel', '--json', '--yaml'])
|
||||
args, _ = mstderr.write.call_args
|
||||
self.assertRegexpMatches(
|
||||
args[0],
|
||||
r"argument (--json|--yaml): not allowed with"
|
||||
r" argument (--yaml|--json)")
|
||||
@@ -22,13 +22,13 @@ from fuelclient.tests import base
|
||||
class TestSnapshot(base.UnitTestCase):
|
||||
|
||||
@patch('fuelclient.cli.actions.snapshot.SnapshotTask.get_default_config')
|
||||
@patch('sys.stdout.write')
|
||||
def test_get_default_config(self, mwrite, mconf):
|
||||
@patch('sys.stdout')
|
||||
def test_get_default_config(self, mstdout, mconf):
|
||||
|
||||
mconf.return_value = {'key': 'value'}
|
||||
|
||||
self.execute(['fuel', 'snapshot', '--conf'])
|
||||
self.assertEqual(mwrite.call_args_list, [call('key: value\n')])
|
||||
self.assertEqual(mstdout.write.call_args_list, [call('key: value\n')])
|
||||
|
||||
@patch('fuelclient.cli.actions.snapshot.SnapshotTask.start_snapshot_task')
|
||||
@patch('fuelclient.cli.actions.snapshot.'
|
||||
|
||||
Reference in New Issue
Block a user