Example #1
0
 def test_parseMongoResponse_bad_json(self):
     with open("tests/fixtures/mongo_responses/replica-status-ok.txt") as f:
         with self.assertRaises(ValueError) as context:
             MongoResources.parseMongoResponse(f.read().replace(
                 "Timestamp", "TimeStamp"))
     self.assertIn("Cannot parse JSON because of error",
                   str(context.exception))
    def _execInPod(self, pod_index: int, name: str, namespace: str,
                   mongo_command: str) -> Dict[str, any]:
        """
        Executes the given mongo command inside the pod with the given name.
        Retries a few times in case we receive a handshake failure.
        :param pod_index: The index of the pod.
        :param name: The name of the cluster.
        :param namespace: The namespace of the cluster.
        :param mongo_command: The command to be executed in mongo.
        :return: The response from MongoDB. See files in `tests/fixtures/mongo_responses` for examples.
        :raise ValueError: If the result could not be parsed.
        :raise TimeoutError: If we could not connect to the pod after retrying.
        """
        exec_command = MongoResources.createMongoExecCommand(mongo_command)
        pod_name = "{}-{}".format(name, pod_index)

        for _ in range(self.EXEC_IN_POD_RETRIES):
            try:
                exec_response = self.kubernetes_service.execInPod(
                    self.CONTAINER, pod_name, namespace, exec_command)
                response = MongoResources.parseMongoResponse(exec_response)
                if response.get("ok") == 0 and response.get(
                        "codeName") == "NodeNotFound":
                    logging.info(
                        "Waiting for replica set members for %s @ ns/%s: %s",
                        pod_name, namespace, response)
                else:
                    return response

            except ValueError as e:
                if str(e) not in ("connection attempt failed",
                                  "connect failed"):
                    raise
                logging.info(
                    "Could not connect to Mongo in pod %s @ ns/%s: %s",
                    pod_name, namespace, e)

            except ApiException as e:
                if "Handshake status" not in e.reason:
                    logging.error(
                        "Error sending following command to pod %s: %s",
                        pod_name, repr(mongo_command))
                    raise
                logging.info(
                    "Could not check the replica set or initialize it because of %s. The service is probably "
                    "starting up. We wait %s seconds before retrying.",
                    e.reason, self.EXEC_IN_POD_WAIT)
            sleep(self.EXEC_IN_POD_WAIT)

        raise TimeoutError(
            "Could not check the replica set after {} retries!".format(
                self.EXEC_IN_POD_RETRIES))
Example #3
0
 def test_parseMongoResponse_not_initialized(self):
     with open(
             "tests/fixtures/mongo_responses/replica-status-not-initialized.txt"
     ) as f:
         response = MongoResources.parseMongoResponse(f.read())
     expected = {
         "info": "run rs.initiate(...) if not yet done for the set",
         "ok": 0,
         "errmsg": "no replset config has been received",
         "code": 94,
         "codeName": "NotYetInitialized"
     }
     self.assertEqual(expected, response)
Example #4
0
 def test_parseMongoResponse_user_created(self):
     with open("tests/fixtures/mongo_responses/createUser-ok.txt") as f:
         response = MongoResources.parseMongoResponse(f.read())
     expected = {"user": "******", "roles": [{"role": "root", "db": "admin"}]}
     self.assertEqual(expected, response)
Example #5
0
 def test_parseMongoResponse_version_twice(self):
     self.assertEqual({},
                      MongoResources.parseMongoResponse(
                          "MongoDB shell version v3.6.4\n"
                          "connecting to: mongodb://localhost:27017/admin\n"
                          "MongoDB server version: 3.6.4\n"))
Example #6
0
 def test_parseMongoResponse_only_version(self):
     self.assertEqual({},
                      MongoResources.parseMongoResponse(
                          "MongoDB shell version v3.6.4\n"))
Example #7
0
 def test_parseMongoResponse_empty(self):
     self.assertEqual({}, MongoResources.parseMongoResponse(''))
