mirror of https://github.com/harness/drone.git
feat: [CDE-697]: Add async flow when gitspace agent fails to perform action (#3602)
* feat: [CDE-697]: fix stop async flow * feat: [CDE-697]: Add async flow when gitspace agent fails to perform actionmain
parent
1ffe29d15a
commit
e518dc7f41
|
@ -47,7 +47,7 @@ func (r *Reporter) EmitGitspaceOperationsEvent(
|
|||
}
|
||||
eventID, err := events.ReporterSendEvent(r.innerReporter, ctx, event, payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send %+v event", event)
|
||||
return fmt.Errorf("failed to send %s event: %w", event, err)
|
||||
}
|
||||
|
||||
log.Ctx(ctx).Debug().Msgf("reported %v event with id '%s'", event, eventID)
|
||||
|
|
|
@ -805,6 +805,7 @@ func GetContainerResponse(
|
|||
codeRepoDir := filepath.Join(homeDir, repoName)
|
||||
|
||||
return &response.StartResponse{
|
||||
Status: response.SuccessStatus,
|
||||
ContainerID: id,
|
||||
ContainerName: containerName,
|
||||
PublishedPorts: ports,
|
||||
|
|
|
@ -318,12 +318,17 @@ func (e *EmbeddedDockerOrchestrator) StopGitspace(
|
|||
return fmt.Errorf("gitspace %s is in a bad state: %s", containerName, state)
|
||||
}
|
||||
|
||||
stopResponse := &response.StopResponse{
|
||||
Status: response.SuccessStatus,
|
||||
}
|
||||
|
||||
err = e.eventReporter.EmitGitspaceOperationsEvent(
|
||||
ctx,
|
||||
events.GitspaceOperationsEvent,
|
||||
&events.GitspaceOperationsEventPayload{
|
||||
Type: enum.GitspaceOperationsEventStop,
|
||||
Infra: infra,
|
||||
Type: enum.GitspaceOperationsEventStop,
|
||||
Infra: infra,
|
||||
Response: stopResponse,
|
||||
},
|
||||
)
|
||||
logger.Debug().Msg("stopped gitspace")
|
||||
|
@ -411,9 +416,12 @@ func (e *EmbeddedDockerOrchestrator) StopAndRemoveGitspace(
|
|||
ctx,
|
||||
events.GitspaceOperationsEvent,
|
||||
&events.GitspaceOperationsEventPayload{
|
||||
Type: enum.GitspaceOperationsEventDelete,
|
||||
Infra: infra,
|
||||
Response: &response.DeleteResponse{CanDeleteUserData: canDeleteUserData},
|
||||
Type: enum.GitspaceOperationsEventDelete,
|
||||
Infra: infra,
|
||||
Response: &response.DeleteResponse{
|
||||
Status: response.SuccessStatus,
|
||||
CanDeleteUserData: canDeleteUserData,
|
||||
},
|
||||
},
|
||||
)
|
||||
logger.Debug().Msg("removed gitspace")
|
||||
|
|
|
@ -15,5 +15,7 @@
|
|||
package response
|
||||
|
||||
type DeleteResponse struct {
|
||||
CanDeleteUserData bool `json:"can_delete_user_data"`
|
||||
Status Status `json:"status"`
|
||||
ErrMessage string `json:"err_message"`
|
||||
CanDeleteUserData bool `json:"can_delete_user_data"`
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ package response
|
|||
|
||||
type StartResponse struct {
|
||||
ContainerID string `json:"container_id"`
|
||||
Status Status `json:"status"`
|
||||
ErrMessage string `json:"err_message"`
|
||||
ContainerName string `json:"container_name"`
|
||||
PublishedPorts map[int]string `json:"published_ports"`
|
||||
AbsoluteRepoPath string `json:"absolute_repo_path"`
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package response
|
||||
|
||||
type Status string
|
||||
|
||||
const (
|
||||
SuccessStatus Status = "success"
|
||||
FailureStatus Status = "failure"
|
||||
)
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package response
|
||||
|
||||
type StopResponse struct {
|
||||
Status Status `json:"status"`
|
||||
ErrMessage string `json:"err_message"`
|
||||
}
|
|
@ -149,8 +149,20 @@ func (o Orchestrator) FinishResumeStartGitspace(
|
|||
provisionedInfra types.Infrastructure,
|
||||
startResponse *response.StartResponse,
|
||||
) (types.GitspaceInstance, *types.GitspaceError) {
|
||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationCompleted)
|
||||
gitspaceInstance := gitspaceConfig.GitspaceInstance
|
||||
if startResponse == nil || startResponse.Status == response.FailureStatus {
|
||||
gitspaceInstance.State = enum.GitspaceInstanceStateError
|
||||
err := fmt.Errorf("gitspace agent does not specify the error for failure")
|
||||
if startResponse != nil && startResponse.ErrMessage != "" {
|
||||
err = fmt.Errorf("%s", startResponse.ErrMessage)
|
||||
}
|
||||
return *gitspaceInstance, &types.GitspaceError{
|
||||
Error: err,
|
||||
ErrorMessage: ptr.String(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationCompleted)
|
||||
|
||||
ideSvc, err := o.ideFactory.GetIDE(gitspaceConfig.IDE)
|
||||
if err != nil {
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
events "github.com/harness/gitness/app/events/gitspace"
|
||||
"github.com/harness/gitness/app/gitspace/infrastructure"
|
||||
"github.com/harness/gitness/app/gitspace/orchestrator/container"
|
||||
"github.com/harness/gitness/app/gitspace/orchestrator/container/response"
|
||||
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
|
||||
"github.com/harness/gitness/app/gitspace/platformconnector"
|
||||
"github.com/harness/gitness/app/gitspace/scm"
|
||||
|
@ -206,7 +207,18 @@ func (o Orchestrator) FinishStopGitspaceContainer(
|
|||
ctx context.Context,
|
||||
gitspaceConfig types.GitspaceConfig,
|
||||
infra types.Infrastructure,
|
||||
stopResponse *response.StopResponse,
|
||||
) *types.GitspaceError {
|
||||
if stopResponse == nil || stopResponse.Status == response.FailureStatus {
|
||||
err := fmt.Errorf("gitspace agent does not specify the error for failure")
|
||||
if stopResponse != nil && stopResponse.ErrMessage != "" {
|
||||
err = fmt.Errorf("%s", stopResponse.ErrMessage)
|
||||
}
|
||||
return &types.GitspaceError{
|
||||
Error: err,
|
||||
ErrorMessage: ptr.String(err.Error()),
|
||||
}
|
||||
}
|
||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceStopCompleted)
|
||||
|
||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraStopStart)
|
||||
|
@ -257,19 +269,29 @@ func (o Orchestrator) FinishStopAndRemoveGitspaceContainer(
|
|||
ctx context.Context,
|
||||
gitspaceConfig types.GitspaceConfig,
|
||||
infra types.Infrastructure,
|
||||
canDeleteUserData bool,
|
||||
deleteResponse *response.DeleteResponse,
|
||||
) *types.GitspaceError {
|
||||
if deleteResponse == nil || deleteResponse.Status == response.FailureStatus {
|
||||
err := fmt.Errorf("gitspace agent does not specify the error for failure")
|
||||
if deleteResponse != nil && deleteResponse.ErrMessage != "" {
|
||||
err = fmt.Errorf("%s", deleteResponse.ErrMessage)
|
||||
}
|
||||
return &types.GitspaceError{
|
||||
Error: err,
|
||||
ErrorMessage: ptr.String(err.Error()),
|
||||
}
|
||||
}
|
||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceDeletionCompleted)
|
||||
if canDeleteUserData {
|
||||
if deleteResponse.CanDeleteUserData {
|
||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningStart)
|
||||
} else {
|
||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraResetStart)
|
||||
}
|
||||
|
||||
opts := infrastructure.InfraEventOpts{CanDeleteUserData: canDeleteUserData}
|
||||
opts := infrastructure.InfraEventOpts{CanDeleteUserData: deleteResponse.CanDeleteUserData}
|
||||
err := o.infraProvisioner.TriggerInfraEventWithOpts(ctx, enum.InfraEventDeprovision, gitspaceConfig, &infra, opts)
|
||||
if err != nil {
|
||||
if canDeleteUserData {
|
||||
if deleteResponse.CanDeleteUserData {
|
||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningFailed)
|
||||
} else {
|
||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraResetFailed)
|
||||
|
|
|
@ -86,14 +86,25 @@ func (s *Service) handleGitspaceOperationsEvent(
|
|||
)
|
||||
if handleResumeStartErr != nil {
|
||||
s.emitGitspaceConfigEvent(ctxWithTimedOut, config, enum.GitspaceEventTypeGitspaceActionStartFailed)
|
||||
instance.State = enum.GitspaceInstanceStateError
|
||||
updatedInstance.ErrorMessage = handleResumeStartErr.ErrorMessage
|
||||
err = fmt.Errorf("failed to finish resume start gitspace: %w", handleResumeStartErr.Error)
|
||||
}
|
||||
instance = &updatedInstance
|
||||
case enum.GitspaceOperationsEventStop:
|
||||
finishStopErr := s.orchestrator.FinishStopGitspaceContainer(ctxWithTimedOut, *config, payload.Infra)
|
||||
stopResponse, ok := payload.Response.(*response.StopResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to cast stop response")
|
||||
}
|
||||
finishStopErr := s.orchestrator.FinishStopGitspaceContainer(
|
||||
ctxWithTimedOut,
|
||||
*config,
|
||||
payload.Infra,
|
||||
stopResponse,
|
||||
)
|
||||
if finishStopErr != nil {
|
||||
s.emitGitspaceConfigEvent(ctxWithTimedOut, config, enum.GitspaceEventTypeGitspaceActionStopFailed)
|
||||
instance.State = enum.GitspaceInstanceStateError
|
||||
instance.ErrorMessage = finishStopErr.ErrorMessage
|
||||
err = fmt.Errorf("failed to finish trigger start gitspace: %w", finishStopErr.Error)
|
||||
}
|
||||
|
@ -106,10 +117,11 @@ func (s *Service) handleGitspaceOperationsEvent(
|
|||
ctxWithTimedOut,
|
||||
*config,
|
||||
payload.Infra,
|
||||
deleteResponse.CanDeleteUserData,
|
||||
deleteResponse,
|
||||
)
|
||||
if finishStopAndRemoveErr != nil {
|
||||
s.emitGitspaceConfigEvent(ctxWithTimedOut, config, enum.GitspaceEventTypeGitspaceActionStopFailed)
|
||||
instance.State = enum.GitspaceInstanceStateError
|
||||
instance.ErrorMessage = finishStopAndRemoveErr.ErrorMessage
|
||||
err = fmt.Errorf("failed to finish trigger start gitspace: %w", finishStopAndRemoveErr.Error)
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ func ReporterSendEvent[T interface{}](reporter *GenericReporter, ctx context.Con
|
|||
buff := &bytes.Buffer{}
|
||||
encoder := gob.NewEncoder(buff)
|
||||
gob.Register((*response.StartResponse)(nil))
|
||||
gob.Register((*response.StopResponse)(nil))
|
||||
gob.Register((*response.DeleteResponse)(nil))
|
||||
|
||||
if err := encoder.Encode(&event); err != nil {
|
||||
|
|
Loading…
Reference in New Issue