Skip to content

Commit 0d298c9

Browse files
committed
MB-65427 Ignore expired passwords in is_cluster_initialized
is_cluster_initialized will no longer return an error when the user password has expired. Change-Id: I5431384400983090514e082137e985ae0074648c Reviewed-on: https://review.couchbase.org/c/couchbase-cli/+/224471 Tested-by: Build Bot <build@couchbase.com> Reviewed-by: Matt Hall <matt.hall@couchbase.com>
1 parent e03d8ef commit 0d298c9

3 files changed

Lines changed: 53 additions & 3 deletions

File tree

cluster_manager.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
BACKUP_SERVICE = 'backup'
3030

3131
ERR_AUTH = 'unable to access the REST API - please check your username (-u) and password (-p)'
32+
ERR_PASSWORD_EXPIRED = 'unable to access the REST API - Password expired'
3233
ERR_INTERNAL = 'Internal server error, please retry your request'
3334

3435
DEFAULT_REQUEST_TIMEOUT = 60
@@ -39,6 +40,10 @@
3940
VERSION = '0.0.0-0000'
4041

4142

43+
def unexpected_403_err(message):
44+
return f"Unexpected response for error 403: {message}"
45+
46+
4247
def one_zero_boolean_to_string(value: str) -> str:
4348
"""Helper function to convert arguments with 1/0 string values to true or false"""
4449
return 'true' if value == '1' else 'false'
@@ -252,7 +257,7 @@ def n1ql_query(self, stmt, args=None):
252257

253258
def is_cluster_initialized(self):
254259
data, errors = self.pools()
255-
if (errors and len(errors) == 1 and errors[0] == ERR_AUTH) or \
260+
if (errors and len(errors) == 1 and errors[0] in [ERR_AUTH, ERR_PASSWORD_EXPIRED]) or \
256261
(data and data['pools'] and len(data['pools']) > 0):
257262
return True, None
258263
return False, errors
@@ -2991,7 +2996,9 @@ def _handle_response(self, response):
29912996
return None, [errors['message'] + ": " + ", ".join(errors["permissions"])]
29922997
elif 'runtime_info' in errors and 'info' in errors['runtime_info']:
29932998
return None, [errors['runtime_info']['info']]
2994-
return None, [f"Unexpected response for error 403: {response.text}"]
2999+
elif 'passwordExpired' in errors and errors['passwordExpired']:
3000+
return None, [ERR_PASSWORD_EXPIRED]
3001+
return None, [unexpected_403_err(response.text)]
29953002
# Error codes from Eventing service
29963003
elif response.status_code in [406, 422, 423]:
29973004
errors = response.json()

test/mock_server.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ def _close(self, url, server, t):
256256

257257

258258
def get_pools(rest_params=None, server_args=None, path="", endpoint_match=None):
259+
if "override-pools" in server_args:
260+
return server_args["override-pools"]
261+
259262
is_admin = True
260263
enterprise = True
261264
version = '0.0.0-0000-enterprise'

test/test_cluster_manager.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
import json
1718
import unittest
19+
import unittest.mock
1820

19-
from cluster_manager import ClusterManager
21+
from mock_server import MockRESTServer
22+
23+
from cluster_manager import ERR_AUTH, ERR_PASSWORD_EXPIRED, ClusterManager, unexpected_403_err
2024

2125

2226
class ClusterManagerTest(unittest.TestCase):
@@ -209,3 +213,39 @@ def test_get_otp_names_of_matched_nodes(self):
209213
test['nodes_to_match'])
210214
self.assertEqual(errors, test['errors'])
211215
self.assertEqual(matched_nodes, test['matched_nodes'])
216+
217+
def test_is_cluster_initialized(self):
218+
tests = {
219+
"ErrAuthIgnored": {
220+
"pools_res": (None, [ERR_AUTH]),
221+
"server_status": 401,
222+
"server_res": {},
223+
"expected_res": (True, None)
224+
},
225+
"ErrPasswordExpiredIgnored": {
226+
"pools_res": (None, [ERR_PASSWORD_EXPIRED]),
227+
"server_status": 403,
228+
"server_res": {"message": "Password expired", "passwordExpired": True},
229+
"expected_res": (True, None)
230+
},
231+
"PropagateOtherErrors": {
232+
"pools_res": (None, ["Unknown error"]),
233+
"server_status": 403,
234+
"server_res": {"message": "Unknown error"},
235+
"expected_res": (False, [unexpected_403_err(json.dumps({"message": "Unknown error"}))])
236+
}
237+
}
238+
239+
for name, test in tests.items():
240+
with self.subTest(name=name):
241+
server = MockRESTServer('127.0.0.1', 6789)
242+
server.args['override-pools'] = (test["server_status"], test["server_res"])
243+
244+
server.run()
245+
246+
cluster_manager = ClusterManager("http://127.0.0.1:6789", "Administrator", "asdasd")
247+
res = cluster_manager.is_cluster_initialized()
248+
249+
server.shutdown()
250+
251+
self.assertEqual(res, test["expected_res"])

0 commit comments

Comments
 (0)