Example #8
0
 def test_parseMongoResponse_error(self):
     with open("tests/fixtures/mongo_responses/replica-status-error.txt"
               ) as f:
         with self.assertRaises(ValueError) as context:
             MongoResources.parseMongoResponse(f.read())
     self.assertEqual("connect failed", str(context.exception))
Example #9
0
 def test_parseMongoResponse_ok(self):
     with open("tests/fixtures/mongo_responses/replica-status-ok.txt") as f:
         response = MongoResources.parseMongoResponse(f.read())
     expected = {
         '$clusterTime': {
             'clusterTime': 1528362785.0,
             'signature': {
                 'hash': 'AAAAAAAAAAAAAAAAAAAAAAAAAAA=',
                 'keyId': 0
             }
         },
         'date':
         '2018-06-07T09:13:07.663Z',
         'heartbeatIntervalMillis':
         2000,
         'members': [{
             '_id': 0,
             'configVersion': 1,
             'electionDate': '2018-06-07T09:10:22Z',
             'electionTime': 1528362622.1,
             'health': 1,
             'name': 'some-db-0.some-db.default.svc.cluster.local:27017',
             'optime': {
                 't': 1,
                 'ts': 1528362783.1
             },
             'optimeDate': '2018-06-07T09:13:03Z',
             'self': True,
             'state': 1,
             'stateStr': 'PRIMARY',
             'uptime': 210
         }, {
             '_id': 1,
             'configVersion': 1,
             'health': 1,
             'lastHeartbeat': '2018-06-07T09:13:07.162Z',
             'lastHeartbeatRecv': '2018-06-07T09:13:07.265Z',
             'name': 'some-db-1.some-db.default.svc.cluster.local:27017',
             'optime': {
                 't': 1,
                 'ts': 1528362783.1
             },
             'optimeDate': '2018-06-07T09:13:03Z',
             'optimeDurable': {
                 't': 1,
                 'ts': 1528362783.1
             },
             'optimeDurableDate': '2018-06-07T09:13:03Z',
             'pingMs': 0,
             'state': 2,
             'stateStr': 'SECONDARY',
             'syncingTo':
             'some-db-2.some-db.default.svc.cluster.local:27017',
             'uptime': 178
         }, {
             '_id': 2,
             'configVersion': 1,
             'health': 1,
             'lastHeartbeat': '2018-06-07T09:13:06.564Z',
             'lastHeartbeatRecv': '2018-06-07T09:13:06.760Z',
             'name': 'some-db-2.some-db.default.svc.cluster.local:27017',
             'optime': {
                 't': 1,
                 'ts': 1528362783.1
             },
             'optimeDate': '2018-06-07T09:13:03Z',
             'optimeDurable': {
                 't': 1,
                 'ts': 1528362783.1
             },
             'optimeDurableDate': '2018-06-07T09:13:03Z',
             'pingMs': 6,
             'state': 2,
             'stateStr': 'SECONDARY',
             'syncingTo':
             'some-db-0.some-db.default.svc.cluster.local:27017',
             'uptime': 178
         }],
         'myState':
         1,
         'ok':
         1,
         'operationTime':
         1528362783.1,
         'optimes': {
             'appliedOpTime': {
                 't': 1,
                 'ts': 1528362783.1
             },
             'durableOpTime': {
                 't': 1,
                 'ts': 1528362783.1
             },
             'lastCommittedOpTime': {
                 't': 1,
                 'ts': 1528362783.1
             },
             'readConcernMajorityOpTime': {
                 't': 1,
                 'ts': 1528362783.1
             }
         },
         'set':
         'some-db',
         'term':
         1
     }
     self.assertEqual(expected, response)
 def test_parseMongoResponse_empty(self):
     with self.assertRaises(ValueError) as context:
         MongoResources.parseMongoResponse("")
     self.assertEqual("Cannot parse MongoDB status response: ''",
                      str(context.exception))