Skip to content

Commit 6efda30

Browse files
committed
ref(aws-lambda): Remove legacy pipeline views
These are no longer needed now that the integration setup is fully API driven. Refs [VDY-80: Remove legacy AWS Lambda integration setup views](https://linear.app/getsentry/issue/VDY-80/remove-legacy-aws-lambda-integration-setup-views)
1 parent 1aa6667 commit 6efda30

File tree

2 files changed

+5
-749
lines changed

2 files changed

+5
-749
lines changed

src/sentry/integrations/aws_lambda/integration.py

Lines changed: 3 additions & 225 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
from botocore.exceptions import ClientError
88
from django.http.request import HttpRequest
9-
from django.http.response import HttpResponseBase
109
from django.utils.translation import gettext_lazy as _
1110
from rest_framework import serializers
1211
from rest_framework.fields import CharField, ChoiceField, IntegerField, ListField
@@ -26,14 +25,10 @@
2625
from sentry.integrations.models.integration import Integration
2726
from sentry.integrations.models.organization_integration import OrganizationIntegration
2827
from sentry.integrations.pipeline import IntegrationPipeline
29-
from sentry.organizations.services.organization import organization_service
3028
from sentry.organizations.services.organization.model import RpcOrganization
3129
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
3431
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
3732
from sentry.utils.concurrent import ContextPropagatingThreadPoolExecutor
3833
from sentry.utils.sdk import capture_exception
3934

@@ -412,13 +407,8 @@ class AwsLambdaIntegrationProvider(IntegrationProvider):
412407
integration_cls = AwsLambdaIntegration
413408
features = frozenset([IntegrationFeatures.SERVERLESS])
414409

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 []
422412

423413
def get_pipeline_api_steps(self) -> ApiPipelineSteps[IntegrationPipeline]:
424414
return [
@@ -475,215 +465,3 @@ def post_install(
475465
organization_id=organization.id, integration=integration
476466
):
477467
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

Comments
 (0)