def create_handler( session: Optional[SessionProxy], request: ResourceHandlerRequest, callback_context: MutableMapping[str, Any], ) -> ProgressEvent: model = request.desiredResourceState progress: ProgressEvent = ProgressEvent( status=OperationStatus.IN_PROGRESS, resourceModel=model, ) if callback_context.get('pending'): return read_handler(session, request, callback_context) try: client = session.client("transcribe") if model.Phrases is not None: client.create_vocabulary( VocabularyName=model.VocabularyName, LanguageCode=model.LanguageCode, Phrases=model.Phrases ) else: client.create_vocabulary( VocabularyName=model.VocabularyName, LanguageCode=model.LanguageCode, VocabularyFileUri=model.VocabularyFileUri ) except client.exceptions.ConflictException as e: raise exceptions.AlreadyExists(type_name=TYPE_NAME, identifier=model.VocabularyName) except Exception as e: raise exceptions.InternalFailure(f"{e}") return read_handler(session, request, callback_context)
def create_handler( session: Optional[SessionProxy], request: ResourceHandlerRequest, callback_context: MutableMapping[str, Any], # pylint: disable=unused-argument ) -> ProgressEvent: """This function is triggered by the CloudFormation CREATE event and will set the StepConcurrency level from the default of 1 to the new provided value within the up to the max of 256. It will also add a tag to the cluster in order to keep track of the resource. Attributes: session (Optional[SessionProxy]): The session proxy for connecting to the needed AWS API client cluster_id (str): The unique ID of the cluster to get details from callback_context (MutableMapping[str, Any]): Use to store any state between re-invocation via IN_PROGRESS Returns: ProgressEvent: An event with the status of the action """ LOG.info("Create Handler") model = request.desiredResourceState progress: ProgressEvent = ProgressEvent( status=OperationStatus.IN_PROGRESS, resourceModel=model, ) model.UID = "cluster:" + model.ClusterId model.StepConcurrencyLevel = int(model.StepConcurrencyLevel) uid = get_uid(session, model.ClusterId) LOG.info("UID: %s", uid) if uid == model.UID: raise exceptions.AlreadyExists(TYPE_NAME, model.ClusterId) if model.StepConcurrencyLevel < 1 or model.StepConcurrencyLevel > 256: raise exceptions.InvalidRequest( f"Step Concurency Level must be between 1 and 256, \ {model.StepConcurrencyLevel} was given.") try: client = session.client('emr') LOG.info("Setting concurrency to %s for cluster %s", model.StepConcurrencyLevel, model.ClusterId) response = client.modify_cluster(ClusterId=model.ClusterId, StepConcurrencyLevel=int( model.StepConcurrencyLevel)) LOG.info("RESPONSE TO SET CONCURRENCY:") LOG.info(response) LOG.info("Setting UID tag to %s", model.ClusterId) tag_response = client.add_tags(ResourceId=model.ClusterId, Tags=[{ "Key": "StepConcurrencyUID", "Value": model.UID }]) LOG.info("RESPONSE TO ADD TAGS:") LOG.info(tag_response) progress.status = OperationStatus.SUCCESS except Exception as unexpected_exception: LOG.error(str(unexpected_exception)) raise exceptions.InternalFailure( f"Failed Create: {str(unexpected_exception)}") return progress
def _validate_inline_label_for_create(afd_client, label): if label.Name is None: raise exceptions.InvalidRequest( "Error occurred: inline labels must include Name!") get_labels_worked, _ = validation_helpers.check_if_get_labels_succeeds( afd_client, label.Name) if get_labels_worked: raise exceptions.AlreadyExists("label", label.Name) common_helpers.put_inline_label(afd_client, label)
def _validate_inline_entity_type_for_create(afd_client, entity_type): if entity_type.Name is None: raise exceptions.InvalidRequest( "Error occurred: inline entity types must include Name!") get_entity_types_worked, _ = validation_helpers.check_if_get_entity_types_succeeds( afd_client, entity_type.Name) if get_entity_types_worked: raise exceptions.AlreadyExists("entity_type", entity_type.Name) common_helpers.put_inline_entity_type(afd_client, entity_type)
def _validate_inline_event_variable_for_create(afd_client, event_variable): if event_variable.Name is None: raise exceptions.InvalidRequest( "Error occurred: inline event variables must include Name!") get_variables_worked, _ = validation_helpers.check_if_get_variables_succeeds( afd_client, event_variable.Name) if get_variables_worked: raise exceptions.AlreadyExists("event_variable", event_variable.Name) common_helpers.create_inline_event_variable( frauddetector_client=afd_client, event_variable=event_variable)
def execute_create_detector_handler_work(session: SessionProxy, model: models.ResourceModel, progress: ProgressEvent): afd_client = client_helpers.get_afd_client(session) # For contract_create_duplicate, we need to fail if the resource already exists get_detectors_works, _ = validation_helpers.check_if_get_detectors_succeeds( afd_client, model.DetectorId) if get_detectors_works: raise exceptions.AlreadyExists("detector", model.DetectorId) # For contract_invalid_create, fail if any read-only properties are present if model.Arn is not None or model.CreatedTime is not None or model.LastUpdatedTime is not None: raise exceptions.InvalidRequest( "Error occurred: cannot create read-only properties.") # Validate existence of referenced resources, validate and create inline resources (except for Rules, Detector, DV) # Also check existence of external models # TODO: split out creation from validation create_worker_helpers.validate_dependencies_for_detector_create( afd_client, model) # Create Detector, Rules, Detector Version ID model_helpers.put_detector_for_model(afd_client, model) rule_dicts = create_worker_helpers.create_rules_for_detector_resource( afd_client, model) detector_version_response = create_worker_helpers.create_detector_version_for_detector_resource( afd_client, model, rule_dicts) # The DV will be created as draft by default, so if the desired status is not draft, update DV status if model.DetectorVersionStatus != DRAFT_STATUS: api_helpers.call_update_detector_version_status( frauddetector_client=afd_client, detector_id=model.DetectorId, detector_version_id=detector_version_response.get( "detectorVersionId", "1"), # version here should be 1 status=model.DetectorVersionStatus, ) # after satisfying all contract tests and AFD requirements, get the resulting model model = read_worker_helpers.validate_detector_exists_and_return_detector_resource_model( afd_client, model) progress.resourceModel = model progress.status = OperationStatus.SUCCESS LOG.info(f"Returning Progress with status: {progress.status}") return progress
def execute_create_label_handler_work(session, model, progress): afd_client = client_helpers.get_afd_client(session) # For contract_create_duplicate, we need to fail if resource already exists get_labels_works, _ = validation_helpers.check_if_get_labels_succeeds(afd_client, model.Name) if get_labels_works: raise exceptions.AlreadyExists("label", model.Name) # For contract_invalid_create, fail if any read-only properties are present if model.Arn is not None or model.CreatedTime is not None or model.LastUpdatedTime is not None: raise exceptions.InvalidRequest("Error occurred: cannot create read-only properties.") # API does not handle 'None' property gracefully if model.Tags is None: del model.Tags # after satisfying contract call put label return common_helpers.put_label_and_return_progress(afd_client, model, progress)
def execute_create_event_type_handler_work(session, model, progress): afd_client = client_helpers.get_afd_client(session) # For contract_create_duplicate, we need to fail if the resource already exists get_event_type_works, _ = validation_helpers.check_if_get_event_types_succeeds( afd_client, model.Name) if get_event_type_works: raise exceptions.AlreadyExists("event_type", model.Name) # For contract_invalid_create, fail if any read-only properties are present if model.Arn is not None or model.CreatedTime is not None or model.LastUpdatedTime is not None: raise exceptions.InvalidRequest( "Error occurred: cannot create read-only properties.") # Validate existence of referenced resources, validate and create inline resources create_worker_helpers.validate_dependencies_for_create(afd_client, model) # after satisfying contract call put event_type return common_helpers.put_event_type_and_return_progress( afd_client, model, progress)
def create_handler( session: Optional[SessionProxy], request: ResourceHandlerRequest, callback_context: MutableMapping[str, Any], ) -> ProgressEvent: model = request.desiredResourceState progress: ProgressEvent = ProgressEvent( status=OperationStatus.IN_PROGRESS, resourceModel=model, ) # TODO: put code here if model.Fingerprint: progress.status = OperationStatus.FAILED progress.errorCode = HandlerErrorCode.InvalidRequest progress.message = "Fingerprint is read-only - should not be specified in a request" progress.resourceModel.PublicKey = None return progress # Example: try: if isinstance(session, SessionProxy): ec2 = session.client('ec2') try: response = ec2.import_key_pair( KeyName=model.KeyName, PublicKeyMaterial=model.PublicKey) except ClientError as e: if e.response.get( "Error", {}).get("Code") == "InvalidKeyPair.Duplicate": raise exceptions.AlreadyExists(TYPE_NAME, model.KeyName) else: raise model.Fingerprint = response['KeyFingerprint'] model.PublicKey = None progress.status = OperationStatus.SUCCESS return progress except TypeError as e: # exceptions module lets CloudFormation know the type of failure that occurred raise exceptions.InternalFailure(f"was not expecting type {e}") # this can also be done by returning a failed progress event # return ProgressEvent.failed(HandlerErrorCode.InternalFailure, f"was not expecting type {e}") return progress
def create_handler( session: Optional[SessionProxy], request: ResourceHandlerRequest, callback_context: MutableMapping[str, Any], ) -> ProgressEvent: model = request.desiredResourceState progress: ProgressEvent = ProgressEvent( status=OperationStatus.IN_PROGRESS, resourceModel=model, ) LOG.debug(f"Create invoke \n\n{request.__dict__}\n\n{callback_context}") physical_resource_id, manifest_file, manifest_dict = handler_init( model, session, request.logicalResourceIdentifier, request.clientRequestToken ) model.CfnId = encode_id( request.clientRequestToken, model.ClusterName, model.Namespace, manifest_dict["kind"], ) if not callback_context: LOG.debug("1st invoke") progress.callbackDelaySeconds = 1 progress.callbackContext = {"init": "complete"} return progress if "stabilizing" in callback_context: if ( callback_context["stabilizing"].startswith("/apis/batch") and "cronjobs" not in callback_context["stabilizing"] ): if stabilize_job( model.Namespace, callback_context["name"], model.ClusterName, session ): progress.status = OperationStatus.SUCCESS progress.callbackContext = callback_context progress.callbackDelaySeconds = 30 LOG.debug(f"stabilizing: {progress.__dict__}") return progress try: outp = run_command( "kubectl create --save-config -o json -f %s -n %s" % (manifest_file, model.Namespace), model.ClusterName, session, ) build_model(json.loads(outp), model) except Exception as e: if "Error from server (AlreadyExists)" not in str(e): raise LOG.debug("checking whether this is a duplicate request....") if not get_model(model, session): raise exceptions.AlreadyExists(TYPE_NAME, model.CfnId) if model.SelfLink.startswith("/apis/batch") and "cronjobs" not in model.SelfLink: callback_context["stabilizing"] = model.SelfLink callback_context["name"] = model.Name progress.callbackContext = callback_context progress.callbackDelaySeconds = 30 LOG.debug(f"need to stabilize: {progress.__dict__}") return progress progress.status = OperationStatus.SUCCESS LOG.debug(f"success {progress.__dict__}") return progress