Пример #1
0
def delete_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.info(f"Starting the {TYPE_NAME} Delete Handler")

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL or "https://api.datadoghq.com",
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = users_api.UsersApi(api_client)
        user_handle = model.Handle
        try:
            api_instance.disable_user(user_handle)
        except ApiException as e:
            LOG.error("Exception when calling UsersApi->disable_user: %s\n" % e)
            return ProgressEvent(status=OperationStatus.FAILED, resourceModel=model, message=e.body)

    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=None,
    )
def delete_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Delete Handler", TYPE_NAME)
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = MonitorsApi(api_client)
        try:
            api_instance.delete_monitor(model.Id)
        except ApiException as e:
            LOG.exception(
                "Exception when calling MonitorsApi->delete_monitor: %s\n", e)
            return ProgressEvent(
                status=OperationStatus.FAILED,
                resourceModel=model,
                message=f"Error deleting monitor: {e}",
                errorCode=http_to_handler_error_code(e.status),
            )

    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=None,
    )
def delete_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    model = request.desiredResourceState

    aws_account = build_aws_account_from_model(model)

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = AWSIntegrationApi(api_client)
        try:
            api_instance.delete_aws_account(aws_account)
        except ApiException as e:
            LOG.error(
                "Exception when calling AWSIntegrationApi->delete_aws_account: %s\n",
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error deleting AWS account: {e}")

    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=None,
    )
Пример #4
0
def update_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.info(f"Starting the {TYPE_NAME} Update Handler")

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL or "https://api.datadoghq.com",
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = users_api.UsersApi(api_client)
        body = User(
            access_role=AccessRole(model.AccessRole),
            email=model.Email,
            disabled=model.Disabled or False,
            name=model.Name,
        )
        try:
            api_instance.update_user(model.Handle, body)
        except ApiException as e:
            LOG.error("Exception when calling UsersApi->update_user: %s\n" % e)
            return ProgressEvent(status=OperationStatus.FAILED, resourceModel=model, message=e.body)

    return read_handler(session, request, callback_context)
Пример #5
0
def read_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    model = request.desiredResourceState
    LOG.info(f"Starting the {TYPE_NAME} Delete Handler")

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL or "https://api.datadoghq.com",
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = users_api.UsersApi(api_client)
        user_handle = model.Handle
        try:
            api_response = api_instance.get_user(user_handle)
        except ApiException as e:
            LOG.error("Exception when calling UsersApi->get_user: %s\n" % e)
            return ProgressEvent(status=OperationStatus.FAILED, resourceModel=model, message=e.body)

    model.AccessRole = api_response.user.access_role.value
    model.Name = api_response.user.name
    model.Disabled = api_response.user.disabled
    model.Verified = api_response.user.verified
    model.Email = api_response.user.email
    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=model,
    )
def update_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    LOG.info(f"Starting the {TYPE_NAME} Update Handler")

    downtime_body = build_downtime_struct(model)

    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = downtimes_api.DowntimesApi(api_client)
        try:
            api_instance.update_downtime(model.Id, downtime_body)
        except ApiException as e:
            LOG.exception(
                "Exception when calling DowntimeApi->update_downtime: %s\n" %
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=e.body,
                                 errorCode=http_to_handler_error_code(
                                     e.status))

    return read_handler(session, request, callback_context)
def delete_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Delete Handler", TYPE_NAME)
    model = request.desiredResourceState

    dashboard_id = model.Id

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = DashboardsApi(api_client)
        try:
            api_instance.delete_dashboard(dashboard_id)
        except ApiException as e:
            LOG.error(
                "Exception when calling DashboardsApi->delete_dashboard: %s\n",
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error deleting dashboard: {e}")

    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=None,
    )
def read_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Read Handler", TYPE_NAME)
    model = request.desiredResourceState

    dashboard_id = model.Id

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = DashboardsApi(api_client)
        try:
            dash = api_instance.get_dashboard(dashboard_id)
            json_dict = ApiClient.sanitize_for_serialization(dash)
            model.DashboardDefinition = json.dumps(json_dict)
        except ApiException as e:
            LOG.error(
                "Exception when calling DashboardsApi->get_dashboard: %s\n", e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error getting dashboard: {e}")
    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=model,
    )
