Просмотр исходного кода

simplify create and update events (#4033)

Feroze Mohideen 2 лет назад
Родитель
Сommit
b74e555170
1 измененных файлов с 24 добавлено и 133 удалено
  1. 24 133
      api/server/handlers/porter_app/create_and_update_events.go

+ 24 - 133
api/server/handlers/porter_app/create_and_update_events.go

@@ -39,10 +39,6 @@ func NewCreateUpdatePorterAppEventHandler(
 	}
 }
 
-const (
-	crashLoopBackoffSubstring string = "stuck in a restart loop"
-)
-
 func (p *CreateUpdatePorterAppEventHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	ctx, span := telemetry.NewSpan(r.Context(), "serve-post-porter-app-event")
 	defer span.End()
@@ -78,33 +74,32 @@ func (p *CreateUpdatePorterAppEventHandler) ServeHTTP(w http.ResponseWriter, r *
 		reportBuildStatus(ctx, request, p.Config(), user, project, appName, validateApplyV2)
 	}
 
-	// This branch will only be hit for v2 app_event type events
-	if request.ID == "" && request.DeploymentTargetID != "" && request.Type == types.PorterAppEventType_AppEvent {
-		err := p.handleNotification(ctx, request, project.ID, cluster.ID)
-		if err != nil {
-			e := telemetry.Error(ctx, span, err, "error handling notification")
-			p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(e, http.StatusInternalServerError))
-			return
+	var event types.PorterAppEvent
+	var err error
+	if request.ID == "" { // no event id provided, so create a new event/notification
+		// This branch will only be hit for v2 app_event type events
+		if request.DeploymentTargetID != "" && request.Type == types.PorterAppEventType_AppEvent {
+			err := p.handleNotification(ctx, request, project.ID, cluster.ID) // no event will be returned when a notification is handled
+			if err != nil {
+				e := telemetry.Error(ctx, span, err, "error handling notification")
+				p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(e, http.StatusInternalServerError))
+				return
+			}
+		} else {
+			event, err = p.createNewAppEvent(ctx, *cluster, appName, request.DeploymentTargetID, request.Status, string(request.Type), request.TypeExternalSource, request.Metadata)
+			if err != nil {
+				e := telemetry.Error(ctx, span, err, "error creating new app event")
+				p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(e, http.StatusBadRequest))
+				return
+			}
 		}
-		return
-	}
-
-	if request.ID == "" {
-		event, err := p.createNewAppEvent(ctx, *cluster, appName, request.DeploymentTargetID, request.Status, string(request.Type), request.TypeExternalSource, request.Metadata)
+	} else { // event id provided, so update an existing event matching that event
+		event, err = p.updateExistingAppEvent(ctx, *cluster, appName, *request)
 		if err != nil {
 			e := telemetry.Error(ctx, span, err, "error creating new app event")
 			p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(e, http.StatusBadRequest))
 			return
 		}
-		p.WriteResult(w, r, event)
-		return
-	}
-
-	event, err := p.updateExistingAppEvent(ctx, *cluster, appName, *request)
-	if err != nil {
-		e := telemetry.Error(ctx, span, err, "error creating new app event")
-		p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(e, http.StatusBadRequest))
-		return
 	}
 	p.WriteResult(w, r, event)
 }
@@ -161,29 +156,14 @@ func (p *CreateUpdatePorterAppEventHandler) createNewAppEvent(ctx context.Contex
 		telemetry.AttributeKV{Key: "project-id", Value: int(cluster.ProjectID)},
 	)
 
+	// this branch can be safely removed once v1 is deprecated
 	if eventType == string(types.PorterAppEventType_AppEvent) {
 		// Agent has no way to know what the porter app event id is, so if we must dedup here
-		// TODO: create a filter to filter by only agent events. Not an issue now as app events are deduped per hour on the agent side
 		if agentEventID, ok := requestMetadata["agent_event_id"]; ok {
 			var existingEvents []*models.PorterAppEvent
-			if deploymentTargetID == "" {
-				existingEvents, _, err = p.Repo().PorterAppEvent().ListEventsByPorterAppID(ctx, app.ID)
-				if err != nil {
-					return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "error listing porter app events for event type")
-				}
-			} else {
-				deploymentTargetUUID, err := uuid.Parse(deploymentTargetID)
-				if err != nil {
-					return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "error parsing deployment target id")
-				}
-				if deploymentTargetUUID == uuid.Nil {
-					return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "deployment target id cannot be nil")
-				}
-
-				existingEvents, _, err = p.Repo().PorterAppEvent().ListEventsByPorterAppIDAndDeploymentTargetID(ctx, app.ID, deploymentTargetUUID)
-				if err != nil {
-					return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "error listing porter app events for event type with deployment target id")
-				}
+			existingEvents, _, err = p.Repo().PorterAppEvent().ListEventsByPorterAppID(ctx, app.ID)
+			if err != nil {
+				return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "error listing porter app events for event type")
 			}
 
 			for _, existingEvent := range existingEvents {
@@ -201,23 +181,6 @@ func (p *CreateUpdatePorterAppEventHandler) createNewAppEvent(ctx context.Contex
 				}
 			}
 		}
