def rde_exists(rde_name, logger=NULL_LOGGER): try: cloudapi_client: CloudApiClient = \ pyvcloud_utils.get_cloudapi_client_from_vcd_client( CLIENT, logger_debug=logger, logger_wire=SERVER_CLOUDAPI_WIRE_LOGGER) # To avoid cyclic import from container_service_extension.rde.common.entity_service import \ DefEntityService entity_svc = DefEntityService(cloudapi_client) rde_version = rde_utils.get_runtime_rde_version_by_vcd_api_version( CLIENT.get_api_version()) entity = \ entity_svc.get_native_rde_by_name_and_rde_version( rde_name, rde_version) return bool(entity) except Exception as e: logger.warning(f"Exception occured when checking if rde exists: {e}") return False
def delete_rde(cluster_name, logger=NULL_LOGGER): """Delete defined entity with the given name. NOTE: RDE names are not unique. This function deletes all occurances """ try: cloudapi_client: CloudApiClient = \ pyvcloud_utils.get_cloudapi_client_from_vcd_client( CLIENT, logger_debug=logger, logger_wire=SERVER_CLOUDAPI_WIRE_LOGGER) # noqa: E501 from container_service_extension.rde.common.entity_service import DefEntityService # noqa: E501 entity_svc = DefEntityService(cloudapi_client) for cluster_rde in \ entity_svc.list_all_native_rde_by_name_and_rde_version( cluster_name, rde_utils.get_runtime_rde_version_by_vcd_api_version(CLIENT.get_api_version())): # noqa: E501 entity_svc.resolve_entity(cluster_rde.id, cluster_rde.entityType) entity_svc.delete_entity(cluster_rde.id) except cse_exceptions.DefEntityServiceError as e: PYTEST_LOGGER.error(f"Failed to delete RDE: {e}") pass
def validate(self, cloudapi_client: CloudApiClient, entity_id: str = None, entity: dict = None, operation: BehaviorOperation = None) -> bool: # noqa: E501 """Validate the input request. This method performs 1. Basic validation of the entity by simply casting the input entity dict to the model class dictated by the api_version specified in the request. This is usually performed for the "create" operation. 2. Operation (create, update, delete) specific validation. - create: "entity" is the only required parameter. - update: both "entity" and "entity_id" are required parameters. - delete: "entity_id" is the only required parameter. - kubeconfig: "entity_id" is the only required parameter. :param cloudapi_client: cloud api client :param dict entity: dict form of the native entity to be validated :param entity_id: entity id to be validated :param BehaviorOperation operation: CSE operation key :return: is validation successful or failure :rtype: bool """ if not entity_id and not entity: raise ValueError( 'Either entity_id or entity is required to validate.' ) # noqa: E501 entity_svc = DefEntityService(cloudapi_client=cloudapi_client) api_version: str = cloudapi_client.get_api_version() rde_version_introduced_at_api_version: str = rde_utils.get_rde_version_introduced_at_api_version( api_version) # noqa: E501 # TODO Reject the request if payload_version does not match with # either rde_in_use (or) rde_version_introduced_at_api_version # Cast the entity to the model class based on the user-specified # api_version. This can be considered as a basic request validation. # Any operation specific validation is handled further down NativeEntityClass: AbstractNativeEntity = rde_factory. \ get_rde_model(rde_version_introduced_at_api_version) input_entity = None if entity: try: input_entity: AbstractNativeEntity = NativeEntityClass.from_dict( entity) # noqa: E501 except Exception as err: msg = f"Failed to parse request body: {err}" raise BadRequestError(msg) # Return True if the operation is not specified. if not operation: return True # TODO: validators for rest of the CSE operations in V36 will be # implemented as and when v36/def_cluster_handler.py get other handler # functions if operation == BehaviorOperation.UPDATE_CLUSTER: if not entity_id or not entity: raise ValueError( 'Both entity_id and entity are required to validate the Update operation.' ) # noqa: E501 current_entity: AbstractNativeEntity = entity_svc.get_entity( entity_id).entity # noqa: E501 input_entity_spec: rde_2_0_0.ClusterSpec = input_entity.spec current_entity_status: rde_2_0_0.Status = current_entity.status current_entity_spec = \ rde_utils.construct_cluster_spec_from_entity_status( current_entity_status, rde_constants.RDEVersion.RDE_2_0_0.value) # noqa: E501 return validate_cluster_update_request_and_check_cluster_upgrade( input_entity_spec, current_entity_spec) # TODO check the reason why there was an unreachable raise statement raise NotImplementedError(f"Validator for {operation.name} not found")
def validate( self, cloudapi_client: CloudApiClient, sysadmin_client: Client, entity_id: str = None, entity: dict = None, operation: BehaviorOperation = BehaviorOperation.CREATE_CLUSTER, **kwargs) -> bool: """Validate the input request. This method performs 1. Basic validation of the entity by simply casting the input entity dict to the model class dictated by the api_version specified in the request. This is usually performed for the "create" operation. 2. Operation (create, update, delete) specific validation. - create: "entity" is the only required parameter. - update: both "entity" and "entity_id" are required parameters. - delete: "entity_id" is the only required parameter. - kubeconfig: "entity_id" is the only required parameter. :param cloudapi_client: cloud api client :param sysadmin_client: :param dict entity: dict form of the native entity to be validated :param entity_id: entity id to be validated :param BehaviorOperation operation: CSE operation key :return: is validation successful or failure :rtype: bool """ is_tkgm_cluster = kwargs.get('is_tkgm_cluster', False) if not entity_id and not entity: raise ValueError( 'Either entity_id or entity is required to validate.' ) # noqa: E501 entity_svc = DefEntityService(cloudapi_client=cloudapi_client) api_version: str = cloudapi_client.get_api_version() rde_version_introduced_at_api_version: str = rde_utils.get_rde_version_introduced_at_api_version( api_version) # noqa: E501 # TODO Reject the request if payload_version does not match with # either rde_in_use (or) rde_version_introduced_at_api_version # Cast the entity to the model class based on the user-specified # api_version. This can be considered as a basic request validation. # Any operation specific validation is handled further down native_entity_class: AbstractNativeEntity = rde_factory. \ get_rde_model(rde_version_introduced_at_api_version) input_entity = None if entity: try: input_entity: AbstractNativeEntity = native_entity_class.from_dict( entity) # noqa: E501 except Exception as err: msg = f"Failed to parse request body: {err}" raise BadRequestError(msg) # Need to ensure that sizing class along with cpu/memory is not # present in the request if isinstance(input_entity, rde_2_1_0.NativeEntity): # cpu and mem are properties of only rde 2.0.0 bad_request_msg = "" if input_entity.spec.topology.workers.sizing_class and \ (input_entity.spec.topology.workers.cpu or input_entity.spec.topology.workers.memory): # noqa: E501 bad_request_msg = "Cannot specify both sizing class and cpu/memory for Workers nodes." # noqa: E501 if input_entity.spec.topology.control_plane.sizing_class and ( input_entity.spec.topology.control_plane.cpu or input_entity.spec.topology.control_plane.memory ): # noqa: E501 bad_request_msg = "Cannot specify both sizing class and cpu/memory for Control Plane nodes." # noqa: E501 if bad_request_msg: raise BadRequestError(bad_request_msg) # Return True if the operation is not specified. if operation == BehaviorOperation.CREATE_CLUSTER: return True # TODO: validators for rest of the CSE operations in V36 will be # implemented as and when v36/def_cluster_handler.py get other handler # functions if operation == BehaviorOperation.UPDATE_CLUSTER: if not entity_id or not entity: raise ValueError( 'Both entity_id and entity are required to validate the Update operation.' ) # noqa: E501 current_entity: AbstractNativeEntity = entity_svc.get_entity( entity_id).entity # noqa: E501 input_entity_spec: rde_2_1_0.ClusterSpec = input_entity.spec current_entity_status: rde_2_1_0.Status = current_entity.status is_tkgm_with_default_sizing_in_control_plane = False is_tkgm_with_default_sizing_in_workers = False if is_tkgm_cluster: # NOTE: Since for TKGm cluster, if cluster is created without # a sizing class, default sizing class is assigned by VCD, # If we find the default sizing policy in the status section, # validate cpu/memory and sizing policy. # Also note that at this point in code, we are sure that only # one of sizing class or cpu/mem will be associated with # control plane and workers. vdc: VDC = get_vdc( sysadmin_client, vdc_name=current_entity_status.cloud_properties. virtual_data_center_name, # noqa: E501 org_name=current_entity_status.cloud_properties.org_name) vdc_resource = vdc.get_resource_admin() default_cp_name = vdc_resource.DefaultComputePolicy.get('name') control_plane_sizing_class = current_entity_status.nodes.control_plane.sizing_class # noqa: E501 is_tkgm_with_default_sizing_in_control_plane = \ (control_plane_sizing_class == default_cp_name) is_tkgm_with_default_sizing_in_workers = \ (len(current_entity_status.nodes.workers) > 0 and current_entity_status.nodes.workers[0].sizing_class == default_cp_name) # noqa: E501 current_entity_spec = \ rde_utils.construct_cluster_spec_from_entity_status( current_entity_status, rde_constants.RDEVersion.RDE_2_1_0.value, is_tkgm_with_default_sizing_in_control_plane=is_tkgm_with_default_sizing_in_control_plane, # noqa: E501 is_tkgm_with_default_sizing_in_workers=is_tkgm_with_default_sizing_in_workers) # noqa: E501 return validate_cluster_update_request_and_check_cluster_upgrade( input_entity_spec, current_entity_spec, is_tkgm_cluster) # TODO check the reason why there was an unreachable raise statement raise NotImplementedError(f"Validator for {operation.name} not found")