def create_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Create Handler", TYPE_NAME)
    model = request.desiredResourceState

    aws_account = build_aws_account_from_model(model)
    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = AWSIntegrationApi(api_client)
        try:
            api_instance.create_aws_account(aws_account)
        except ApiException as e:
            LOG.error(
                "Exception when calling AWSIntegrationApi->create_aws_account: %s\n",
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error creating AWS account: {e}")

    model.IntegrationID = get_integration_id(model.AccountID, model.RoleName,
                                             model.AccessKeyID)

    return read_handler(session, request, callback_context)
Пример #10
0
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.info(f"Starting the {TYPE_NAME} Create Handler")

    downtime_body = build_downtime_struct(model)

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = downtimes_api.DowntimesApi(api_client)
        try:
            api_resp = api_instance.create_downtime(downtime_body)
            model.Id = api_resp.id
        except ApiException as e:
            LOG.error(
                "Exception when calling DowntimeApi->create_downtime: %s\n" %
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=e.body)

    return read_handler(session, request, callback_context)
Пример #11
0
def update_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Update Handler", TYPE_NAME)
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    try:
        json_payload = json.loads(model.DashboardDefinition)
    except ValueError as e:
        LOG.exception("Exception parsing dashboard payload: %s\n", e)
        return ProgressEvent(
            status=OperationStatus.FAILED,
            resourceModel=model,
            message=f"Error parsing dashboard payload: {e}",
            errorCode=HandlerErrorCode.InternalFailure,
        )

    dashboard_id = model.Id

    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = DashboardsApi(api_client)
        try:
            # Get raw http response with _preload_content False
            api_instance.update_dashboard(dashboard_id,
                                          json_payload,
                                          _check_input_type=False,
                                          _preload_content=False)
        except TypeError as e:
            LOG.exception(
                "Exception when deserializing the Dashboard payload definition: %s\n",
                e)
            return ProgressEvent(
                status=OperationStatus.FAILED,
                resourceModel=model,
                message=f"Error deserializing dashboard: {e}",
                errorCode=HandlerErrorCode.InternalFailure,
            )
        except ApiException as e:
            LOG.exception(
                "Exception when calling DashboardsApi->update_dashboard: %s\n",
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error updating dashboard: {e}",
                                 errorCode=http_to_handler_error_code(
                                     e.status))
    return read_handler(session, request, callback_context)
def create_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Create Handler", TYPE_NAME)
    model = request.desiredResourceState

    try:
        json_payload = json.loads(model.DashboardDefinition)
    except json.JSONDecodeError as e:
        LOG.error("Exception when loading the Dashboard JSON definition: %s\n",
                  e)
        return ProgressEvent(
            status=OperationStatus.FAILED,
            resourceModel=model,
            message=f"Error loading Dashboard JSON definition: {e}")

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = DashboardsApi(api_client)
        try:
            # Call the deserialization function of the python client.
            # It expects the loaded JSON payload, the python client type of the model,
            # some path to the data (not sure what this one does),
            # whether or not the payload is a server payload, so true in our case,
            # whether or not to do type conversion, true in our case too
            # and importantly the api_client configuration, needed to perform the type conversions
            dashboard = validate_and_convert_types(
                json_payload, (Dashboard, ), ["resource_data"],
                True,
                True,
                configuration=api_client.configuration)
            res = api_instance.create_dashboard(dashboard)
            model.Id = res.id
        except TypeError as e:
            LOG.error(
                "Exception when deserializing the Dashboard payload definition: %s\n",
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error deserializing dashboard: {e}")
        except ApiException as e:
            LOG.error(
                "Exception when calling DashboardsApi->create_dashboard: %s\n",
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error creating dashboard: {e}")
    return read_handler(session, request, callback_context)
Пример #13
0
def read_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    model = request.desiredResourceState
    LOG.info(f"Starting the {TYPE_NAME} Read Handler")

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = downtimes_api.DowntimesApi(api_client)
        try:
            api_resp = api_instance.get_downtime(model.Id)
        except ApiException as e:
            LOG.error(
                "Exception when calling DowntimeApi->get_downtime: %s\n" % e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=e.body)

    LOG.info(f"Success retrieving downtime {api_resp}")

    # Add hasattr checks for non-nullable fields to ensure they're available to be set
    # Currently in datadog-api-client-python, accessing fields that don't exist return an AttributeError
    if hasattr(api_resp, 'message'):
        model.Message = api_resp.message
    if hasattr(api_resp, 'monitor_tags'):
        model.MonitorTags = api_resp.monitor_tags
    if hasattr(api_resp, 'scope'):
        model.Scope = api_resp.scope
    if hasattr(api_resp, 'timezone'):
        model.Timezone = api_resp.timezone
    if hasattr(api_resp, 'start'):
        model.Start = api_resp.start

    # Nullable fields, these should be None or set as a value
    if api_resp.end:
        model.End = api_resp.end
    if api_resp.monitor_id:
        model.MonitorId = api_resp.monitor_id

    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=model,
    )
def delete_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration
    LOG.info(f"Starting the {TYPE_NAME} Delete Handler")

    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = downtimes_api.DowntimesApi(api_client)
        # First get the downtime to check if it's disabled (mostly a hack to make a contract_delete_delete test pass)
        try:
            api_resp = api_instance.get_downtime(model.Id)
            if api_resp.disabled:
                # Return a 404 to indicate the downtime was already deleted
                return ProgressEvent(
                    status=OperationStatus.FAILED,
                    resourceModel=None,
                    message="Downtime {model.Id} already disabled",
                    errorCode=HandlerErrorCode.NotFound)
        except ApiException as e:
            # Log error but continue in case of failure to get, this should not prevent the next call to delete
            LOG.exception(
                "Exception when calling DowntimeApi->get_downtime: %s\n" % e)
        try:
            api_instance.cancel_downtime(model.Id)
        except ApiException as e:
            LOG.exception(
                "Exception when calling DowntimeApi->cancel_downtime: %s\n" %
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=e.body,
                                 errorCode=http_to_handler_error_code(
                                     e.status))

    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=None,
    )
Пример #15
0
def read_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Read Handler", TYPE_NAME)
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    dashboard_id = model.Id

    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = DashboardsApi(api_client)
        try:
            # Get raw http response with _preload_content  set to False
            resp = api_instance.get_dashboard(dashboard_id,
                                              _preload_content=False)
            json_dict = json.loads(resp.data)
            model.Url = json_dict["url"]
            for k in [
                    "author_handle", "id", "created_at", "modified_at", "url",
                    "author_name"
            ]:
                try:
                    del json_dict[k]
                except KeyError:
                    pass
            model.DashboardDefinition = json.dumps(json_dict, sort_keys=True)
        except ApiException as e:
            LOG.exception(
                "Exception when calling DashboardsApi->get_dashboard: %s\n", e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error getting dashboard: {e}",
                                 errorCode=http_to_handler_error_code(
                                     e.status))
    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=model,
    )
