Skip to content

Commit 04ab2b3

Browse files
author
Feroze Mohideen
authored
Update service deployment status in ccp (#4035)
1 parent 4f6f01c commit 04ab2b3

File tree

4 files changed

+135
-98
lines changed

4 files changed

+135
-98
lines changed

api/server/handlers/porter_app/create_and_update_events.go

Lines changed: 129 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,26 @@ func (p *CreateUpdatePorterAppEventHandler) createNewAppEvent(ctx context.Contex
186186
if eventType == string(types.PorterAppEventType_Deploy) {
187187
// Agent has no way to know what the porter app event id is, so update the deploy event if it exists
188188
if _, ok := requestMetadata["deploy_status"]; ok {
189-
return p.updateDeployEvent(ctx, porterAppName, app.ID, deploymentTargetID, requestMetadata), nil
189+
if deploymentTargetID == "" {
190+
event, err := p.updateDeployEventV1(ctx, porterAppName, app.ID, requestMetadata)
191+
if err != nil {
192+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "error updating v1 deploy event")
193+
}
194+
return event, nil
195+
} else {
196+
err := p.updateDeployEventV2(ctx, updateDeployEventV2Input{
197+
projectID: cluster.ProjectID,
198+
appName: porterAppName,
199+
appID: app.ID,
200+
deploymentTargetID: deploymentTargetID,
201+
updatedStatusMetadata: requestMetadata,
202+
})
203+
if err != nil {
204+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "error updating v2 deploy event")
205+
}
206+
// v2 method calls ccp and will not return an event, so we just return an empty event
207+
return types.PorterAppEvent{}, nil
208+
}
190209
}
191210
}
192211

@@ -290,104 +309,59 @@ func (p *CreateUpdatePorterAppEventHandler) updateExistingAppEvent(ctx context.C
290309
return existingAppEvent.ToPorterAppEvent(), nil
291310
}
292311

293-
// updateDeployEvent attempts to update the deploy event with the deploy status of each service given in updatedStatusMetadata
312+
// updateDeployEventV1 attempts to update the deploy event with the deploy status of each service given in updatedStatusMetadata
294313
// an update is only made in the following cases:
295314
// 1. the deploy event is found
296315
// 2. the deploy event is in the PROGRESSING state
297316
// 3. the deploy event service deployment metadata is formatted correctly
298317
// 4. the services specified in the updatedStatusMetadata match the services in the deploy event metadata
299318
// 5. some of the above services are still in the PROGRESSING state
300319
// if one of these conditions is not met, then an empty event is returned and no update is made; otherwise, the matched event is returned
301-
func (p *CreateUpdatePorterAppEventHandler) updateDeployEvent(ctx context.Context, appName string, appID uint, deploymentTargetID string, updatedStatusMetadata map[string]any) types.PorterAppEvent {
320+
func (p *CreateUpdatePorterAppEventHandler) updateDeployEventV1(ctx context.Context, appName string, appID uint, updatedStatusMetadata map[string]any) (types.PorterAppEvent, error) {
302321
ctx, span := telemetry.NewSpan(ctx, "update-deploy-event")
303322
defer span.End()
304323

305-
var serviceName string
306-
var matchEvent models.PorterAppEvent
307-
308-
if deploymentTargetID != "" {
309-
appRevisionIDField, ok := updatedStatusMetadata["app_revision_id"]
310-
if !ok {
311-
_ = telemetry.Error(ctx, span, nil, "app_revision_id not found in request metadata")
312-
return types.PorterAppEvent{}
313-
}
314-
appRevisionID, ok := appRevisionIDField.(string)
315-
if !ok {
316-
_ = telemetry.Error(ctx, span, nil, "appRevisionID is not a string")
317-
return types.PorterAppEvent{}
318-
}
319-
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "app-revision-id", Value: appRevisionID})
320-
321-
serviceNameField, ok := updatedStatusMetadata["service_name"]
322-
if !ok {
323-
_ = telemetry.Error(ctx, span, nil, "service_name not found in request metadata")
324-
return types.PorterAppEvent{}
325-
}
326-
serviceName, ok = serviceNameField.(string)
327-
if !ok {
328-
_ = telemetry.Error(ctx, span, nil, "serviceName is not a string")
329-
return types.PorterAppEvent{}
330-
}
331-
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "service-name", Value: serviceName})
332-
333-
var err error
334-
matchEvent, err = p.Repo().PorterAppEvent().ReadDeployEventByAppRevisionID(ctx, appID, appRevisionID)
335-
if err != nil {
336-
_ = telemetry.Error(ctx, span, err, "error finding matching deploy event")
337-
return types.PorterAppEvent{}
338-
}
339-
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "updating-deployment-event", Value: false})
340-
} else {
341-
revision, ok := updatedStatusMetadata["revision"]
342-
if !ok {
343-
_ = telemetry.Error(ctx, span, nil, "revision not found in request metadata")
344-
return types.PorterAppEvent{}
345-
}
346-
revisionFloat64, ok := revision.(float64)
347-
if !ok {
348-
_ = telemetry.Error(ctx, span, nil, "revision not a float64")
349-
return types.PorterAppEvent{}
350-
}
351-
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "revision", Value: revisionFloat64})
352-
353-
podName, ok := updatedStatusMetadata["pod_name"]
354-
if !ok {
355-
_ = telemetry.Error(ctx, span, nil, "pod name not found in request metadata")
356-
return types.PorterAppEvent{}
357-
}
358-
podNameStr, ok := podName.(string)
359-
if !ok {
360-
_ = telemetry.Error(ctx, span, nil, "pod name not a string")
361-
return types.PorterAppEvent{}
362-
}
363-
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "pod-name", Value: podNameStr})
324+
revision, ok := updatedStatusMetadata["revision"]
325+
if !ok {
326+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "revision not found in request metadata")
327+
}
328+
revisionFloat64, ok := revision.(float64)
329+
if !ok {
330+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "revision not a float64")
331+
}
332+
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "revision", Value: revisionFloat64})
364333

