|
6 | 6 |
|
7 | 7 | from botocore.exceptions import ClientError |
8 | 8 | from django.http.request import HttpRequest |
9 | | -from django.http.response import HttpResponseBase |
10 | 9 | from django.utils.translation import gettext_lazy as _ |
11 | 10 | from rest_framework import serializers |
12 | 11 | from rest_framework.fields import CharField, ChoiceField, IntegerField, ListField |
|
26 | 25 | from sentry.integrations.models.integration import Integration |
27 | 26 | from sentry.integrations.models.organization_integration import OrganizationIntegration |
28 | 27 | from sentry.integrations.pipeline import IntegrationPipeline |
29 | | -from sentry.organizations.services.organization import organization_service |
30 | 28 | from sentry.organizations.services.organization.model import RpcOrganization |
31 | 29 | from sentry.pipeline.types import PipelineStepResult |
32 | | -from sentry.pipeline.views.base import ApiPipelineSteps, PipelineView, render_react_view |
33 | | -from sentry.projects.services.project import project_service |
| 30 | +from sentry.pipeline.views.base import ApiPipelineSteps |
34 | 31 | from sentry.silo.base import control_silo_function |
35 | | -from sentry.users.models.user import User |
36 | | -from sentry.users.services.user.serial import serialize_rpc_user |
37 | 32 | from sentry.utils.concurrent import ContextPropagatingThreadPoolExecutor |
38 | 33 | from sentry.utils.sdk import capture_exception |
39 | 34 |
|
@@ -412,13 +407,8 @@ class AwsLambdaIntegrationProvider(IntegrationProvider): |
412 | 407 | integration_cls = AwsLambdaIntegration |
413 | 408 | features = frozenset([IntegrationFeatures.SERVERLESS]) |
414 | 409 |
|
415 | | - def get_pipeline_views(self) -> list[PipelineView[IntegrationPipeline]]: |
416 | | - return [ |
417 | | - AwsLambdaProjectSelectPipelineView(), |
418 | | - AwsLambdaCloudFormationPipelineView(), |
419 | | - AwsLambdaListFunctionsPipelineView(), |
420 | | - AwsLambdaSetupLayerPipelineView(), |
421 | | - ] |
| 410 | + def get_pipeline_views(self) -> list: |
| 411 | + return [] |
422 | 412 |
|
423 | 413 | def get_pipeline_api_steps(self) -> ApiPipelineSteps[IntegrationPipeline]: |
424 | 414 | return [ |
@@ -475,215 +465,3 @@ def post_install( |
475 | 465 | organization_id=organization.id, integration=integration |
476 | 466 | ): |
477 | 467 | oi.update(config={"default_project_id": default_project_id}) |
478 | | - |
479 | | - |
480 | | -class AwsLambdaProjectSelectPipelineView: |
481 | | - def dispatch(self, request: HttpRequest, pipeline: IntegrationPipeline) -> HttpResponseBase: |
482 | | - # if we have the projectId, go to the next step |
483 | | - if "projectId" in request.GET: |
484 | | - pipeline.bind_state("project_id", request.GET["projectId"]) |
485 | | - return pipeline.next_step() |
486 | | - |
487 | | - assert pipeline.organization is not None |
488 | | - organization = pipeline.organization |
489 | | - projects = organization.projects |
490 | | - |
491 | | - # if only one project, automatically use that |
492 | | - if len(projects) == 1: |
493 | | - pipeline.bind_state("skipped_project_select", True) |
494 | | - pipeline.bind_state("project_id", projects[0].id) |
495 | | - return pipeline.next_step() |
496 | | - |
497 | | - projects = sorted(projects, key=lambda p: p.slug) |
498 | | - serialized_projects = project_service.serialize_many( |
499 | | - organization_id=organization.id, |
500 | | - filter=dict(project_ids=[p.id for p in projects]), |
501 | | - ) |
502 | | - return render_react_view( |
503 | | - request, "awsLambdaProjectSelect", {"projects": serialized_projects} |
504 | | - ) |
505 | | - |
506 | | - |
507 | | -class AwsLambdaCloudFormationPipelineView: |
508 | | - def dispatch(self, request: HttpRequest, pipeline: IntegrationPipeline) -> HttpResponseBase: |
509 | | - curr_step = 0 if pipeline.fetch_state("skipped_project_select") else 1 |
510 | | - |
511 | | - def render_response(error=None): |
512 | | - assert pipeline.organization is not None |
513 | | - serialized_organization = organization_service.serialize_organization( |
514 | | - id=pipeline.organization.id, |
515 | | - as_user=( |
516 | | - serialize_rpc_user(request.user) if isinstance(request.user, User) else None |
517 | | - ), |
518 | | - ) |
519 | | - template_url = options.get("aws-lambda.cloudformation-url") |
520 | | - context = { |
521 | | - "baseCloudformationUrl": "https://console.aws.amazon.com/cloudformation/home#/stacks/create/review", |
522 | | - "templateUrl": template_url, |
523 | | - "stackName": "Sentry-Monitoring-Stack", |
524 | | - "regionList": ALL_AWS_REGIONS, |
525 | | - "accountNumber": pipeline.fetch_state("account_number"), |
526 | | - "region": pipeline.fetch_state("region"), |
527 | | - "error": error, |
528 | | - "initialStepNumber": curr_step, |
529 | | - "organization": serialized_organization, |
530 | | - "awsExternalId": pipeline.fetch_state("aws_external_id"), |
531 | | - } |
532 | | - return render_react_view(request, "awsLambdaCloudformation", context) |
533 | | - |
534 | | - # form submit adds accountNumber to GET parameters |
535 | | - if "accountNumber" in request.GET: |
536 | | - data = request.GET |
537 | | - |
538 | | - # load parameters post request |
539 | | - account_number = data["accountNumber"] |
540 | | - region = data["region"] |
541 | | - aws_external_id = data["awsExternalId"] |
542 | | - |
543 | | - pipeline.bind_state("account_number", account_number) |
544 | | - pipeline.bind_state("region", region) |
545 | | - pipeline.bind_state("aws_external_id", aws_external_id) |
546 | | - |
547 | | - # now validate the arn works |
548 | | - try: |
549 | | - gen_aws_client(account_number, region, aws_external_id) |
550 | | - except ClientError: |
551 | | - return render_response( |
552 | | - _("Please validate the Cloudformation stack was created successfully") |
553 | | - ) |
554 | | - except ConfigurationError: |
555 | | - # if we have a configuration error, we should blow up the pipeline |
556 | | - raise |
557 | | - except Exception as e: |
558 | | - logger.warning( |
559 | | - "AwsLambdaCloudFormationPipelineView.unexpected_error", |
560 | | - extra={"error": str(e)}, |
561 | | - ) |
562 | | - return render_response(_("Unknown error")) |
563 | | - |
564 | | - # if no error, continue |
565 | | - return pipeline.next_step() |
566 | | - |
567 | | - return render_response() |
568 | | - |
569 | | - |
570 | | -class AwsLambdaListFunctionsPipelineView: |
571 | | - def dispatch(self, request: HttpRequest, pipeline: IntegrationPipeline) -> HttpResponseBase: |
572 | | - if request.method == "POST": |
573 | | - raw_data = request.POST |
574 | | - data = {} |
575 | | - for key, val in raw_data.items(): |
576 | | - # form posts have string values for booleans and this form only sends booleans |
577 | | - data[key] = val == "true" |
578 | | - pipeline.bind_state("enabled_lambdas", data) |
579 | | - return pipeline.next_step() |
580 | | - |
581 | | - account_number = pipeline.fetch_state("account_number") |
582 | | - region = pipeline.fetch_state("region") |
583 | | - aws_external_id = pipeline.fetch_state("aws_external_id") |
584 | | - |
585 | | - lambda_client = gen_aws_client(account_number, region, aws_external_id) |
586 | | - |
587 | | - lambda_functions = get_supported_functions(lambda_client) |
588 | | - |
589 | | - curr_step = 2 if pipeline.fetch_state("skipped_project_select") else 3 |
590 | | - |
591 | | - return render_react_view( |
592 | | - request, |
593 | | - "awsLambdaFunctionSelect", |
594 | | - {"lambdaFunctions": lambda_functions, "initialStepNumber": curr_step}, |
595 | | - ) |
596 | | - |
597 | | - |
598 | | -class AwsLambdaSetupLayerPipelineView: |
599 | | - def dispatch(self, request: HttpRequest, pipeline: IntegrationPipeline) -> HttpResponseBase: |
600 | | - if "finish_pipeline" in request.GET: |
601 | | - return pipeline.finish_pipeline() |
602 | | - |
603 | | - assert pipeline.organization is not None |
604 | | - organization = pipeline.organization |
605 | | - |
606 | | - account_number = pipeline.fetch_state("account_number") |
607 | | - region = pipeline.fetch_state("region") |
608 | | - |
609 | | - project_id = pipeline.fetch_state("project_id") |
610 | | - aws_external_id = pipeline.fetch_state("aws_external_id") |
611 | | - enabled_lambdas = pipeline.fetch_state("enabled_lambdas") |
612 | | - assert enabled_lambdas is not None |
613 | | - |
614 | | - sentry_project_dsn = get_dsn_for_project(organization.id, project_id) |
615 | | - |
616 | | - lambda_client = gen_aws_client(account_number, region, aws_external_id) |
617 | | - |
618 | | - lambda_functions = get_supported_functions(lambda_client) |
619 | | - lambda_functions.sort(key=lambda x: x["FunctionName"].lower()) |
620 | | - |
621 | | - def is_lambda_enabled(function): |
622 | | - name = function["FunctionName"] |
623 | | - # check to see if the user wants to enable this function |
624 | | - return enabled_lambdas.get(name) |
625 | | - |
626 | | - lambda_functions = filter(is_lambda_enabled, lambda_functions) |
627 | | - |
628 | | - def _enable_lambda(function): |
629 | | - try: |
630 | | - enable_single_lambda(lambda_client, function, sentry_project_dsn) |
631 | | - return (True, function, None) |
632 | | - except Exception as e: |
633 | | - return (False, function, e) |
634 | | - |
635 | | - failures = [] |
636 | | - success_count = 0 |
637 | | - |
638 | | - with ContextPropagatingThreadPoolExecutor( |
639 | | - max_workers=options.get("aws-lambda.thread-count") |
640 | | - ) as _lambda_setup_thread_pool: |
641 | | - # use threading here to parallelize requests |
642 | | - # no timeout on the thread since the underlying request will time out |
643 | | - # if it takes too long |
644 | | - for success, function, e in _lambda_setup_thread_pool.map( |
645 | | - _enable_lambda, lambda_functions |
646 | | - ): |
647 | | - name = function["FunctionName"] |
648 | | - if success: |
649 | | - success_count += 1 |
650 | | - else: |
651 | | - # need to make sure we catch any error to continue to the next function |
652 | | - err_message: str | _StrPromise = str(e) |
653 | | - is_custom_err, err_message = get_sentry_err_message(err_message) |
654 | | - if not is_custom_err: |
655 | | - capture_exception(e) |
656 | | - err_message = _("Unknown Error") |
657 | | - failures.append({"name": function["FunctionName"], "error": err_message}) |
658 | | - logger.info( |
659 | | - "update_function_configuration.error", |
660 | | - extra={ |
661 | | - "organization_id": organization.id, |
662 | | - "lambda_name": name, |
663 | | - "account_number": account_number, |
664 | | - "region": region, |
665 | | - "error": str(e), |
666 | | - }, |
667 | | - ) |
668 | | - |
669 | | - analytics.record( |
670 | | - IntegrationServerlessSetup( |
671 | | - user_id=request.user.id, |
672 | | - organization_id=organization.id, |
673 | | - integration="aws_lambda", |
674 | | - success_count=success_count, |
675 | | - failure_count=len(failures), |
676 | | - ) |
677 | | - ) |
678 | | - |
679 | | - # if we have failures, show them to the user |
680 | | - # otherwise, finish |
681 | | - |
682 | | - if failures: |
683 | | - return render_react_view( |
684 | | - request, |
685 | | - "awsLambdaFailureDetails", |
686 | | - {"lambdaFunctionFailures": failures, "successCount": success_count}, |
687 | | - ) |
688 | | - else: |
689 | | - return pipeline.finish_pipeline() |
0 commit comments