def read_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    model = request.desiredResourceState

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = AWSIntegrationApi(api_client)
        try:
            aws_account = api_instance.list_aws_accounts(
                account_id=model.AccountID,
                role_name=model.RoleName,
                access_key_id=model.AccessKeyID).accounts[0]
        except ApiException as e:
            LOG.error(
                "Exception when calling AWSIntegrationApi->list_aws_accounts: %s\n",
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error getting AWS account: {e}")
        except IndexError:
            LOG.error(
                f"Account with integration ID '{model.IntegrationID}' not found. "
                f"Was it updated outside of AWS CloudFormation ?")
            return ProgressEvent(
                status=OperationStatus.FAILED,
                resourceModel=model,
                message=
                f"Account with integration ID '{model.IntegrationID}' not found. "
                f"Was it updated outside of AWS CloudFormation ?")

    model.HostTags = aws_account.host_tags
    model.FilterTags = aws_account.filter_tags
    model.AccountSpecificNamespaceRules = aws_account.account_specific_namespace_rules

    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=model,
    )
def create_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Create Handler", TYPE_NAME)
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    aws_account = build_aws_account_from_model(model)
    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = AWSIntegrationApi(api_client)
        try:
            response = api_instance.create_aws_account(aws_account)
        except ApiException as e:
            LOG.exception(
                "Exception when calling AWSIntegrationApi->create_aws_account: %s\n",
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error creating AWS account: {e}",
                                 errorCode=http_to_handler_error_code(
                                     e.status))
    if model.ExternalIDSecretName is not None:
        secret_name = model.ExternalIDSecretName
    else:
        secret_name = DEFAULT_SECRET_NAME
    boto_client = session.client("secretsmanager")
    boto_client.create_secret(
        Description=
        'The external_id associated with your Datadog AWS Integration.',
        Name=secret_name,
        SecretString='{"external_id":"%s"}' % response.external_id,
    )

    model.IntegrationID = get_integration_id(model.AccountID, model.RoleName,
                                             model.AccessKeyID)

    return read_handler(session, request, callback_context)