-
-		// before creating a new app_event type event, check the event for crashloop backoff
-		// if the event is a crashloop backoff, then update the service status of the deployment event associated it to FAILED, since the service's deployment will never succeed from crashloop backoff
-		// only applies to v2 apps (where the deployment target id is not empty)
-		if deploymentTargetID != "" {
-			updateMetadata, appEventFormattedCorrectly := appEventMatchesDetail(requestMetadata, crashLoopBackoffSubstring)
-			if appEventFormattedCorrectly {
-				_ = p.updateDeployEventMatchingAppEventDetails(
-					ctx,
-					porterAppName,
-					app.ID,
-					deploymentTargetID,
-					updateMetadata,
-					types.PorterAppEventStatus_Failed,
-				)
-			}
-		}
 	}
 
 	if eventType == string(types.PorterAppEventType_Deploy) {
@@ -553,78 +516,6 @@ func getServiceNameFromPodName(podName, porterAppName string) string {
 	return ""
 }
 
-// appEventMatchesDetail checks if the app event metadata matches the detail string, returning true if so
-// also returns the app event metadata as a defined struct, rather than a generic map
-func appEventMatchesDetail(eventMetadata map[string]any, detail string) (*types.PorterAppAppEventMetadata, bool) {
-	appEventMetadata := &types.PorterAppAppEventMetadata{}
-
-	by, err := json.Marshal(eventMetadata)
-	if err != nil {
-		return appEventMetadata, false
-	}
-
-	err = json.Unmarshal(by, appEventMetadata)
-	if err != nil {
-		return appEventMetadata, false
-	}
-
-	if appEventMetadata.AppRevisionID == "" {
-		return appEventMetadata, false
-	}
-	if appEventMetadata.ServiceName == "" {
-		return appEventMetadata, false
-	}
-	if !strings.Contains(appEventMetadata.Detail, detail) {
-		return appEventMetadata, false
-	}
-
-	return appEventMetadata, true
-}
-
-// updateDeployEventMatchingAppEventDetails updates the deploy event and service specified by the app event metadata, if it exists
-func (p *CreateUpdatePorterAppEventHandler) updateDeployEventMatchingAppEventDetails(
-	ctx context.Context,
-	porterAppName string,
-	porterAppId uint,
-	deploymentTargetID string,
-	updateMetadata *types.PorterAppAppEventMetadata,
-	status types.PorterAppEventStatus,
-) error {
-	ctx, span := telemetry.NewSpan(ctx, "update-deploy-event-matching-app-event-details")
-	defer span.End()
-
-	if updateMetadata == nil {
-		return telemetry.Error(ctx, span, nil, "update metadata is nil")
-	}
-
-	telemetry.WithAttributes(
-		span,
-		telemetry.AttributeKV{Key: "porter-app-name", Value: porterAppName},
-		telemetry.AttributeKV{Key: "porter-app-id", Value: porterAppId},
-		telemetry.AttributeKV{Key: "deployment-target-id", Value: deploymentTargetID},
-		telemetry.AttributeKV{Key: "app-revision-id", Value: updateMetadata.AppRevisionID},
-		telemetry.AttributeKV{Key: "service-name", Value: updateMetadata.ServiceName},
-		telemetry.AttributeKV{Key: "detail", Value: updateMetadata.Detail},
-	)
-
-	// convert the metadata to a map[string]interface{} because that is the type updateDeployEvent expects
-	// TODO: refactor updateDeployEvent so we don't have to do this
-	updateMetadataBytes, err := json.Marshal(updateMetadata)
-	if err != nil {
-		return telemetry.Error(ctx, span, err, "error marshaling update metadata")
-	}
-	updateMetadataMap := make(map[string]interface{})
-	err = json.Unmarshal(updateMetadataBytes, &updateMetadataMap)
-	if err != nil {
-		return telemetry.Error(ctx, span, err, "error unmarshaling update metadata")
-	}
-
-	updateMetadataMap["deploy_status"] = string(status)
-	// we do not need the returned updated event
-	_ = p.updateDeployEvent(ctx, porterAppName, porterAppId, deploymentTargetID, updateMetadataMap)
-	return nil
-}
-
 // handleNotification handles all logic for notifications in app v2
 func (p *CreateUpdatePorterAppEventHandler) handleNotification(ctx context.Context,
 	request *types.CreateOrUpdatePorterAppEventRequest,