1# Licensed under the Apache License, Version 2.0 (the "License"); you may 2# not use this file except in compliance with the License. You may obtain 3# a copy of the License at 4# 5# http://www.apache.org/licenses/LICENSE-2.0 6# 7# Unless required by applicable law or agreed to in writing, software 8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10# License for the specific language governing permissions and limitations 11# under the License. 12# 13from unittest import mock 14 15from osc_lib.cli import format_columns 16from osc_lib import exceptions 17from osc_lib import utils as common_utils 18 19from openstackclient.compute.v2 import server_image 20from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes 21from openstackclient.tests.unit.image.v2 import fakes as image_fakes 22 23 24class TestServerImage(compute_fakes.TestComputev2): 25 26 def setUp(self): 27 super(TestServerImage, self).setUp() 28 29 # Get a shortcut to the compute client ServerManager Mock 30 self.servers_mock = self.app.client_manager.compute.servers 31 self.servers_mock.reset_mock() 32 33 # Get a shortcut to the image client ImageManager Mock 34 self.images_mock = self.app.client_manager.image 35 self.images_mock.find_image.reset_mock() 36 37 # Set object attributes to be tested. Could be overwritten in subclass. 38 self.attrs = {} 39 40 # Set object methods to be tested. Could be overwritten in subclass. 41 self.methods = {} 42 43 def setup_servers_mock(self, count): 44 servers = compute_fakes.FakeServer.create_servers( 45 attrs=self.attrs, 46 methods=self.methods, 47 count=count, 48 ) 49 50 # This is the return value for utils.find_resource() 51 self.servers_mock.get = compute_fakes.FakeServer.get_servers( 52 servers, 53 0, 54 ) 55 return servers 56 57 58class TestServerImageCreate(TestServerImage): 59 60 def image_columns(self, image): 61 # columnlist = tuple(sorted(image.keys())) 62 columnlist = ( 63 'id', 'name', 'owner', 'protected', 'status', 'tags', 'visibility' 64 ) 65 return columnlist 66 67 def image_data(self, image): 68 datalist = ( 69 image['id'], 70 image['name'], 71 image['owner_id'], 72 image['is_protected'], 73 'active', 74 format_columns.ListColumn(image.get('tags')), 75 image['visibility'], 76 ) 77 return datalist 78 79 def setUp(self): 80 super(TestServerImageCreate, self).setUp() 81 82 # Get the command object to test 83 self.cmd = server_image.CreateServerImage(self.app, None) 84 85 self.methods = { 86 'create_image': None, 87 } 88 89 def setup_images_mock(self, count, servers=None): 90 if servers: 91 images = image_fakes.FakeImage.create_images( 92 attrs={ 93 'name': servers[0].name, 94 'status': 'active', 95 }, 96 count=count, 97 ) 98 else: 99 images = image_fakes.FakeImage.create_images( 100 attrs={ 101 'status': 'active', 102 }, 103 count=count, 104 ) 105 106 self.images_mock.find_image = mock.Mock(side_effect=images) 107 self.servers_mock.create_image = mock.Mock( 108 return_value=images[0].id, 109 ) 110 return images 111 112 def test_server_image_create_defaults(self): 113 servers = self.setup_servers_mock(count=1) 114 images = self.setup_images_mock(count=1, servers=servers) 115 116 arglist = [ 117 servers[0].id, 118 ] 119 verifylist = [ 120 ('server', servers[0].id), 121 ] 122 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 123 124 # In base command class ShowOne in cliff, abstract method take_action() 125 # returns a two-part tuple with a tuple of column names and a tuple of 126 # data to be shown. 127 columns, data = self.cmd.take_action(parsed_args) 128 129 # ServerManager.create_image(server, image_name, metadata=) 130 self.servers_mock.create_image.assert_called_with( 131 servers[0].id, 132 servers[0].name, 133 ) 134 135 self.assertEqual(self.image_columns(images[0]), columns) 136 self.assertItemEqual(self.image_data(images[0]), data) 137 138 def test_server_image_create_options(self): 139 servers = self.setup_servers_mock(count=1) 140 images = self.setup_images_mock(count=1, servers=servers) 141 142 arglist = [ 143 '--name', 'img-nam', 144 servers[0].id, 145 ] 146 verifylist = [ 147 ('name', 'img-nam'), 148 ('server', servers[0].id), 149 ] 150 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 151 152 # In base command class ShowOne in cliff, abstract method take_action() 153 # returns a two-part tuple with a tuple of column names and a tuple of 154 # data to be shown. 155 columns, data = self.cmd.take_action(parsed_args) 156 157 # ServerManager.create_image(server, image_name, metadata=) 158 self.servers_mock.create_image.assert_called_with( 159 servers[0].id, 160 'img-nam', 161 ) 162 163 self.assertEqual(self.image_columns(images[0]), columns) 164 self.assertItemEqual(self.image_data(images[0]), data) 165 166 @mock.patch.object(common_utils, 'wait_for_status', return_value=False) 167 def test_server_create_image_wait_fail(self, mock_wait_for_status): 168 servers = self.setup_servers_mock(count=1) 169 images = self.setup_images_mock(count=1, servers=servers) 170 171 arglist = [ 172 '--wait', 173 servers[0].id, 174 ] 175 verifylist = [ 176 ('wait', True), 177 ('server', servers[0].id), 178 ] 179 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 180 181 self.assertRaises( 182 exceptions.CommandError, 183 self.cmd.take_action, 184 parsed_args, 185 ) 186 187 # ServerManager.create_image(server, image_name, metadata=) 188 self.servers_mock.create_image.assert_called_with( 189 servers[0].id, 190 servers[0].name, 191 ) 192 193 mock_wait_for_status.assert_called_once_with( 194 self.images_mock.get_image, 195 images[0].id, 196 callback=mock.ANY 197 ) 198 199 @mock.patch.object(common_utils, 'wait_for_status', return_value=True) 200 def test_server_create_image_wait_ok(self, mock_wait_for_status): 201 servers = self.setup_servers_mock(count=1) 202 images = self.setup_images_mock(count=1, servers=servers) 203 204 arglist = [ 205 '--wait', 206 servers[0].id, 207 ] 208 verifylist = [ 209 ('wait', True), 210 ('server', servers[0].id), 211 ] 212 parsed_args = self.check_parser(self.cmd, arglist, verifylist) 213 214 # In base command class ShowOne in cliff, abstract method take_action() 215 # returns a two-part tuple with a tuple of column names and a tuple of 216 # data to be shown. 217 columns, data = self.cmd.take_action(parsed_args) 218 219 # ServerManager.create_image(server, image_name, metadata=) 220 self.servers_mock.create_image.assert_called_with( 221 servers[0].id, 222 servers[0].name, 223 ) 224 225 mock_wait_for_status.assert_called_once_with( 226 self.images_mock.get_image, 227 images[0].id, 228 callback=mock.ANY 229 ) 230 231 self.assertEqual(self.image_columns(images[0]), columns) 232 self.assertItemEqual(self.image_data(images[0]), data) 233