Пример #18
0
def create_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Create Handler", TYPE_NAME)
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration
    thresholds = build_slo_thresholds_from_model(model)

    slo = ApiSLORequest(name=model.Name,
                        type=ApiSLOType(model.Type),
                        thresholds=thresholds)
    if model.Description is not None:
        slo.description = model.Description
    if model.Groups is not None:
        slo.groups = model.Groups
    if model.MonitorIds is not None:
        slo.monitor_ids = model.MonitorIds
    if model.Query is not None:
        slo.query = ApiSLOQuery(numerator=model.Query.Numerator,
                                denominator=model.Query.Denominator)
    if model.Tags is not None:
        slo.tags = model.Tags

    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = ServiceLevelObjectivesApi(api_client)
        try:
            slo_resp = api_instance.create_slo(slo)
        except ApiException as e:
            LOG.error("Exception when calling SLOApi->create_slo: %s\n", e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error creating slo: {e}",
                                 errorCode=http_to_handler_error_code(
                                     e.status))

    model.Id = slo_resp.data[0].id
    return read_handler(session, request, callback_context)
def update_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Update Handler", TYPE_NAME)
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    monitor = ApiMonitorUpdateRequest()
    monitor.query = model.Query
    monitor.type = ApiMonitorType(model.Type)
    if model.Message is not None:
        monitor.message = model.Message
    if model.Name is not None:
        monitor.name = model.Name
    if model.Tags is not None:
        monitor.tags = model.Tags
    if model.Priority is not None:
        monitor.priority = model.Priority
    options = build_monitor_options_from_model(model)
    if options:
        monitor.options = options

    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = MonitorsApi(api_client)
        try:
            api_instance.update_monitor(model.Id, monitor)
        except ApiException as e:
            LOG.exception(
                "Exception when calling MonitorsApi->update_monitor: %s\n", e)
            return ProgressEvent(
                status=OperationStatus.FAILED,
                resourceModel=model,
                message=f"Error updating monitor: {e}",
                errorCode=http_to_handler_error_code(e.status),
            )

    return read_handler(session, request, callback_context)
