Fix PEP8 warning E501 line too long
[samba.git] / python / samba / tests / samba_tool / ou.py
1 # Unix SMB/CIFS implementation.
2 #
3 # Copyright (C) Bjoern Baumbach <bb@sernet.de> 2018
4 #
5 # based on group.py:
6 # Copyright (C) Michael Adam 2012
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21
22 import os
23 import ldb
24 from samba.tests.samba_tool.base import SambaToolCmdTest
25
26 class OUCmdTestCase(SambaToolCmdTest):
27     """Tests for samba-tool ou subcommands"""
28     ous = []
29     samdb = None
30
31     def setUp(self):
32         super(OUCmdTestCase, self).setUp()
33         self.samdb = self.getSamDB("-H", "ldap://%s" % os.environ["DC_SERVER"],
34             "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"]))
35         self.ous = []
36         self.ous.append(self._randomOU({"name": "testou1"}))
37         self.ous.append(self._randomOU({"name": "testou2"}))
38         self.ous.append(self._randomOU({"name": "testou3"}))
39         self.ous.append(self._randomOU({"name": "testou4"}))
40
41         # setup the 4 ous and ensure they are correct
42         for ou in self.ous:
43             (result, out, err) = self._create_ou(ou)
44
45             self.assertCmdSuccess(result, out, err)
46             self.assertEquals(err, "", "There shouldn't be any error message")
47             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
48             self.assertIn('Created ou "%s"' % full_ou_dn, out)
49
50             found = self._find_ou(ou["name"])
51
52             self.assertIsNotNone(found)
53
54             self.assertEquals("%s" % found.get("name"), ou["name"])
55             self.assertEquals("%s" % found.get("description"),
56                               ou["description"])
57
58     def tearDown(self):
59         super(OUCmdTestCase, self).tearDown()
60         # clean up all the left over ous, just in case
61         for ou in self.ous:
62             if self._find_ou(ou["name"]):
63                 (result, out, err) = self.runsubcmd("ou", "delete",
64                                                     "OU=%s" % ou["name"])
65                 self.assertCmdSuccess(result, out, err,
66                                       "Failed to delete ou '%s'" % ou["name"])
67
68
69     def test_newou(self):
70         """This tests the "ou create" and "ou delete" commands"""
71         # try to create all the ous again, this should fail
72         for ou in self.ous:
73             (result, out, err) = self._create_ou(ou)
74             self.assertCmdFail(result, "Succeeded to create existing ou")
75             self.assertIn("already exists", err)
76
77         # try to delete all the ous we just created
78         for ou in self.ous:
79             (result, out, err) = self.runsubcmd("ou", "delete", "OU=%s" %
80                                                 ou["name"])
81             self.assertCmdSuccess(result, out, err,
82                                   "Failed to delete ou '%s'" % ou["name"])
83             found = self._find_ou(ou["name"])
84             self.assertIsNone(found,
85                               "Deleted ou '%s' still exists" % ou["name"])
86
87         # test creating ous
88         for ou in self.ous:
89             (result, out, err) = self.runsubcmd(
90                 "ou", "create", "OU=%s" % ou["name"],
91                  "--description=%s" % ou["description"])
92
93             self.assertCmdSuccess(result, out, err)
94             self.assertEquals(err, "", "There shouldn't be any error message")
95             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
96             self.assertIn('Created ou "%s"' % full_ou_dn, out)
97
98             found = self._find_ou(ou["name"])
99
100             self.assertEquals("%s" % found.get("ou"),
101                               "%s" % ou["name"])
102
103         # try to delete all the ous we just created (with full dn)
104         for ou in self.ous:
105             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
106             (result, out, err) = self.runsubcmd("ou", "delete", str(full_ou_dn))
107             self.assertCmdSuccess(result, out, err,
108                                   "Failed to delete ou '%s'" % ou["name"])
109             found = self._find_ou(ou["name"])
110             self.assertIsNone(found,
111                               "Deleted ou '%s' still exists" % ou["name"])
112
113         # test creating ous (with full dn)
114         for ou in self.ous:
115             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
116             (result, out, err) = self.runsubcmd(
117                 "ou", "create", str(full_ou_dn),
118                  "--description=%s" % ou["description"])
119
120             self.assertCmdSuccess(result, out, err)
121             self.assertEquals(err, "", "There shouldn't be any error message")
122             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
123             self.assertIn('Created ou "%s"' % full_ou_dn, out)
124
125             found = self._find_ou(ou["name"])
126
127             self.assertEquals("%s" % found.get("ou"),
128                               "%s" % ou["name"])
129
130     def test_list(self):
131         (result, out, err) = self.runsubcmd("ou", "list")
132         self.assertCmdSuccess(result, out, err, "Error running list")
133
134         search_filter = "(objectClass=organizationalUnit)"
135
136         oulist = self.samdb.search(base=self.samdb.domain_dn(),
137                                       scope=ldb.SCOPE_SUBTREE,
138                                       expression=search_filter,
139                                       attrs=["name"])
140
141         self.assertTrue(len(oulist) > 0, "no ous found in samdb")
142
143         for ouobj in oulist:
144             name = ouobj.get("name", idx=0)
145             found = self.assertMatch(out, name,
146                                      "ou '%s' not found" % name)
147
148     def test_rename(self):
149         for ou in self.ous:
150             ousuffix = "RenameTest"
151             newouname = ou["name"] + ousuffix
152             (result, out, err) = self.runsubcmd("ou", "rename",
153                                                 "OU=%s" % ou["name"],
154                                                 "OU=%s" % newouname)
155             self.assertCmdSuccess(result, out, err,
156                                   "Failed to rename ou '%s'" % ou["name"])
157             found = self._find_ou(ou["name"])
158             self.assertIsNone(found,
159                               "Renamed ou '%s' still exists" % ou["name"])
160             found = self._find_ou(newouname)
161             self.assertIsNotNone(found,
162                               "Renamed ou '%s' does not exist" % newouname)
163
164             (result, out, err) = self.runsubcmd("ou", "rename",
165                                                 "OU=%s" % newouname,
166                                                 "OU=%s" % ou["name"])
167             self.assertCmdSuccess(result, out, err,
168                                   "Failed to rename ou '%s'" % newouname)
169
170     def test_move(self):
171         parentou = self._randomOU({"name": "parentOU"})
172         (result, out, err) = self._create_ou(parentou)
173         self.assertCmdSuccess(result, out, err)
174
175         for ou in self.ous:
176             olddn = self._find_ou(ou["name"]).get("dn")
177
178             (result, out, err) = self.runsubcmd("ou", "move",
179                                                 "OU=%s" % ou["name"],
180                                                 "OU=%s" % parentou["name"])
181             self.assertCmdSuccess(result, out, err,
182                                   "Failed to move ou '%s'" % ou["name"])
183             self.assertEquals(err, "", "There shouldn't be any error message")
184             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
185             self.assertIn('Moved ou "%s"' % full_ou_dn, out)
186
187             found = self._find_ou(ou["name"])
188             self.assertNotEquals(found.get("dn"), olddn,
189                                  "Moved ou '%s' still exists with the same dn" %
190                                  ou["name"])
191             newexpecteddn = ldb.Dn(self.samdb,
192                                    "OU=%s,OU=%s,%s" %
193                                    (ou["name"], parentou["name"],
194                                     self.samdb.domain_dn()))
195             self.assertEquals(found.get("dn"), newexpecteddn,
196                               "Moved ou '%s' does not exist" %
197                               ou["name"])
198
199             (result, out, err) = self.runsubcmd("ou", "move",
200                                                 "%s" % newexpecteddn,
201                                                 "%s" % olddn.parent())
202             self.assertCmdSuccess(result, out, err,
203                                   "Failed to move ou '%s'" % ou["name"])
204
205         (result, out, err) = self.runsubcmd("ou", "delete",
206                                             "OU=%s" % parentou["name"])
207         self.assertCmdSuccess(result, out, err,
208                               "Failed to delete ou '%s'" % parentou["name"])
209
210     def test_listobjects(self):
211         (result, out, err) = self.runsubcmd("ou", "listobjects",
212                                             "%s" % self.samdb.domain_dn(),
213                                             "--full-dn")
214         self.assertCmdSuccess(result, out, err,
215                               "Failed to list ou's objects")
216         self.assertEquals(err, "", "There shouldn't be any error message")
217
218         objlist = self.samdb.search(base=self.samdb.domain_dn(),
219                                     scope=ldb.SCOPE_ONELEVEL,
220                                     attrs=[])
221         self.assertTrue(len(objlist) > 0, "no objects found")
222
223         for obj in objlist:
224             found = self.assertMatch(out, str(obj.dn),
225                                      "object '%s' not found" % obj.dn)
226
227
228     def test_list(self):
229         (result, out, err) = self.runsubcmd("ou", "list",
230                                             "--full-dn")
231         self.assertCmdSuccess(result, out, err,
232                               "Failed to list ous")
233         self.assertEquals(err, "", "There shouldn't be any error message")
234
235         filter = "(objectClass=organizationalUnit)"
236         objlist = self.samdb.search(base=self.samdb.domain_dn(),
237                                     scope=ldb.SCOPE_SUBTREE,
238                                     expression=filter,
239                                     attrs=[])
240         self.assertTrue(len(objlist) > 0, "no ou objects found")
241
242         for obj in objlist:
243             found = self.assertMatch(out, str(obj.dn),
244                                      "object '%s' not found" % obj.dn)
245
246
247     def _randomOU(self, base={}):
248         """create an ou with random attribute values, you can specify base
249         attributes"""
250
251         ou = {
252             "name": self.randomName(),
253             "description": self.randomName(count=100),
254             }
255         ou.update(base)
256         return ou
257
258     def _create_ou(self, ou):
259         return self.runsubcmd("ou", "create", "OU=%s" % ou["name"],
260                               "--description=%s" % ou["description"])
261
262     def _find_ou(self, name):
263         search_filter = ("(&(name=%s)(objectCategory=%s,%s))" %
264                          (ldb.binary_encode(name),
265                          "CN=Organizational-Unit,CN=Schema,CN=Configuration",
266                          self.samdb.domain_dn()))
267         oulist = self.samdb.search(base=self.samdb.domain_dn(),
268                                    scope=ldb.SCOPE_SUBTREE,
269                                    expression=search_filter,
270                                    attrs=[])
271         if oulist:
272             return oulist[0]
273         else:
274             return None