Skip to content

Commit 61579a5

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Add project and domain params to network create"
2 parents 6214344 + 6c224f5 commit 61579a5

4 files changed

Lines changed: 138 additions & 0 deletions

File tree

‎doc/source/command-objects/network.rst‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,20 @@ Create new network
1313
.. code:: bash
1414
1515
os network create
16+
[--domain <domain>]
1617
[--enable | --disable]
18+
[--project <project>]
1719
[--share | --no-share]
1820
<name>
1921
22+
.. option:: --domain <domain>
23+
24+
Owner's domain (name or ID)"
25+
26+
.. option:: --project <project>
27+
28+
Owner's project (name or ID)
29+
2030
.. option:: --enable
2131

2232
Enable network (default)

‎openstackclient/network/v2/network.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
from openstackclient.common import exceptions
2424
from openstackclient.common import utils
25+
from openstackclient.identity import common as identity_common
2526
from openstackclient.network import common
2627

2728

@@ -82,6 +83,14 @@ def get_parser(self, prog_name):
8283
action='store_false',
8384
help='Do not share the network between projects',
8485
)
86+
parser.add_argument(
87+
'--project',
88+
metavar='<project>',
89+
help="Owner's project (name or ID)")
90+
parser.add_argument(
91+
'--domain',
92+
metavar='<domain>',
93+
help="Owner's domain (name or ID)")
8594
return parser
8695

8796
def take_action(self, parsed_args):
@@ -101,6 +110,18 @@ def get_body(self, parsed_args):
101110
'admin_state_up': parsed_args.admin_state}
102111
if parsed_args.shared is not None:
103112
body['shared'] = parsed_args.shared
113+
if parsed_args.project is not None:
114+
identity_client = self.app.client_manager.identity
115+
if parsed_args.domain is not None:
116+
domain = identity_common.find_domain(identity_client,
117+
parsed_args.domain)
118+
project_id = utils.find_resource(identity_client.projects,
119+
parsed_args.project,
120+
domain_id=domain.id).id
121+
else:
122+
project_id = utils.find_resource(identity_client.projects,
123+
parsed_args.project).id
124+
body['tenant_id'] = project_id
104125
return {'network': body}
105126

106127

‎openstackclient/tests/identity/v2_0/fakes.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,13 @@ def __init__(self, **kwargs):
142142
self.auth_token = kwargs['token']
143143
self.management_url = kwargs['endpoint']
144144

145+
def __getattr__(self, name):
146+
# Map v3 'projects' back to v2 'tenants'
147+
if name == "projects":
148+
return self.tenants
149+
else:
150+
raise AttributeError(name)
151+
145152

146153
class TestIdentityv2(utils.TestCommand):
147154
def setUp(self):

‎openstackclient/tests/network/v2/test_network.py‎

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
from openstackclient.common import exceptions
1818
from openstackclient.network.v2 import network
19+
from openstackclient.tests import fakes
20+
from openstackclient.tests.identity.v2_0 import fakes as identity_fakes_v2
21+
from openstackclient.tests.identity.v3 import fakes as identity_fakes_v3
1922
from openstackclient.tests.network import common
2023

2124
RESOURCE = 'network'
@@ -65,6 +68,7 @@ def test_create_no_options(self):
6568
('name', FAKE_NAME),
6669
('admin_state', True),
6770
('shared', None),
71+
('project', None),
6872
]
6973
mocker = mock.Mock(return_value=copy.deepcopy(RESPONSE))
7074
self.app.client_manager.network.create_network = mocker
@@ -85,15 +89,36 @@ def test_create_all_options(self):
8589
arglist = [
8690
"--disable",
8791
"--share",
92+
"--project", identity_fakes_v3.project_name,
93+
"--domain", identity_fakes_v3.domain_name,
8894
FAKE_NAME,
8995
] + self.given_show_options
9096
verifylist = [
9197
('admin_state', False),
9298
('shared', True),
99+
('project', identity_fakes_v3.project_name),
100+
('domain', identity_fakes_v3.domain_name),
93101
('name', FAKE_NAME),
94102
] + self.then_show_options
95103
mocker = mock.Mock(return_value=copy.deepcopy(RESPONSE))
96104
self.app.client_manager.network.create_network = mocker
105+
identity_client = identity_fakes_v3.FakeIdentityv3Client(
106+
endpoint=fakes.AUTH_URL,
107+
token=fakes.AUTH_TOKEN,
108+
)
109+
self.app.client_manager.identity = identity_client
110+
self.projects_mock = self.app.client_manager.identity.projects
111+
self.projects_mock.get.return_value = fakes.FakeResource(
112+
None,
113+
copy.deepcopy(identity_fakes_v3.PROJECT),
114+
loaded=True,
115+
)
116+
self.domains_mock = self.app.client_manager.identity.domains
117+
self.domains_mock.get.return_value = fakes.FakeResource(
118+
None,
119+
copy.deepcopy(identity_fakes_v3.DOMAIN),
120+
loaded=True,
121+
)
97122
cmd = network.CreateNetwork(self.app, self.namespace)
98123