def update_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Update Handler", TYPE_NAME)
    model = request.desiredResourceState

    aws_account = build_aws_account_from_model(model)
    if get_integration_id(model.AccountID, model.RoleName,
                          model.AccessKeyID) != model.IntegrationID:
        LOG.error(
            f"Cannot update `account_id`, `role_name` or `access_key_id` using this resource. "
            f"Please delete it and create a new one instead.")
        return ProgressEvent(
            status=OperationStatus.FAILED,
            resourceModel=model,
            message=
            f"Cannot update `account_id`, `role_name` or `access_key_id` using this resource. "
            f"Please delete it and create a new one instead.")
    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = AWSIntegrationApi(api_client)
        try:
            api_instance.update_aws_account(
                aws_account,
                account_id=model.AccountID,
                role_name=model.RoleName,
                access_key_id=model.AccessKeyID,
            )
        except ApiException as e:
            LOG.error(
                "Exception when calling AWSIntegrationApi->update_aws_account: %s\n",
                e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error updating AWS account: {e}")

    return read_handler(session, request, callback_context)
Пример #21
0
def create_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Create Handler", TYPE_NAME)
    model = request.desiredResourceState

    monitor = ApiMonitor()
    monitor.query = model.Query
    monitor.type = ApiMonitorType(model.Type)
    if model.Message is not None:
        monitor.message = model.Message
    if model.Name is not None:
        monitor.name = model.Name
    if model.Tags is not None:
        monitor.tags = model.Tags
    options = build_monitor_options_from_model(model)
    if options:
        monitor.options = options

    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL or "https://api.datadoghq.com",
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = MonitorsApi(api_client)
        try:
            monitor_resp = api_instance.create_monitor(monitor)
        except ApiException as e:
            LOG.error(
                "Exception when calling MonitorsApi->create_monitor: %s\n", e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error creating monitor: {e}")

    model.Id = monitor_resp.id
    return read_handler(session, request, callback_context)
def update_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Update Handler", TYPE_NAME)
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    aws_account = build_aws_account_from_model(model)
    if not model.IntegrationID:
        LOG.error("Cannot update non existent resource")
        return ProgressEvent(
            status=OperationStatus.FAILED,
            resourceModel=model,
            message="Cannot update non existent resource",
            errorCode=HandlerErrorCode.NotFound,
        )
    if get_integration_id(model.AccountID, model.RoleName,
                          model.AccessKeyID) != model.IntegrationID:
        LOG.error(
            "Cannot update `account_id`, `role_name` or `access_key_id` using this resource. "
            "Please delete it and create a new one instead.")
        return ProgressEvent(
            status=OperationStatus.FAILED,
            resourceModel=model,
            message=
            "Cannot update `account_id`, `role_name` or `access_key_id` using this resource. "
            "Please delete it and create a new one instead.",
            errorCode=HandlerErrorCode.NotUpdatable)
    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = AWSIntegrationApi(api_client)
        try:
            kwargs = {}
            if model.AccountID is not None:
                kwargs["account_id"] = model.AccountID
            if model.RoleName is not None:
                kwargs["role_name"] = model.RoleName
            if model.AccessKeyID is not None:
                kwargs["access_key_id"] = model.AccessKeyID
            api_instance.update_aws_account(aws_account, **kwargs)
        except ApiException as e:
            LOG.exception(
                "Exception when calling AWSIntegrationApi->update_aws_account: %s\n",
                e)
            error_code = http_to_handler_error_code(e.status)
            if e.status == 400 and "errors" in e.body and any(
                    "does not exist" in s for s in e.body['errors']):
                error_code = HandlerErrorCode.NotFound
            return ProgressEvent(
                status=OperationStatus.FAILED,
                resourceModel=model,
                message=f"Error updating AWS account: {e}",
                errorCode=error_code,
            )

    return read_handler(session, request, callback_context)
def read_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = AWSIntegrationApi(api_client)
        try:
            if model.IntegrationID is None:
                return ProgressEvent(
                    status=OperationStatus.FAILED,
                    resourceModel=model,
                    message="No IntegrationID set, resource never created",
                    errorCode=HandlerErrorCode.NotFound,
                )
            account_id, role_name, access_key_id = parse_integration_id(
                model.IntegrationID)
            kwargs = {}
            if account_id is not None:
                kwargs["account_id"] = account_id
            if role_name is not None:
                kwargs["role_name"] = role_name
            if access_key_id is not None:
                kwargs["access_key_id"] = access_key_id
            aws_account = api_instance.list_aws_accounts(**kwargs).accounts[0]
        except ApiException as e:
            LOG.exception(
                "Exception when calling AWSIntegrationApi->list_aws_accounts: %s\n",
                e)
            error_code = http_to_handler_error_code(e.status)
            if e.status == 400 and "errors" in e.body and any(
                    "does not exist" in s for s in e.body['errors']):
                error_code = HandlerErrorCode.NotFound
            return ProgressEvent(
                status=OperationStatus.FAILED,
                resourceModel=model,
                message=f"Error getting AWS account: {e}",
                errorCode=error_code,
            )
        except IndexError:
            LOG.error(
                f"Account with integration ID '{model.IntegrationID}' not found. "
                f"Was it updated outside of AWS CloudFormation ?")
            return ProgressEvent(
                status=OperationStatus.FAILED,
                resourceModel=model,
                message=
                f"Account with integration ID '{model.IntegrationID}' not found. "
                f"Was it updated outside of AWS CloudFormation ?",
                errorCode=HandlerErrorCode.NotFound,
            )

    model.HostTags = aws_account.host_tags
    model.FilterTags = aws_account.filter_tags
    model.AccountSpecificNamespaceRules = aws_account.account_specific_namespace_rules

    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=model,
    )
Пример #24
0
def read_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Read Handler", TYPE_NAME)
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    with v1_client(
            type_configuration.DatadogCredentials.ApiKey,
            type_configuration.DatadogCredentials.ApplicationKey,
            type_configuration.DatadogCredentials.ApiURL,
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = ServiceLevelObjectivesApi(api_client)
        slo_id = model.Id
        if slo_id is None:
            return ProgressEvent(
                status=OperationStatus.FAILED,
                resourceModel=model,
                message="Error getting SLO: SLO does not exist",
                errorCode=HandlerErrorCode.NotFound,
            )
        try:
            slo = api_instance.get_slo(slo_id)
        except ApiException as e:
            LOG.error("Exception when calling SLOApi->get_slo: %s\n", e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error getting SLO: {e}",
                                 errorCode=http_to_handler_error_code(
                                     e.status))
    model.Created = slo.data.created_at
    model.Modified = slo.data.modified_at
    model.Description = slo.data.description
    model.Name = slo.data.name
    model.Tags = slo.data.tags
    model.Type = slo.data.type.value
    if slo.data.creator:
        model.Creator = Creator(Name=slo.data.creator.name,
                                Email=slo.data.creator.email,
                                Handle=slo.data.creator.handle)

    if slo.data.type.value == "monitor":
        if hasattr(slo.data, 'groups'):
            model.Groups = slo.data.groups
        model.MonitorIds = slo.data.monitor_ids
    elif slo.data.type.value == "metric":
        model.Query = Query(Denominator=slo.data.query.denominator,
                            Numerator=slo.data.query.numerator)
    thresholds = []
    for th in slo.data.thresholds:
        thresholds.append(
            Threshold(Target=th.target if hasattr(th, "target") else None,
                      TargetDisplay=th.target_display if hasattr(
                          th, "target_display") else None,
                      Timeframe=th.timeframe.value
                      if hasattr(th, "timeframe") else None,
                      Warning=th.warning if hasattr(th, "warning") else None,
                      WarningDisplay=th.warning_display if hasattr(
                          th, "warning_display") else None))
    model.Thresholds = thresholds

    model.Id = slo.data.id

    return ProgressEvent(status=OperationStatus.SUCCESS, resourceModel=model)
Пример #25
0
def read_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    LOG.info("Starting %s Read Handler", TYPE_NAME)
    model = request.desiredResourceState
    with v1_client(
            model.DatadogCredentials.ApiKey,
            model.DatadogCredentials.ApplicationKey,
            model.DatadogCredentials.ApiURL or "https://api.datadoghq.com",
            TELEMETRY_TYPE_NAME,
            __version__,
    ) as api_client:
        api_instance = MonitorsApi(api_client)
        monitor_id = model.Id
        try:
            monitor = api_instance.get_monitor(monitor_id)
        except ApiException as e:
            LOG.error("Exception when calling MonitorsApi->get_monitor: %s\n",
                      e)
            return ProgressEvent(status=OperationStatus.FAILED,
                                 resourceModel=model,
                                 message=f"Error getting monitor: {e}")

    model.Created = monitor.created.isoformat()
    model.Modified = monitor.modified.isoformat()
    model.Message = monitor.message
    model.Name = monitor.name
    model.Tags = monitor.tags
    model.Query = monitor.query
    model.Multi = monitor.multi
    if monitor.deleted:
        model.Deleted = monitor.deleted.isoformat()
    if not ((model.Type == "query alert"
             and monitor.type.value == "metric alert") or
            (model.Type == "metric alert"
             and monitor.type.value == "query alert")):
        # metric alert and query alert are interchangeable, so don't update from one to the other
        model.Type = monitor.type.value
    if monitor.creator:
        model.Creator = Creator(Name=monitor.creator.name,
                                Email=monitor.creator.email,
                                Handle=monitor.creator.handle)

    # Add hasattr checks for options since not all of them are applicable to all monitor types, so some attributes
    # might not always be present
    options = monitor.options if hasattr(monitor, "options") else None
    if options:
        model.Options = MonitorOptions(
            EnableLogsSample=options.enable_logs_sample if hasattr(
                options, "enable_logs_sample") else None,
            EscalationMessage=options.escalation_message if hasattr(
                options, "escalation_message") else None,
            EvaluationDelay=options.evaluation_delay if hasattr(
                options, "evaluation_delay") else None,
            IncludeTags=options.include_tags if hasattr(
                options, "include_tags") else None,
            Locked=options.locked if hasattr(options, "locked") else None,
            MinLocationFailed=options.min_location_failed if hasattr(
                options, "min_location_failed") else None,
            NewHostDelay=options.new_host_delay if hasattr(
                options, "new_host_delay") else None,
            NoDataTimeframe=options.no_data_timeframe if hasattr(
                options, "no_data_timeframe") else None,
            NotifyAudit=options.notify_audit if hasattr(
                options, "notify_audit") else None,
            NotifyNoData=options.notify_no_data if hasattr(
                options, "notify_no_data") else None,
            RenotifyInterval=options.renotify_interval if hasattr(
                options, "renotify_interval") else None,
            RequireFullWindow=options.require_full_window if hasattr(
                options, "require_full_window") else None,
            SyntheticsCheckID=options.synthetics_check_id if hasattr(
                options, "synthetics_check_id") else None,
            Thresholds=None,
            ThresholdWindows=None,
            TimeoutH=options.timeout_h
            if hasattr(options, "timeout_h") else None,
        )
        thresholds = options.thresholds if hasattr(options,
                                                   "thresholds") else None
        if thresholds:
            model.Options.Thresholds = MonitorThresholds(
                Critical=thresholds.critical if hasattr(
                    thresholds, "critical") else None,
                CriticalRecovery=thresholds.critical_recovery if hasattr(
                    thresholds, "critical_recovery") else None,
                Warning=thresholds.warning
                if hasattr(thresholds, "warning") else None,
                WarningRecovery=thresholds.warning_recovery if hasattr(
                    thresholds, "warning_recovery") else None,
                OK=thresholds.ok if hasattr(thresholds, "ok") else None,
            )
        tw = options.threshold_windows if hasattr(
            options, "threshold_windows") else None
        if tw:
            model.Options.ThresholdWindows = MonitorThresholdWindows(
                TriggerWindow=tw.trigger_window if hasattr(
                    tw, "trigger_window") else None,
                RecoveryWindow=tw.recovery_window if hasattr(
                    tw, "recovery_window") else None,
            )
    model.Id = monitor.id

    return ProgressEvent(
        status=OperationStatus.SUCCESS,
        resourceModel=model,
    )
def delete_handler(
    session: Optional[SessionProxy],
    request: ResourceHandlerRequest,
    callback_context: MutableMapping[str, Any],
) -> ProgressEvent:
    model = request.desiredResourceState
    type_configuration = request.typeConfiguration

    if model.ExternalIDSecretName is not None:
        secret_name = model.ExternalIDSecretName
    else:
        secret_name = DEFAULT_SECRET_NAME
    boto_client = session.client("secretsmanager")
    callback_count = callback_context.get("callback_count", 0)

    if 0 < callback_count <= MAX_DELETE_SECRET_RETRIES:
        LOG.info(f"Checking deletion of secret {secret_name}")
        try:
            boto_client.describe_secret(SecretId=secret_name)
        except boto_client.exceptions.ResourceNotFoundException:
            return ProgressEvent(
                status=OperationStatus.SUCCESS,
                resourceModel=None,
            )
    elif callback_count > MAX_DELETE_SECRET_RETRIES:
        return ProgressEvent(
            status=OperationStatus.FAILED,
            message=
            f"Error deleting AWS Account: failed to delete secret {secret_name}"
        )
    else:
        kwargs = {}
        if model.AccountID is not None:
            kwargs["account_id"] = model.AccountID
        if model.RoleName is not None:
            kwargs["role_name"] = model.RoleName
        if model.AccessKeyID is not None:
            kwargs["access_key_id"] = model.AccessKeyID
        delete_request = AWSAccountDeleteRequest(**kwargs)

        with v1_client(
                type_configuration.DatadogCredentials.ApiKey,
                type_configuration.DatadogCredentials.ApplicationKey,
                type_configuration.DatadogCredentials.ApiURL,
                TELEMETRY_TYPE_NAME,
                __version__,
        ) as api_client:
            api_instance = AWSIntegrationApi(api_client)
            try:
                api_instance.delete_aws_account(delete_request)
            except ApiException as e:
                LOG.exception(
                    "Exception when calling AWSIntegrationApi->delete_aws_account: %s\n",
                    e)
                error_code = http_to_handler_error_code(e.status)
                if e.status == 400 and "errors" in e.body and any(
                        "does not exist" in s for s in e.body['errors']):
                    error_code = HandlerErrorCode.NotFound
                return ProgressEvent(
                    status=OperationStatus.FAILED,
                    resourceModel=model,
                    message=f"Error deleting AWS account: {e}",
                    errorCode=error_code)

        boto_client.delete_secret(
            SecretId=secret_name,
            ForceDeleteWithoutRecovery=True,
        )

    return ProgressEvent(
        status=OperationStatus.IN_PROGRESS,
        resourceModel=model,
        callbackContext={"callback_count": callback_count + 1},
        callbackDelaySeconds=DELETE_SECRET_CALLBACK_INTERVAL,
    )