Support deployment history for fuel client v1

Add new commands for Fuel v1:

fuel deployment-tasks --task-id 5 --statuses error --nodes 1,2

Add tests

Change-Id: I5a9633058925491b939c3dfe8979dc43e4c7763c
Implements: blueprint store-deployment-tasks-history
This commit is contained in:
Vladimir Sharshov (warpc)
2016-03-25 20:10:50 +03:00
parent 6d2f207b2a
commit 3dc2837d2a
6 changed files with 235 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ All action classes must be added to action_tuple to be used by parser
"""
from fuelclient.cli.actions.deploy import DeployChangesAction
from fuelclient.cli.actions.deploy import RedeployChangesAction
from fuelclient.cli.actions.deployment_tasks import DeploymentTasksAction
from fuelclient.cli.actions.environment import EnvironmentAction
from fuelclient.cli.actions.fact import DeploymentAction
from fuelclient.cli.actions.fact import ProvisioningAction
@@ -48,6 +49,7 @@ from fuelclient.cli.actions.vip import VIPAction
actions_tuple = (
DeployChangesAction,
DeploymentAction,
DeploymentTasksAction,
EnvironmentAction,
FuelVersionAction,
GraphAction,

View File

@@ -0,0 +1,71 @@
# 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.cli.actions.base import Action
import fuelclient.cli.arguments as Args
from fuelclient.cli.arguments import group
from fuelclient.cli.formatting import format_table
from fuelclient.objects.deployment_history import DeploymentHistory
class DeploymentTasksAction(Action):
"""Show deployment tasks
"""
action_name = "deployment-tasks"
acceptable_keys = ("deployment_graph_task_name", "node_id", "status",
"time_start", "time_end")
def __init__(self):
super(DeploymentTasksAction, self).__init__()
self.args = [
group(
Args.get_list_arg("List all deployment tasks"),
),
Args.get_single_task_arg(required=True),
Args.get_deployment_node_arg(
"Node ids."
),
Args.get_status_arg(
"Statuses: pending, error, ready, running, skipped"
)
]
self.flag_func_map = (
(None, self.list),
)
def list(self, params):
"""To display all deployment tasks:
fuel deployment-tasks --task-id 5
To display deployment tasks with for some nodes:
fuel deployment-tasks --task-id 5 --nodes 1,2
To display deployment tasks with for some statuses(pending, error,
ready, running):
fuel deployment-tasks --task-id 5 --statuses pending,running
To display deployment tasks with for some statuses(pending, error,
ready, running) on some nodes:
fuel deployment-tasks --task-id 5 --statuses error --nodes 1,2
"""
d_tasks_data = DeploymentHistory.get_all_with_nodes_and_statuses(
params.task,
params.node,
params.status
)
self.serializer.print_to_output(
d_tasks_data,
format_table(d_tasks_data, acceptable_keys=self.acceptable_keys)
)

View File

@@ -25,6 +25,7 @@ substitutions = {
# replace from: to
"env": "environment",
"nodes": "node",
"statuses": "status",
"net": "network",
"rel": "release",
"list": "--list",
@@ -179,6 +180,15 @@ def get_env_arg(required=False):
)
def get_single_task_arg(required=False):
return get_int_arg(
"task",
flags=("--task-id", "--tid"),
help="task id",
required=required
)
def get_new_password_arg(help_msg):
return get_str_arg(
"newpass",
@@ -666,3 +676,25 @@ def get_upload_file_arg(help_msg):
flags=("-u", "--upload",),
help=help_msg
)
def get_status_arg(help_msg):
default_kwargs = {
"action": SetAction,
"flags": ("--status",),
"nargs": '+',
"default": None,
"help": help_msg
}
return get_arg("status", **default_kwargs)
def get_deployment_node_arg(help_msg):
default_kwargs = {
"action": SetAction,
"flags": ("--node-id",),
"nargs": '+',
"default": None,
"help": help_msg
}
return get_arg("node", **default_kwargs)

View File

@@ -17,6 +17,7 @@ functionality from nailgun objects.
"""
from fuelclient.objects.base import BaseObject
from fuelclient.objects.deployment_history import DeploymentHistory
from fuelclient.objects.environment import Environment
from fuelclient.objects.node import Node
from fuelclient.objects.node import NodeCollection

View File

@@ -0,0 +1,34 @@
# 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.objects.base import BaseObject
class DeploymentHistory(BaseObject):
class_api_path = "transactions/{transaction_id}/deployment_history/"\
"?nodes={nodes}&statuses={statuses}"
@classmethod
def get_all_with_nodes_and_statuses(cls, transaction_id,
nodes=None, statuses=None):
statuses = ",".join(str(s) for s in statuses) if statuses else ""
nodes = ",".join(str(n) for n in nodes) if nodes else ""
history = cls.connection.get_request(
cls.class_api_path.format(
transaction_id=transaction_id,
nodes=nodes,
statuses=statuses))
return history

View File

@@ -0,0 +1,95 @@
# -*- 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 mock import patch
from fuelclient.cli.actions import DeploymentTasksAction
from fuelclient.cli.formatting import format_table
from fuelclient.cli.serializers import Serializer
from fuelclient.tests.unit.v1 import base
HISTORY_API_OUTPUT = [
{
"status": "ready",
"time_start": "2016-03-25T17:22:10.687135",
"time_end": "2016-03-25T17:22:30.830701",
"node_id": "1",
"deployment_graph_task_name": "controller_remaining_tasks"
},
{
"status": "skipped",
"time_start": "2016-03-25T17:23:37.313212",
"time_end": "2016-03-25T17:23:37.313234",
"node_id": "2",
"deployment_graph_task_name": "ironic-compute"
}
]
class TestDeploymentTasksAction(base.UnitTestCase):
def assert_print_table(self, print_mock, tasks):
print_mock.assert_called_once_with(
tasks, format_table(
tasks,
acceptable_keys=DeploymentTasksAction.acceptable_keys))
@patch.object(Serializer, 'print_to_output')
def test_show_full_history(self, print_mock):
self.m_history_api = self.m_request.get(
'/api/v1/transactions/1/deployment_history/?nodes=&statuses=',
json=HISTORY_API_OUTPUT)
self.execute(
['fuel', 'deployment-tasks', '--tid', '1']
)
self.assert_print_table(print_mock, HISTORY_API_OUTPUT)
def test_show_history_for_special_nodes(self):
self.m_history_api = self.m_request.get(
'/api/v1/transactions/1/deployment_history/?nodes=1,2&statuses=',
json={})
self.execute(
['fuel', 'deployment-tasks', '--tid', '1',
'--node-id', '1,2']
)
self.assertEqual(self.m_history_api.call_count, 1)
def test_show_history_with_special_statuses(self):
self.m_history_api = self.m_request.get(
'/api/v1/transactions/1/deployment_history/'
'?nodes=&statuses=ready,skipped',
json={})
self.execute(
['fuel', 'deployment-tasks', '--tid', '1',
'--status', 'ready,skipped']
)
self.assertEqual(self.m_history_api.call_count, 1)
def test_show_history_with_special_statuses_for_special_nodes(self):
self.m_history_api = self.m_request.get(
'/api/v1/transactions/1/deployment_history/'
'?nodes=1,2&statuses=ready,skipped',
json={})
self.execute(
['fuel', 'deployment-tasks', '--tid', '1',
'--status', 'ready,skipped', '--node', '1,2']
)
self.assertEqual(self.m_history_api.call_count, 1)