99124
parsed_args = self.check_parser(cmd, arglist, verifylist)
@@ -104,6 +129,7 @@ def test_create_all_options(self):
104129
'admin_state_up': False,
105130
'name': FAKE_NAME,
106131
'shared': True,
132+
'tenant_id': identity_fakes_v3.project_id,
107133
}
108134
})
109135
self.assertEqual(FILTERED, result)
@@ -135,6 +161,80 @@ def test_create_other_options(self):
135161
})
136162
self.assertEqual(FILTERED, result)
137163

164+
def test_create_with_project_identityv2(self):
165+
arglist = [
166+
"--project", identity_fakes_v2.project_name,
167+
FAKE_NAME,
168+
169+
]
170+
verifylist = [
171+
('admin_state', True),
172+
('shared', None),
173+
('name', FAKE_NAME),
174+
('project', identity_fakes_v2.project_name),
175+
]
176+
mocker = mock.Mock(return_value=copy.deepcopy(RESPONSE))
177+
self.app.client_manager.network.create_network = mocker
178+
identity_client = identity_fakes_v2.FakeIdentityv2Client(
179+
endpoint=fakes.AUTH_URL,
180+
token=fakes.AUTH_TOKEN,
181+
)
182+
self.app.client_manager.identity = identity_client
183+
self.projects_mock = self.app.client_manager.identity.tenants
184+
self.projects_mock.get.return_value = fakes.FakeResource(
185+
None,
186+
copy.deepcopy(identity_fakes_v2.PROJECT),
187+
loaded=True,
188+
)
189+
cmd = network.CreateNetwork(self.app, self.namespace)
190+
191+
parsed_args = self.check_parser(cmd, arglist, verifylist)
192+
result = list(cmd.take_action(parsed_args))
193+
194+
mocker.assert_called_with({
195+
RESOURCE: {
196+
'admin_state_up': True,
197+
'name': FAKE_NAME,
198+
'tenant_id': identity_fakes_v2.project_id,
199+
}
200+
})
201+
self.assertEqual(FILTERED, result)
202+
203+
def test_create_with_domain_identityv2(self):
204+
arglist = [
205+
"--project", identity_fakes_v3.project_name,
206+
"--domain", identity_fakes_v3.domain_name,
207+
FAKE_NAME,
208+
]
209+
verifylist = [
210+
('admin_state', True),
211+
('shared', None),
212+
('project', identity_fakes_v3.project_name),
213+
('domain', identity_fakes_v3.domain_name),
214+
('name', FAKE_NAME),
215+
]
216+
mocker = mock.Mock(return_value=copy.deepcopy(RESPONSE))
217+
self.app.client_manager.network.create_network = mocker
218+
identity_client = identity_fakes_v2.FakeIdentityv2Client(
219+
endpoint=fakes.AUTH_URL,
220+
token=fakes.AUTH_TOKEN,
221+
)
222+
self.app.client_manager.identity = identity_client
223+
self.projects_mock = self.app.client_manager.identity.tenants
224+
self.projects_mock.get.return_value = fakes.FakeResource(
225+
None,
226+
copy.deepcopy(identity_fakes_v2.PROJECT),
227+
loaded=True,
228+
)
229+
cmd = network.CreateNetwork(self.app, self.namespace)
230+
parsed_args = self.check_parser(cmd, arglist, verifylist)
231+
232+
self.assertRaises(
233+
AttributeError,
234+
cmd.take_action,
235+
parsed_args,
236+
)
237+
138238

139239
class TestDeleteNetwork(common.TestNetworkBase):
140240
def test_delete(self):

0 commit comments

Comments
 (0)