365-
serviceName = getServiceNameFromPodName(podNameStr, appName)
366-
if serviceName == "" {
367-
_ = telemetry.Error(ctx, span, nil, "service name not found in pod name")
368-
return types.PorterAppEvent{}
369-
}
370-
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "service-name", Value: serviceName})
334+
podName, ok := updatedStatusMetadata["pod_name"]
335+
if !ok {
336+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "pod name not found in request metadata")
337+
}
338+
podNameStr, ok := podName.(string)
339+
if !ok {
340+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "pod name not a string")
341+
}
342+
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "pod-name", Value: podNameStr})
371343

372-
var err error
373-
matchEvent, err = p.Repo().PorterAppEvent().ReadDeployEventByRevision(ctx, appID, revisionFloat64)
374-
if err != nil {
375-
_ = telemetry.Error(ctx, span, err, "error finding matching deploy event")
376-
return types.PorterAppEvent{}
377-
}
344+
serviceName := getServiceNameFromPodName(podNameStr, appName)
345+
if serviceName == "" {
346+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "service name not found in pod name")
347+
}
348+
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "service-name", Value: serviceName})
378349

379-
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "updating-deployment-event", Value: false})
350+
var err error
351+
matchEvent, err := p.Repo().PorterAppEvent().ReadDeployEventByRevision(ctx, appID, revisionFloat64)
352+
if err != nil {
353+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "error finding matching deploy event")
380354
}
381355

356+
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "updating-deployment-event", Value: false})
357+
382358
newStatus, ok := updatedStatusMetadata["deploy_status"]
383359
if !ok {
384-
_ = telemetry.Error(ctx, span, nil, "deploy status not found in request metadata")
385-
return types.PorterAppEvent{}
360+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "deploy status not found in request metadata")
386361
}
387362
newStatusStr, ok := newStatus.(string)
388363
if !ok {
389-
_ = telemetry.Error(ctx, span, nil, "deploy status not a string")
390-
return types.PorterAppEvent{}
364+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "deploy status not a string")
391365
}
392366
var porterAppEventStatus types.PorterAppEventStatus
393367
switch newStatusStr {
@@ -398,47 +372,41 @@ func (p *CreateUpdatePorterAppEventHandler) updateDeployEvent(ctx context.Contex
398372
case string(types.PorterAppEventStatus_Progressing):
399373
porterAppEventStatus = types.PorterAppEventStatus_Progressing
400374
default:
401-
_ = telemetry.Error(ctx, span, nil, "deploy status not valid")
402-
return types.PorterAppEvent{}
375+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "deploy status not valid")
403376
}
404377

405378
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "new-status", Value: string(porterAppEventStatus)})
406379

407380
// first check to see if the event is empty, meaning there was no match found, or not progressing, meaning it has already been updated
408381
if matchEvent.ID == uuid.Nil || matchEvent.Status != string(types.PorterAppEventStatus_Progressing) {
409-
return types.PorterAppEvent{}
382+
return types.PorterAppEvent{}, nil
410383
}
411384

