Merge "Introduced command 'env redeploy' in v2 version of fuelclient"
This commit is contained in:
commit
a54da335f1
@ -201,14 +201,35 @@ class EnvDeploy(EnvMixIn, base.BaseCommand):
|
||||
|
||||
parser.add_argument('id',
|
||||
type=int,
|
||||
help='Id of the nailgun entity to be processed.')
|
||||
help='Id of the environment to be deployed.')
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
task_id = self.client.deploy_changes(parsed_args.id)
|
||||
|
||||
msg = 'Deploy task with id {t} for the environment {e} '\
|
||||
msg = 'Deployment task with id {t} for the environment {e} '\
|
||||
'has been started.\n'.format(t=task_id, e=parsed_args.id)
|
||||
|
||||
self.app.stdout.write(msg)
|
||||
|
||||
|
||||
class EnvRedeploy(EnvMixIn, base.BaseCommand):
|
||||
"""Redeploys changes on the specified environment."""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(EnvRedeploy, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument('id',
|
||||
type=int,
|
||||
help='Id of the environment to be redeployed.')
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
task_id = self.client.redeploy_changes(parsed_args.id)
|
||||
|
||||
msg = 'Deployment task with id {t} for the environment {e} '\
|
||||
'has been started.\n'.format(t=task_id, e=parsed_args.id)
|
||||
|
||||
self.app.stdout.write(msg)
|
||||
|
@ -14,4 +14,21 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
def Enum(*values, **kwargs):
|
||||
names = kwargs.get('names')
|
||||
if names:
|
||||
return namedtuple('Enum', names)(*values)
|
||||
return namedtuple('Enum', values)(*values)
|
||||
|
||||
|
||||
SERIALIZATION_FORMAT_FLAG = 'serialization_format'
|
||||
|
||||
TASK_STATUSES = Enum(
|
||||
'error',
|
||||
'pending',
|
||||
'ready',
|
||||
'running'
|
||||
)
|
||||
|
@ -12,24 +12,27 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from oslotest import base as oslo_base
|
||||
|
||||
from fuelclient import consts
|
||||
from fuelclient.objects import Release
|
||||
|
||||
from oslotest import base as oslo_base
|
||||
|
||||
logging.basicConfig(stream=sys.stderr)
|
||||
log = logging.getLogger("CliTest.ExecutionLog")
|
||||
log.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
class CliExectutionResult(object):
|
||||
class CliExecutionResult(object):
|
||||
def __init__(self, process_handle, out, err):
|
||||
self.return_code = process_handle.returncode
|
||||
self.stdout = out
|
||||
@ -45,6 +48,8 @@ class CliExectutionResult(object):
|
||||
|
||||
|
||||
class BaseTestCase(oslo_base.BaseTestCase):
|
||||
|
||||
handler = ''
|
||||
nailgun_root = os.environ.get('NAILGUN_ROOT', '/tmp/fuel_web/nailgun')
|
||||
|
||||
def setUp(self):
|
||||
@ -91,7 +96,7 @@ class BaseTestCase(oslo_base.BaseTestCase):
|
||||
def run_cli_command(self, command_line,
|
||||
check_errors=True, env=os.environ.copy()):
|
||||
|
||||
command_args = [" ".join(('fuel', command_line))]
|
||||
command_args = [" ".join((self.handler, command_line))]
|
||||
process_handle = subprocess.Popen(
|
||||
command_args,
|
||||
stdout=subprocess.PIPE,
|
||||
@ -100,7 +105,7 @@ class BaseTestCase(oslo_base.BaseTestCase):
|
||||
env=env
|
||||
)
|
||||
out, err = process_handle.communicate()
|
||||
result = CliExectutionResult(process_handle, out, err)
|
||||
result = CliExecutionResult(process_handle, out, err)
|
||||
log.debug("command_args: '%s',stdout: '%s', stderr: '%s'",
|
||||
command_args[0], out, err)
|
||||
if check_errors:
|
||||
@ -129,6 +134,12 @@ class BaseTestCase(oslo_base.BaseTestCase):
|
||||
call = self.run_cli_command(command, check_errors=check_errors)
|
||||
self.assertEqual(call.stdout, msg)
|
||||
|
||||
def check_for_stdout_by_regexp(self, command, pattern, check_errors=True):
|
||||
call = self.run_cli_command(command, check_errors=check_errors)
|
||||
result = re.search(pattern, call.stdout)
|
||||
self.assertIsNotNone(result)
|
||||
return result
|
||||
|
||||
def check_for_stderr(self, command, msg, check_errors=True):
|
||||
call = self.run_cli_command(command, check_errors=check_errors)
|
||||
self.assertIn(msg, call.stderr)
|
||||
@ -147,3 +158,59 @@ class BaseTestCase(oslo_base.BaseTestCase):
|
||||
def check_number_of_rows_in_table(self, command, number_of_rows):
|
||||
output = self.run_cli_command(command)
|
||||
self.assertEqual(len(output.stdout.split("\n")), number_of_rows + 3)
|
||||
|
||||
def _get_task_info(self, task_id):
|
||||
"""Get info about task with given ID.
|
||||
|
||||
:param task_id: Task ID
|
||||
:type task_id: str or int
|
||||
:return: Task info
|
||||
:rtype: dict
|
||||
"""
|
||||
return {}
|
||||
|
||||
def wait_task_ready(self, task_id, timeout=60, interval=3):
|
||||
"""Wait for changing task status to 'ready'.
|
||||
|
||||
:param task_id: Task ID
|
||||
:type task_id: str or int
|
||||
:param timeout: Max time of waiting, in seconds
|
||||
:type timeout: int
|
||||
:param interval: Interval of getting task info, in seconds
|
||||
:type interval: int
|
||||
"""
|
||||
wait_until_in_statuses = (consts.TASK_STATUSES.running,
|
||||
consts.TASK_STATUSES.pending)
|
||||
timer = time.time()
|
||||
while True:
|
||||
task = self._get_task_info(task_id)
|
||||
status = task.get('status', '')
|
||||
if status not in wait_until_in_statuses:
|
||||
self.assertEqual(status, consts.TASK_STATUSES.ready)
|
||||
break
|
||||
|
||||
if time.time() - timer > timeout:
|
||||
raise Exception(
|
||||
"Task '{0}' seems to be hanged".format(task['name'])
|
||||
)
|
||||
time.sleep(interval)
|
||||
|
||||
|
||||
class CLIv1TestCase(BaseTestCase):
|
||||
|
||||
handler = 'fuel'
|
||||
|
||||
def _get_task_info(self, task_id):
|
||||
command = "task --task {0} --json".format(str(task_id))
|
||||
call = self.run_cli_command(command)
|
||||
return json.loads(call.stdout)[0]
|
||||
|
||||
|
||||
class CLIv2TestCase(BaseTestCase):
|
||||
|
||||
handler = 'fuel2'
|
||||
|
||||
def _get_task_info(self, task_id):
|
||||
command = "task show -f json {0}".format(str(task_id))
|
||||
call = self.run_cli_command(command)
|
||||
return json.loads(call.stdout)
|
||||
|
@ -20,7 +20,7 @@ import tempfile
|
||||
from fuelclient.tests.functional import base
|
||||
|
||||
|
||||
class TestHandlers(base.BaseTestCase):
|
||||
class TestHandlers(base.CLIv1TestCase):
|
||||
|
||||
def test_env_action(self):
|
||||
# check env help
|
||||
@ -289,7 +289,7 @@ class TestHandlers(base.BaseTestCase):
|
||||
)
|
||||
|
||||
|
||||
class TestCharset(base.BaseTestCase):
|
||||
class TestCharset(base.CLIv1TestCase):
|
||||
|
||||
def test_charset_problem(self):
|
||||
self.load_data_to_nailgun_server()
|
||||
@ -301,7 +301,7 @@ class TestCharset(base.BaseTestCase):
|
||||
))
|
||||
|
||||
|
||||
class TestFiles(base.BaseTestCase):
|
||||
class TestFiles(base.CLIv1TestCase):
|
||||
|
||||
def test_file_creation(self):
|
||||
self.load_data_to_nailgun_server()
|
||||
@ -393,7 +393,7 @@ class TestFiles(base.BaseTestCase):
|
||||
))
|
||||
|
||||
|
||||
class TestDownloadUploadNodeAttributes(base.BaseTestCase):
|
||||
class TestDownloadUploadNodeAttributes(base.CLIv1TestCase):
|
||||
|
||||
def test_upload_download_interfaces(self):
|
||||
self.load_data_to_nailgun_server()
|
||||
@ -415,35 +415,43 @@ class TestDownloadUploadNodeAttributes(base.BaseTestCase):
|
||||
self.upload_command(cmd)))
|
||||
|
||||
|
||||
class TestDeployChanges(base.BaseTestCase):
|
||||
class TestDeployChanges(base.CLIv1TestCase):
|
||||
|
||||
create_env = "env create --name=test --release={0}"
|
||||
add_node = "--env-id=1 node set --node 1 --role=controller"
|
||||
deploy_changes = "deploy-changes --env 1"
|
||||
redeploy_changes = "redeploy-changes --env 1"
|
||||
cmd_create_env = "env create --name=test --release={0}"
|
||||
cmd_add_node = "--env-id=1 node set --node 1 --role=controller"
|
||||
cmd_deploy_changes = "deploy-changes --env 1"
|
||||
cmd_redeploy_changes = "redeploy-changes --env 1"
|
||||
|
||||
messages_success = [
|
||||
"Deploying changes to environment with id=1\n",
|
||||
"Finished deployment!\n"
|
||||
]
|
||||
message_error = "(No changes to deploy)\n"
|
||||
|
||||
def setUp(self):
|
||||
super(TestDeployChanges, self).setUp()
|
||||
self.load_data_to_nailgun_server()
|
||||
release_id = self.get_first_deployable_release_id()
|
||||
self.create_env = self.create_env.format(release_id)
|
||||
self.run_cli_commands((self.create_env, self.add_node))
|
||||
self.cmd_create_env = self.cmd_create_env.format(release_id)
|
||||
self.run_cli_commands((
|
||||
self.cmd_create_env,
|
||||
self.cmd_add_node
|
||||
))
|
||||
|
||||
def test_deploy_changes(self):
|
||||
self.run_cli_commands((self.deploy_changes,))
|
||||
|
||||
def test_no_changes_to_deploy(self):
|
||||
self.run_cli_commands((self.deploy_changes,))
|
||||
self.check_for_stderr(self.deploy_changes,
|
||||
"(No changes to deploy)\n",
|
||||
check_errors=False)
|
||||
self.check_all_in_msg(self.cmd_deploy_changes,
|
||||
self.messages_success)
|
||||
|
||||
def test_redeploy_changes(self):
|
||||
self.run_cli_commands((self.deploy_changes,
|
||||
self.redeploy_changes))
|
||||
self.run_cli_command(self.cmd_deploy_changes)
|
||||
self.check_for_stderr(self.cmd_deploy_changes,
|
||||
self.message_error,
|
||||
check_errors=False)
|
||||
self.check_all_in_msg(self.cmd_redeploy_changes,
|
||||
self.messages_success)
|
||||
|
||||
|
||||
class TestDirectoryDoesntExistErrorMessages(base.BaseTestCase):
|
||||
class TestDirectoryDoesntExistErrorMessages(base.CLIv1TestCase):
|
||||
|
||||
def test_settings_upload(self):
|
||||
self.check_for_stderr(
|
||||
@ -520,7 +528,7 @@ class TestDirectoryDoesntExistErrorMessages(base.BaseTestCase):
|
||||
)
|
||||
|
||||
|
||||
class TestUploadSettings(base.BaseTestCase):
|
||||
class TestUploadSettings(base.CLIv1TestCase):
|
||||
|
||||
create_env = "env create --name=test --release={0}"
|
||||
add_node = "--env-id=1 node set --node 1 --role=controller"
|
||||
|
56
fuelclient/tests/functional/v2/test_client.py
Normal file
56
fuelclient/tests/functional/v2/test_client.py
Normal file
@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2013-2014 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.tests.functional import base
|
||||
|
||||
|
||||
class TestDeployChanges(base.CLIv2TestCase):
|
||||
|
||||
cmd_create_env = "env create -r {0} cluster-test"
|
||||
cmd_add_node = "env add nodes -e 1 -n 1 -r controller"
|
||||
cmd_deploy_changes = "env deploy 1"
|
||||
cmd_redeploy_changes = "env redeploy 1"
|
||||
|
||||
pattern_success = (r"^Deployment task with id (\d{1,}) "
|
||||
r"for the environment 1 has been started.\n$")
|
||||
message_error = "(No changes to deploy)\n"
|
||||
|
||||
def setUp(self):
|
||||
super(TestDeployChanges, self).setUp()
|
||||
self.load_data_to_nailgun_server()
|
||||
release_id = self.get_first_deployable_release_id()
|
||||
self.cmd_create_env = self.cmd_create_env.format(release_id)
|
||||
self.run_cli_commands((
|
||||
self.cmd_create_env,
|
||||
self.cmd_add_node
|
||||
))
|
||||
|
||||
def test_deploy_changes(self):
|
||||
self.check_for_stdout_by_regexp(self.cmd_deploy_changes,
|
||||
self.pattern_success)
|
||||
|
||||
def test_redeploy_changes(self):
|
||||
result = self.check_for_stdout_by_regexp(self.cmd_deploy_changes,
|
||||
self.pattern_success)
|
||||
task_id = result.group(1)
|
||||
self.wait_task_ready(task_id)
|
||||
|
||||
self.check_for_stderr(self.cmd_deploy_changes,
|
||||
self.message_error,
|
||||
check_errors=False)
|
||||
|
||||
self.check_for_stdout_by_regexp(self.cmd_redeploy_changes,
|
||||
self.pattern_success)
|
@ -95,6 +95,13 @@ class TestEnvCommand(test_engine.BaseCLITest):
|
||||
self.m_get_client.assert_called_once_with('environment', mock.ANY)
|
||||
self.m_client.deploy_changes.assert_called_once_with(42)
|
||||
|
||||
def test_env_redeploy(self):
|
||||
args = 'env redeploy 42'
|
||||
self.exec_command(args)
|
||||
|
||||
self.m_get_client.assert_called_once_with('environment', mock.ANY)
|
||||
self.m_client.redeploy_changes.assert_called_once_with(42)
|
||||
|
||||
def test_env_add_nodes(self):
|
||||
args = 'env add nodes -e 42 -n 24 25 -r compute cinder'
|
||||
self.exec_command(args)
|
||||
|
@ -71,6 +71,12 @@ class EnvironmentClient(base_v1.BaseV1Client):
|
||||
|
||||
return deploy_task.id
|
||||
|
||||
def redeploy_changes(self, environment_id):
|
||||
env = self._entity_wrapper(obj_id=environment_id)
|
||||
redeploy_task = env.redeploy_changes()
|
||||
|
||||
return redeploy_task.id
|
||||
|
||||
def spawn_vms(self, environment_id):
|
||||
env = self._entity_wrapper(obj_id=environment_id)
|
||||
return env.spawn_vms()
|
||||
|
@ -34,6 +34,7 @@ fuelclient =
|
||||
env_delete=fuelclient.commands.environment:EnvDelete
|
||||
env_deploy=fuelclient.commands.environment:EnvDeploy
|
||||
env_list=fuelclient.commands.environment:EnvList
|
||||
env_redeploy=fuelclient.commands.environment:EnvRedeploy
|
||||
env_show=fuelclient.commands.environment:EnvShow
|
||||
env_spawn-vms=fuelclient.commands.environment:EnvSpawnVms
|
||||
env_update=fuelclient.commands.environment:EnvUpdate
|
||||
|
2
tox.ini
2
tox.ini
@ -14,7 +14,7 @@ setenv = VIRTUAL_ENV={envdir}
|
||||
|
||||
# Functional env settings
|
||||
FUEL_WEB_CLONE={env:FUEL_WEB_CLONE:yes}
|
||||
FUEL_WEB_REPO={env:FUEL_WEB_REPO:https://github.com/stackforge/fuel-web.git}
|
||||
FUEL_WEB_REPO={env:FUEL_WEB_REPO:https://github.com/openstack/fuel-web.git}
|
||||
FUEL_WEB_ROOT={env:FUEL_WEB_ROOT:/tmp/fuel_web}
|
||||
FETCH_REPO={env:FETCH_REPO:}
|
||||
FETCH_REFSPEC={env:FETCH_REFSPEC:}
|
||||
|
Loading…
Reference in New Issue
Block a user