def dump_configuration(self, planned_only=False): """ Returns the Magic Castle configuration dictionary of the current cluster. :param planned_only: Set to True to extract configuration exclusively from main.tf.json (runs faster). If set to False, it will attempt to extract the configuration from the terraform state file if available (and otherwise use the main.tf.json file). :return: The configuration dictionary """ if self.__not_found(): raise ClusterNotFoundException try: if (planned_only or self.get_status() in [ ClusterStatusCode.BUILD_RUNNING, ClusterStatusCode.DESTROY_RUNNING ] or not path.exists( self.__get_cluster_path(TERRAFORM_STATE_FILENAME))): self.__configuration = MagicCastleConfiguration.get_from_main_tf_json_file( self.get_hostname(), ) else: self.__configuration = MagicCastleConfiguration.get_from_state_file( self.get_hostname()) return self.__configuration.dump() except FileNotFoundError: return dict()
def test_constructor_no_hieradata_valid(): config = MagicCastleConfiguration({ "cluster_name": "foo-123", "domain": "calculquebec.cloud", "image": "CentOS-7-x64-2019-07", "nb_users": 17, "instances": { "mgmt": { "type": "p4-6gb", "count": 1 }, "login": { "type": "p4-6gb", "count": 1 }, "node": { "type": "p2-3gb", "count": 3 }, }, "storage": { "type": "nfs", "home_size": 50, "project_size": 1, "scratch_size": 1, }, "public_keys": [""], "guest_passwd": '1234\\56789\t "', "os_floating_ips": [], }) assert config.dump() == { "cluster_name": "foo-123", "domain": "calculquebec.cloud", "image": "CentOS-7-x64-2019-07", "nb_users": 17, "instances": { "mgmt": { "type": "p4-6gb", "count": 1 }, "login": { "type": "p4-6gb", "count": 1 }, "node": { "type": "p2-3gb", "count": 3 }, }, "storage": { "type": "nfs", "home_size": 50, "project_size": 1, "scratch_size": 1, }, "public_keys": [""], "hieradata": "", "guest_passwd": '1234\\56789\t "', "os_floating_ips": [], }
def test_get_from_state_file_missing_nodes(): config = MagicCastleConfiguration.get_from_state_file( "missingnodes.sub.example.com") assert config.dump() == { "cluster_name": "missingnodes", "domain": "sub.example.com", "image": "CentOS-7-x64-2019-07", "nb_users": 10, "instances": { "mgmt": { "type": "", "count": 0 }, "login": { "type": "", "count": 0 }, "node": { "type": "", "count": 0 }, }, "storage": { "type": "nfs", "home_size": 100, "project_size": 50, "scratch_size": 50, }, "public_keys": ["ssh-rsa FAKE"], "hieradata": "", "guest_passwd": "password-123", "os_floating_ips": ["100.101.102.103"], }
def test_get_from_state_file_empty(): config = MagicCastleConfiguration.get_from_state_file( "empty-state.calculquebec.cloud") assert config.dump() == { "cluster_name": "empty-state", "domain": "calculquebec.cloud", "image": "", "nb_users": 0, "instances": { "mgmt": { "type": "", "count": 0 }, "login": { "type": "", "count": 0 }, "node": { "type": "", "count": 0 }, }, "storage": { "type": "nfs", "home_size": 0, "project_size": 0, "scratch_size": 0, }, "public_keys": [""], "hieradata": "", "guest_passwd": "", "os_floating_ips": [], }
def test_constructor_invalid_domain(): with pytest.raises(ServerException): MagicCastleConfiguration({ "cluster_name": "foo", "domain": "invalid.cloud", "image": "CentOS-7-x64-2019-07", "nb_users": 17, "instances": { "mgmt": { "type": "p4-6gb", "count": 1 }, "login": { "type": "p4-6gb", "count": 1 }, "node": { "type": "p2-3gb", "count": 3 }, }, "storage": { "type": "nfs", "home_size": 50, "project_size": 1, "scratch_size": 1, }, "public_keys": [""], "hieradata": "", "guest_passwd": '1234\\56789\t "', "os_floating_ips": [], })
def set_configuration(self, configuration: dict): try: self.__configuration = MagicCastleConfiguration.get_from_dict( configuration) self.__hostname = self.__configuration.get_hostname() except ValidationError: raise InvalidUsageException( "The magic castle configuration could not be parsed.")
def test_update_main_tf_json_file(): modified_config = MagicCastleConfiguration.get_from_dict({ "cluster_name": "missingnodes", "domain": "sub.example.com", "image": "CentOS-7-x64-2019-07", "nb_users": 30, "instances": { "mgmt": { "type": "p4-6gb", "count": 1 }, "login": { "type": "p4-6gb", "count": 1 }, "node": { "type": "p2-3gb", "count": 12 }, }, "storage": { "type": "nfs", "home_size": 400, "project_size": 12, "scratch_size": 50, }, "public_keys": ["ssh-rsa FOOBAR"], "hieradata": "", "guest_passwd": "", "os_floating_ips": [], }) modified_config.update_main_tf_json_file() saved_config = MagicCastleConfiguration.get_from_main_tf_json_file( "missingnodes.sub.example.com") assert saved_config.dump() == { "cluster_name": "missingnodes", "domain": "sub.example.com", "image": "CentOS-7-x64-2019-07", "nb_users": 30, "instances": { "mgmt": { "type": "p4-6gb", "count": 1 }, "login": { "type": "p4-6gb", "count": 1 }, "node": { "type": "p2-3gb", "count": 12 }, }, "storage": { "type": "nfs", "home_size": 400, "project_size": 12, "scratch_size": 50, }, "public_keys": ["ssh-rsa FOOBAR"], "hieradata": "", "guest_passwd": "", "os_floating_ips": ["100.101.102.103"], }
def test_get_from_state_file_not_found(): with pytest.raises(FileNotFoundError): MagicCastleConfiguration.get_from_state_file("non-existing")
def test_constructor_none(): config = MagicCastleConfiguration() assert config.dump() == {}
def test_get_from_main_tf_json_file_not_found(): with pytest.raises(FileNotFoundError): MagicCastleConfiguration.get_from_main_tf_json_file("empty") with pytest.raises(FileNotFoundError): MagicCastleConfiguration.get_from_main_tf_json_file("non-existing")
def test_get_from_dict_valid(): config = MagicCastleConfiguration.get_from_dict({ "cluster_name": "foo", "domain": "calculquebec.cloud", "image": "CentOS-7-x64-2019-07", "nb_users": 17, "instances": { "mgmt": { "type": "p4-6gb", "count": 1 }, "login": { "type": "p4-6gb", "count": 1 }, "node": { "type": "p2-3gb", "count": 3 }, }, "storage": { "type": "nfs", "home_size": 50, "project_size": 1, "scratch_size": 1, }, "public_keys": [""], "hieradata": 'profile::base::admin_email: "*****@*****.**"', "guest_passwd": '1234\\56789\t "', "os_floating_ips": [], }) assert config.dump() == { "cluster_name": "foo", "domain": "calculquebec.cloud", "image": "CentOS-7-x64-2019-07", "nb_users": 17, "instances": { "mgmt": { "type": "p4-6gb", "count": 1 }, "login": { "type": "p4-6gb", "count": 1 }, "node": { "type": "p2-3gb", "count": 3 }, }, "storage": { "type": "nfs", "home_size": 50, "project_size": 1, "scratch_size": 1, }, "public_keys": [""], "hieradata": 'profile::base::admin_email: "*****@*****.**"', "guest_passwd": '1234\\56789\t "', "os_floating_ips": [], }
def test_constructor_valid(): config = MagicCastleConfiguration({ "cluster_name": "foo-123", "domain": "calculquebec.cloud", "image": "CentOS-7-x64-2019-07", "nb_users": 17, "instances": { "mgmt": { "type": "p4-6gb", "count": 1 }, "login": { "type": "p4-6gb", "count": 1 }, "node": { "type": "p2-3gb", "count": 3 }, }, "storage": { "type": "nfs", "home_size": 50, "project_size": 1, "scratch_size": 1, }, "public_keys": [""], "hieradata": 'profile::base::admin_email: "*****@*****.**"\n' "jupyterhub::enable_otp_auth: false", "guest_passwd": '1234\\56789\t "', "os_floating_ips": [], }) assert config.dump() == { "cluster_name": "foo-123", "domain": "calculquebec.cloud", "image": "CentOS-7-x64-2019-07", "nb_users": 17, "instances": { "mgmt": { "type": "p4-6gb", "count": 1 }, "login": { "type": "p4-6gb", "count": 1 }, "node": { "type": "p2-3gb", "count": 3 }, }, "storage": { "type": "nfs", "home_size": 50, "project_size": 1, "scratch_size": 1, }, "public_keys": [""], "hieradata": 'profile::base::admin_email: "*****@*****.**"\n' "jupyterhub::enable_otp_auth: false", "guest_passwd": '1234\\56789\t "', "os_floating_ips": [], }
def test_get_file_not_found(): with pytest.raises(FileNotFoundError): MagicCastleConfiguration.get_from_state_file("non-existing") with pytest.raises(FileNotFoundError): MagicCastleConfiguration.get_from_main_tf_json_file( "non-existing", parse_floating_ips_from_state=False)