412385
serviceStatus, ok := matchEvent.Metadata["service_deployment_metadata"]
413386
if !ok {
414-
_ = telemetry.Error(ctx, span, nil, "service deployment metadata not found in deploy event metadata")
415-
return types.PorterAppEvent{}
387+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "service deployment metadata not found in deploy event metadata")
416388
}
417389
serviceDeploymentGenericMap, ok := serviceStatus.(map[string]interface{})
418390
if !ok {
419-
_ = telemetry.Error(ctx, span, nil, "service deployment metadata is not map[string]interface{}")
420-
return types.PorterAppEvent{}
391+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "service deployment metadata is not map[string]interface{}")
421392
}
422393
serviceDeploymentMap := make(map[string]types.ServiceDeploymentMetadata)
423394
for k, v := range serviceDeploymentGenericMap {
424395
by, err := json.Marshal(v)
425396
if err != nil {
426-
_ = telemetry.Error(ctx, span, nil, "unable to marshal")
427-
return types.PorterAppEvent{}
397+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "unable to marshal")
428398
}
429399

430400
var serviceDeploymentMetadata types.ServiceDeploymentMetadata
431401
err = json.Unmarshal(by, &serviceDeploymentMetadata)
432402
if err != nil {
433-
_ = telemetry.Error(ctx, span, nil, "unable to unmarshal")
434-
return types.PorterAppEvent{}
403+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, err, "unable to unmarshal")
435404
}
436405
serviceDeploymentMap[k] = serviceDeploymentMetadata
437406
}
438407
serviceDeploymentMetadata, ok := serviceDeploymentMap[serviceName]
439408
if !ok {
440-
_ = telemetry.Error(ctx, span, nil, "deployment metadata not found for service")
441-
return types.PorterAppEvent{}
409+
return types.PorterAppEvent{}, telemetry.Error(ctx, span, nil, "deployment metadata not found for service")
442410
}
443411

444412
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "existing-status", Value: serviceDeploymentMetadata.Status})
@@ -476,13 +444,79 @@ func (p *CreateUpdatePorterAppEventHandler) updateDeployEvent(ctx context.Contex
476444
err := p.Repo().PorterAppEvent().UpdateEvent(ctx, &matchEvent)
477445
if err != nil {
478446
_ = telemetry.Error(ctx, span, err, "error updating deploy event")
479-
return matchEvent.ToPorterAppEvent()
447+
return matchEvent.ToPorterAppEvent(), nil
480448
}
481449
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "updating-deployment-event", Value: true})
482-
return matchEvent.ToPorterAppEvent()
450+
return matchEvent.ToPorterAppEvent(), nil
483451
}
484452

485-
return types.PorterAppEvent{}
453+
return types.PorterAppEvent{}, nil
454+
}
455+
456+
type updateDeployEventV2Input struct {
457+
projectID uint
458+
appName string
459+
appID uint
460+
deploymentTargetID string
461+
updatedStatusMetadata map[string]any
462+
}
463+
464+
func (p *CreateUpdatePorterAppEventHandler) updateDeployEventV2(
465+
ctx context.Context,
466+
inp updateDeployEventV2Input,
467+
) error {
468+
ctx, span := telemetry.NewSpan(ctx, "update-deploy-event-v2")
469+
defer span.End()
470+
471+
telemetry.WithAttributes(span,
472+
telemetry.AttributeKV{Key: "app-name", Value: inp.appName},
473+
telemetry.AttributeKV{Key: "app-id", Value: inp.appID},
474+
telemetry.AttributeKV{Key: "deployment-target-id", Value: inp.deploymentTargetID},
475+
telemetry.AttributeKV{Key: "project-id", Value: int(inp.projectID)},
476+
)
477+
478+
agentEventMetadata, err := notifications.ParseAgentEventMetadata(inp.updatedStatusMetadata)
479+
if err != nil {
480+
return telemetry.Error(ctx, span, err, "failed to unmarshal agent event metadata")
481+
}
482+
if agentEventMetadata == nil {
483+
return telemetry.Error(ctx, span, nil, "agent event metadata is nil")
484+
}
485+
486+
telemetry.WithAttributes(span,
487+
telemetry.AttributeKV{Key: "app-revision-id", Value: agentEventMetadata.AppRevisionID},
488+
telemetry.AttributeKV{Key: "service-name", Value: agentEventMetadata.ServiceName},
489+
telemetry.AttributeKV{Key: "deployment-status", Value: agentEventMetadata.DeployStatus},
490+
)
491+
var deploymentStatus porterv1.EnumServiceDeploymentStatus
492+
switch agentEventMetadata.DeployStatus {
493+
case types.PorterAppEventStatus_Success:
494+
deploymentStatus = porterv1.EnumServiceDeploymentStatus_ENUM_SERVICE_DEPLOYMENT_STATUS_SUCCESS
495+
case types.PorterAppEventStatus_Failed:
496+
deploymentStatus = porterv1.EnumServiceDeploymentStatus_ENUM_SERVICE_DEPLOYMENT_STATUS_FAILED
497+
case types.PorterAppEventStatus_Progressing:
498+
deploymentStatus = porterv1.EnumServiceDeploymentStatus_ENUM_SERVICE_DEPLOYMENT_STATUS_PROGRESSING
499+
default:
500+
return telemetry.Error(ctx, span, nil, "deployment status not valid")
501+
}
502+
503+
updateRequest := connect.NewRequest(&porterv1.UpdateServiceDeploymentStatusRequest{
504+
ProjectId: int64(inp.projectID),
505+
DeploymentTargetIdentifier: &porterv1.DeploymentTargetIdentifier{
506+
Id: inp.deploymentTargetID,
507+
},
508+
AppName: inp.appName,
509+
AppRevisionId: agentEventMetadata.AppRevisionID,
510+
ServiceName: agentEventMetadata.ServiceName,
511+
Status: deploymentStatus,
512+
})
513+
514+
_, err = p.Config().ClusterControlPlaneClient.UpdateServiceDeploymentStatus(ctx, updateRequest)
515+
if err != nil {
516+
return telemetry.Error(ctx, span, err, "error updating service deployment status")
517+
}
518+
519+
return nil
486520
}
487521

488522
func getServiceNameFromPodName(podName, porterAppName string) string {

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ require (
8383
github.com/matryer/is v1.4.0
8484
github.com/nats-io/nats.go v1.24.0
8585
github.com/open-policy-agent/opa v0.44.0
86-
github.com/porter-dev/api-contracts v0.2.56
86+
github.com/porter-dev/api-contracts v0.2.58
8787
github.com/riandyrn/otelchi v0.5.1
8888
github.com/santhosh-tekuri/jsonschema/v5 v5.0.1
8989
github.com/stefanmcshane/helm v0.0.0-20221213002717-88a4a2c6e77d

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,8 @@ github.com/porter-dev/api-contracts v0.2.55 h1:H8RvD004mX4uWrlRVcL8kzo7ZtFQyZDN+
15241524
github.com/porter-dev/api-contracts v0.2.55/go.mod h1:fX6JmP5QuzxDLvqP3evFOTXjI4dHxsG0+VKNTjImZU8=
15251525
github.com/porter-dev/api-contracts v0.2.56 h1:zym8eomipCj7BVQVlnCY4RjNv1tkduY68gsmwVJIfaQ=
15261526
github.com/porter-dev/api-contracts v0.2.56/go.mod h1:fX6JmP5QuzxDLvqP3evFOTXjI4dHxsG0+VKNTjImZU8=
1527+
github.com/porter-dev/api-contracts v0.2.58 h1:8h5ORZtaq2f1vyEdYD88ZOcHQmYJb77zs+lQXY82yrU=
1528+
github.com/porter-dev/api-contracts v0.2.58/go.mod h1:fX6JmP5QuzxDLvqP3evFOTXjI4dHxsG0+VKNTjImZU8=
15271529
github.com/porter-dev/switchboard v0.0.3 h1:dBuYkiVLa5Ce7059d6qTe9a1C2XEORFEanhbtV92R+M=
15281530
github.com/porter-dev/switchboard v0.0.3/go.mod h1:xSPzqSFMQ6OSbp42fhCi4AbGbQbsm6nRvOkrblFeXU4=
15291531
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=

internal/porter_app/notifications/app_event.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package notifications
33
import (
44
"encoding/json"
55

6+
"github.com/porter-dev/porter/api/types"
67
"github.com/porter-dev/porter/internal/models"
78
)
89

@@ -22,14 +23,14 @@ type AppEventMetadata struct {
2223
ShortSummary string `json:"short_summary"`
2324
// Summary is the summary of the app event
2425
Summary string `json:"summary"`
25-
// AppID is the ID of the app that this event refers to
26-
AppID string `json:"app_id"`
2726
// AppName is the name of the app that this event refers to
2827
AppName string `json:"app_name"`
2928
// Detail is the detail of the app event
3029
Detail string `json:"detail"`
3130
// JobRunID is the ID of the job run that this event refers to, if applicable
3231
JobRunID string `json:"job_run_id"`
32+
// DeployStatus is the status of the deployment, if applicable
33+
DeployStatus types.PorterAppEventStatus `json:"deploy_status"`
3334
}
3435

3536
// ParseAgentEventMetadata parses raw app event metadata to a AppEventMetadata struct

0 commit comments

Comments
 (0)