mirror of https://github.com/harness/drone.git
feat: [CDE-391]:add infrastruce and orchestrator funcs (#2841)
* Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into add-force-delete-job-funcs * change name * increase scope of delete * change func name * modify delete api * Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into add-force-delete-job-funcs * add delete and handler condition * address comment * handle cleanup event * update enum mapping * find destroyed infra as well * Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into add-force-delete-job-funcs * modify find signature * Merge branch 'add-force-delete-job-funcs' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into add-force-delete-job-funcs * address feedback 2 * address feedback * Apply suggestion from code review * Apply suggestion from code review * remove std out * add infrastruce and orchestrator funcs * add and modify infra provider methods Add cleanupInstanceResources method Modify Deprovision method and make it idempotent * address feedback 2 * Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into add-force-delete-job-funcs * Merge branch 'add-force-delete-job-funcs' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into add-force-delete-job-funcs * address feedback * Apply suggestion from code review * Apply suggestion from code review * remove std out * Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into add-force-delete-job-funcs * add infrastruce and orchestrator funcs * add and modify infra provider methods Add cleanupInstanceResources method Modify Deprovision method and make it idempotentdevcontainer-setup
parent
f3016357d3
commit
6983438ec2
|
@ -25,6 +25,9 @@ import (
|
||||||
"github.com/harness/gitness/store/database/dbtx"
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// gitspaceInstanceCleaningTimedOutMins is timeout for which a gitspace instance can be in cleaning state.
|
||||||
|
const gitspaceInstanceCleaningTimedOutMins = 10
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
authorizer authz.Authorizer
|
authorizer authz.Authorizer
|
||||||
infraProviderSvc *infraprovider.Service
|
infraProviderSvc *infraprovider.Service
|
||||||
|
|
|
@ -55,6 +55,7 @@ func (c *Controller) Delete(
|
||||||
instance, _ := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, gitspaceConfig.ID)
|
instance, _ := c.gitspaceInstanceStore.FindLatestByGitspaceConfigID(ctx, gitspaceConfig.ID)
|
||||||
gitspaceConfig.GitspaceInstance = instance
|
gitspaceConfig.GitspaceInstance = instance
|
||||||
if instance == nil || instance.State == enum.GitspaceInstanceStateUninitialized {
|
if instance == nil || instance.State == enum.GitspaceInstanceStateUninitialized {
|
||||||
|
gitspaceConfig.IsMarkedForDeletion = true
|
||||||
gitspaceConfig.IsDeleted = true
|
gitspaceConfig.IsDeleted = true
|
||||||
if err = c.gitspaceSvc.UpdateConfig(ctx, gitspaceConfig); err != nil {
|
if err = c.gitspaceSvc.UpdateConfig(ctx, gitspaceConfig); err != nil {
|
||||||
return fmt.Errorf("failed to mark gitspace config as deleted: %w", err)
|
return fmt.Errorf("failed to mark gitspace config as deleted: %w", err)
|
||||||
|
@ -87,6 +88,12 @@ func (c *Controller) removeGitspace(ctx context.Context, config types.GitspaceCo
|
||||||
config.GitspaceInstance.Identifier)
|
config.GitspaceInstance.Identifier)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else if config.GitspaceInstance.State == enum.GitSpaceInstanceStateCleaning &&
|
||||||
|
time.Since(time.UnixMilli(config.GitspaceInstance.Updated)).Milliseconds() <=
|
||||||
|
(gitspaceInstanceCleaningTimedOutMins*60*1000) {
|
||||||
|
log.Ctx(ctx).Warn().Msgf("gitspace start/stop is already pending for : %q",
|
||||||
|
config.GitspaceInstance.Identifier)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if err := c.gitspaceSvc.TriggerDelete(ctx, config); err != nil {
|
if err := c.gitspaceSvc.TriggerDelete(ctx, config); err != nil {
|
||||||
log.Ctx(ctx).Err(err).Msgf("error during triggering delete for gitspace instance %s",
|
log.Ctx(ctx).Err(err).Msgf("error during triggering delete for gitspace instance %s",
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
// 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 infrastructure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/types"
|
||||||
|
"github.com/harness/gitness/types/enum"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (i infraProvisioner) TriggerCleanupInstance(
|
||||||
|
ctx context.Context,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
infra types.Infrastructure,
|
||||||
|
) error {
|
||||||
|
infraProviderEntity, err := i.getConfigFromResource(ctx, gitspaceConfig.InfraProviderResource)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
infraProvider, err := i.getInfraProvider(infraProviderEntity.Type)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return infraProvider.CleanupInstanceResources(ctx, infra)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i infraProvisioner) ResumeCleanupInstance(
|
||||||
|
ctx context.Context,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
cleanedInfra types.Infrastructure,
|
||||||
|
) error {
|
||||||
|
infraProvider, err := i.getInfraProvider(cleanedInfra.ProviderType)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew {
|
||||||
|
return i.resumeCleanupForNewProvisioning(ctx, gitspaceConfig, cleanedInfra)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i infraProvisioner) resumeCleanupForNewProvisioning(
|
||||||
|
ctx context.Context,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
cleanedInfra types.Infrastructure,
|
||||||
|
) error {
|
||||||
|
err := i.updateInfraProvisionedRecord(ctx, gitspaceConfig, cleanedInfra)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to update provisioned record after cleanup: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ func (i infraProvisioner) TriggerDeprovision(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
infra types.Infrastructure,
|
infra types.Infrastructure,
|
||||||
|
canDeleteUserData bool,
|
||||||
) error {
|
) error {
|
||||||
infraProviderEntity, err := i.getConfigFromResource(ctx, gitspaceConfig.InfraProviderResource)
|
infraProviderEntity, err := i.getConfigFromResource(ctx, gitspaceConfig.InfraProviderResource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -39,9 +40,9 @@ func (i infraProvisioner) TriggerDeprovision(
|
||||||
}
|
}
|
||||||
|
|
||||||
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew {
|
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew {
|
||||||
return i.triggerDeprovisionForNewProvisioning(ctx, infraProvider, gitspaceConfig, infra)
|
return i.triggerDeprovisionForNewProvisioning(ctx, infraProvider, gitspaceConfig, infra, canDeleteUserData)
|
||||||
}
|
}
|
||||||
return i.triggerDeprovisionForExistingProvisioning(ctx, infraProvider, infra)
|
return i.triggerDeprovisionForExistingProvisioning(ctx, infraProvider, infra, canDeleteUserData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i infraProvisioner) triggerDeprovisionForNewProvisioning(
|
func (i infraProvisioner) triggerDeprovisionForNewProvisioning(
|
||||||
|
@ -49,6 +50,7 @@ func (i infraProvisioner) triggerDeprovisionForNewProvisioning(
|
||||||
infraProvider infraprovider.InfraProvider,
|
infraProvider infraprovider.InfraProvider,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
infra types.Infrastructure,
|
infra types.Infrastructure,
|
||||||
|
canDeleteUserData bool,
|
||||||
) error {
|
) error {
|
||||||
infraProvisionedLatest, err := i.infraProvisionedStore.FindLatestByGitspaceInstanceID(
|
infraProvisionedLatest, err := i.infraProvisionedStore.FindLatestByGitspaceInstanceID(
|
||||||
ctx, gitspaceConfig.SpaceID, gitspaceConfig.GitspaceInstance.ID)
|
ctx, gitspaceConfig.SpaceID, gitspaceConfig.GitspaceInstance.ID)
|
||||||
|
@ -62,7 +64,7 @@ func (i infraProvisioner) triggerDeprovisionForNewProvisioning(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = infraProvider.Deprovision(ctx, infra)
|
err = infraProvider.Deprovision(ctx, infra, canDeleteUserData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to trigger deprovision infra %+v: %w", infra, err)
|
return fmt.Errorf("unable to trigger deprovision infra %+v: %w", infra, err)
|
||||||
}
|
}
|
||||||
|
@ -74,8 +76,9 @@ func (i infraProvisioner) triggerDeprovisionForExistingProvisioning(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
infraProvider infraprovider.InfraProvider,
|
infraProvider infraprovider.InfraProvider,
|
||||||
infra types.Infrastructure,
|
infra types.Infrastructure,
|
||||||
|
canDeleteUserData bool,
|
||||||
) error {
|
) error {
|
||||||
err := infraProvider.Deprovision(ctx, infra)
|
err := infraProvider.Deprovision(ctx, infra, canDeleteUserData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to trigger deprovision infra %+v: %w", infra, err)
|
return fmt.Errorf("unable to trigger deprovision infra %+v: %w", infra, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,15 +52,32 @@ type InfraProvisioner interface {
|
||||||
deprovisionedInfra types.Infrastructure,
|
deprovisionedInfra types.Infrastructure,
|
||||||
) error
|
) error
|
||||||
|
|
||||||
// TriggerDeprovision triggers deprovisionign of all the resources created for the Gitspace.
|
// TriggerDeprovision triggers deprovisionign of resources created for a Gitspace.
|
||||||
|
// canDeleteUserData = true -> triggers deprovision of all resources
|
||||||
|
// canDeleteUserData = false -> triggers deprovision of all resources except storage associated to user data.
|
||||||
TriggerDeprovision(
|
TriggerDeprovision(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
infra types.Infrastructure,
|
infra types.Infrastructure,
|
||||||
|
canDeleteUserData bool,
|
||||||
|
) error
|
||||||
|
|
||||||
|
// ResumeDeprovision stores the deprovisioned infra details in the db depending on the provisioning type.
|
||||||
|
ResumeDeprovision(
|
||||||
|
ctx context.Context,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
deprovisionedInfra types.Infrastructure,
|
||||||
|
) error
|
||||||
|
|
||||||
|
// TriggerCleanupInstance cleans up resources exclusive for a gitspace instance
|
||||||
|
TriggerCleanupInstance(
|
||||||
|
ctx context.Context,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
infra types.Infrastructure,
|
||||||
) error
|
) error
|
||||||
|
|
||||||
// ResumeDeprovision stores the deprovisioned infra details in the db depending on the provisioning type.
|
// ResumeCleanupInstance stores the deprovisioned infra details in the db depending on the provisioning type.
|
||||||
ResumeDeprovision(
|
ResumeCleanupInstance(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
deprovisionedInfra types.Infrastructure,
|
deprovisionedInfra types.Infrastructure,
|
||||||
|
|
|
@ -43,9 +43,21 @@ type Orchestrator interface {
|
||||||
stoppedInfra types.Infrastructure,
|
stoppedInfra types.Infrastructure,
|
||||||
) (enum.GitspaceInstanceStateType, error)
|
) (enum.GitspaceInstanceStateType, error)
|
||||||
|
|
||||||
|
// TriggerCleanupInstanceResources cleans up all the resources exclusive to gitspace instance.
|
||||||
|
TriggerCleanupInstanceResources(ctx context.Context, gitspaceConfig types.GitspaceConfig) error
|
||||||
|
|
||||||
|
// ResumeCleanupInstanceResources saves the cleaned up infra details.
|
||||||
|
ResumeCleanupInstanceResources(
|
||||||
|
ctx context.Context,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
cleanedUpInfra types.Infrastructure,
|
||||||
|
) (enum.GitspaceInstanceStateType, error)
|
||||||
|
|
||||||
// TriggerDeleteGitspace removes the Gitspace container and triggers infra deprovisioning to deprovision
|
// TriggerDeleteGitspace removes the Gitspace container and triggers infra deprovisioning to deprovision
|
||||||
// all the infra resources.
|
// the infra resources.
|
||||||
TriggerDeleteGitspace(ctx context.Context, gitspaceConfig types.GitspaceConfig) error
|
// canDeleteUserData = false -> trigger deprovision of all resources except storage associated to user data.
|
||||||
|
// canDeleteUserData = true -> trigger deprovision of all resources.
|
||||||
|
TriggerDeleteGitspace(ctx context.Context, gitspaceConfig types.GitspaceConfig, canDeleteUserData bool) error
|
||||||
|
|
||||||
// ResumeDeleteGitspace saves the deprovisioned infra details.
|
// ResumeDeleteGitspace saves the deprovisioned infra details.
|
||||||
ResumeDeleteGitspace(
|
ResumeDeleteGitspace(
|
||||||
|
|
|
@ -199,12 +199,89 @@ func (o orchestrator) stopAndRemoveGitspaceContainer(
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o orchestrator) TriggerCleanupInstanceResources(ctx context.Context, gitspaceConfig types.GitspaceConfig) error {
|
||||||
|
infra, err := o.getProvisionedInfra(ctx, gitspaceConfig,
|
||||||
|
[]enum.InfraStatus{
|
||||||
|
enum.InfraStatusProvisioned,
|
||||||
|
enum.InfraStatusStopped,
|
||||||
|
enum.InfraStatusPending,
|
||||||
|
enum.InfraStatusUnknown,
|
||||||
|
enum.InfraStatusDestroyed,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"unable to find provisioned infra while triggering cleanup for gitspace instance %s: %w",
|
||||||
|
gitspaceConfig.GitspaceInstance.Identifier, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if gitspaceConfig.GitspaceInstance.State != enum.GitSpaceInstanceStateCleaning {
|
||||||
|
return fmt.Errorf("cannot trigger cleanup, expected state: %s, actual state: %s ",
|
||||||
|
enum.GitSpaceInstanceStateCleaning,
|
||||||
|
gitspaceConfig.GitspaceInstance.State,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraCleanupStart)
|
||||||
|
|
||||||
|
err = o.infraProvisioner.TriggerCleanupInstance(ctx, gitspaceConfig, *infra)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot trigger cleanup infrastructure with ID %s: %w",
|
||||||
|
gitspaceConfig.InfraProviderResource.UID,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o orchestrator) ResumeCleanupInstanceResources(
|
||||||
|
ctx context.Context,
|
||||||
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
cleanedUpInfra types.Infrastructure,
|
||||||
|
) (enum.GitspaceInstanceStateType, error) {
|
||||||
|
instanceState := enum.GitspaceInstanceStateError
|
||||||
|
|
||||||
|
err := o.infraProvisioner.ResumeCleanupInstance(ctx, gitspaceConfig, cleanedUpInfra)
|
||||||
|
if err != nil {
|
||||||
|
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraCleanupFailed)
|
||||||
|
|
||||||
|
return instanceState, fmt.Errorf(
|
||||||
|
"cannot clenup provisioned infrastructure with ID %s: %w",
|
||||||
|
gitspaceConfig.InfraProviderResource.UID,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cleanedUpInfra.Status != enum.InfraStatusDestroyed && cleanedUpInfra.Status != enum.InfraStatusStopped {
|
||||||
|
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraCleanupFailed)
|
||||||
|
|
||||||
|
return instanceState, fmt.Errorf(
|
||||||
|
"infra state is %v, should be %v for gitspace instance identifier %s",
|
||||||
|
cleanedUpInfra.Status,
|
||||||
|
[]enum.InfraStatus{enum.InfraStatusDestroyed, enum.InfraStatusStopped},
|
||||||
|
gitspaceConfig.GitspaceInstance.Identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraCleanupCompleted)
|
||||||
|
|
||||||
|
instanceState = enum.GitspaceInstanceStateCleaned
|
||||||
|
|
||||||
|
return instanceState, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (o orchestrator) TriggerDeleteGitspace(
|
func (o orchestrator) TriggerDeleteGitspace(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
gitspaceConfig types.GitspaceConfig,
|
gitspaceConfig types.GitspaceConfig,
|
||||||
|
canDeleteUserData bool,
|
||||||
) error {
|
) error {
|
||||||
infra, err := o.getProvisionedInfra(ctx, gitspaceConfig,
|
infra, err := o.getProvisionedInfra(ctx, gitspaceConfig,
|
||||||
[]enum.InfraStatus{enum.InfraStatusProvisioned, enum.InfraStatusStopped, enum.InfraStatusDestroyed})
|
[]enum.InfraStatus{
|
||||||
|
enum.InfraStatusProvisioned,
|
||||||
|
enum.InfraStatusStopped,
|
||||||
|
enum.InfraStatusDestroyed,
|
||||||
|
enum.InfraStatusError,
|
||||||
|
enum.InfraStatusUnknown,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"unable to find provisioned infra while triggering delete for gitspace instance %s: %w",
|
"unable to find provisioned infra while triggering delete for gitspace instance %s: %w",
|
||||||
|
@ -217,7 +294,7 @@ func (o orchestrator) TriggerDeleteGitspace(
|
||||||
}
|
}
|
||||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningStart)
|
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningStart)
|
||||||
|
|
||||||
err = o.infraProvisioner.TriggerDeprovision(ctx, gitspaceConfig, *infra)
|
err = o.infraProvisioner.TriggerDeprovision(ctx, gitspaceConfig, *infra, canDeleteUserData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningFailed)
|
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraDeprovisioningFailed)
|
||||||
|
|
||||||
|
|
|
@ -24,5 +24,5 @@ func (c *Service) TriggerDelete(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
config types.GitspaceConfig,
|
config types.GitspaceConfig,
|
||||||
) error {
|
) error {
|
||||||
return c.orchestrator.TriggerDeleteGitspace(ctx, config)
|
return c.orchestrator.TriggerDeleteGitspace(ctx, config, true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,10 +80,11 @@ func (c *Service) setInstance(
|
||||||
func (c *Service) FindByID(
|
func (c *Service) FindByID(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
id int64,
|
id int64,
|
||||||
|
includeDeleted bool,
|
||||||
) (*types.GitspaceConfig, error) {
|
) (*types.GitspaceConfig, error) {
|
||||||
var gitspaceConfigResult *types.GitspaceConfig
|
var gitspaceConfigResult *types.GitspaceConfig
|
||||||
txErr := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
txErr := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||||
gitspaceConfig, err := c.gitspaceConfigStore.Find(ctx, id)
|
gitspaceConfig, err := c.gitspaceConfigStore.Find(ctx, id, includeDeleted)
|
||||||
gitspaceConfigResult = gitspaceConfig
|
gitspaceConfigResult = gitspaceConfig
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to find gitspace config: %w", err)
|
return fmt.Errorf("failed to find gitspace config: %w", err)
|
||||||
|
|
|
@ -68,7 +68,7 @@ func (s *Service) handleGitspaceInfraEvent(
|
||||||
instanceState, resumeDeleteErr := s.orchestrator.ResumeDeleteGitspace(ctx, *config, payload.Infra)
|
instanceState, resumeDeleteErr := s.orchestrator.ResumeDeleteGitspace(ctx, *config, payload.Infra)
|
||||||
if resumeDeleteErr != nil {
|
if resumeDeleteErr != nil {
|
||||||
err = fmt.Errorf("failed to resume delete gitspace: %w", resumeDeleteErr)
|
err = fmt.Errorf("failed to resume delete gitspace: %w", resumeDeleteErr)
|
||||||
} else {
|
} else if config.IsMarkedForDeletion {
|
||||||
config.IsDeleted = true
|
config.IsDeleted = true
|
||||||
updateErr := s.gitspaceSvc.UpdateConfig(ctx, config)
|
updateErr := s.gitspaceSvc.UpdateConfig(ctx, config)
|
||||||
if updateErr != nil {
|
if updateErr != nil {
|
||||||
|
@ -76,6 +76,15 @@ func (s *Service) handleGitspaceInfraEvent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance.State = instanceState
|
||||||
|
case enum.InfraEventCleanup:
|
||||||
|
instanceState, resumeCleanupErr := s.orchestrator.ResumeCleanupInstanceResources(ctx, *config, payload.Infra)
|
||||||
|
if resumeCleanupErr != nil {
|
||||||
|
s.emitGitspaceConfigEvent(ctx, config, enum.GitspaceEventTypeInfraCleanupFailed)
|
||||||
|
|
||||||
|
err = fmt.Errorf("failed to resume cleanup gitspace: %w", resumeCleanupErr)
|
||||||
|
}
|
||||||
|
|
||||||
instance.State = instanceState
|
instance.State = instanceState
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown event type: %s", event.Payload.Type)
|
return fmt.Errorf("unknown event type: %s", event.Payload.Type)
|
||||||
|
|
|
@ -648,7 +648,7 @@ type (
|
||||||
|
|
||||||
GitspaceConfigStore interface {
|
GitspaceConfigStore interface {
|
||||||
// Find returns a gitspace config given a ID from the datastore.
|
// Find returns a gitspace config given a ID from the datastore.
|
||||||
Find(ctx context.Context, id int64) (*types.GitspaceConfig, error)
|
Find(ctx context.Context, id int64, includeDeleted bool) (*types.GitspaceConfig, error)
|
||||||
|
|
||||||
// FindAll returns list of gitspace configs given a IDs from the datastore.
|
// FindAll returns list of gitspace configs given a IDs from the datastore.
|
||||||
FindAll(ctx context.Context, id []int64) ([]*types.GitspaceConfig, error)
|
FindAll(ctx context.Context, id []int64) ([]*types.GitspaceConfig, error)
|
||||||
|
|
|
@ -133,12 +133,16 @@ func (s gitspaceConfigStore) Count(ctx context.Context, filter *types.GitspaceFi
|
||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s gitspaceConfigStore) Find(ctx context.Context, id int64) (*types.GitspaceConfig, error) {
|
func (s gitspaceConfigStore) Find(ctx context.Context, id int64, includeDeleted bool) (*types.GitspaceConfig, error) {
|
||||||
stmt := database.Builder.
|
stmt := database.Builder.
|
||||||
Select(gitspaceConfigSelectColumns).
|
Select(gitspaceConfigSelectColumns).
|
||||||
From(gitspaceConfigsTable).
|
From(gitspaceConfigsTable).
|
||||||
Where("gconf_id = ?", id). //nolint:goconst
|
Where("gconf_id = ?", id) //nolint:goconst
|
||||||
Where("gconf_is_deleted = ?", false)
|
|
||||||
|
if !includeDeleted {
|
||||||
|
stmt = stmt.Where("gconf_is_deleted = ?", false)
|
||||||
|
}
|
||||||
|
|
||||||
dst := new(gitspaceConfig)
|
dst := new(gitspaceConfig)
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -182,8 +182,51 @@ func (d DockerProvider) Stop(ctx context.Context, infra types.Infrastructure) er
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprovision deletes the volume created by Provision. It does not stop the docker engine.
|
// CleanupInstanceResources is NOOP as this provider does not utilise infra exclusively associated to a gitspace
|
||||||
func (d DockerProvider) Deprovision(ctx context.Context, infra types.Infrastructure) error {
|
// instance.
|
||||||
|
func (d DockerProvider) CleanupInstanceResources(ctx context.Context, infra types.Infrastructure) error {
|
||||||
|
event := &events.GitspaceInfraEventPayload{
|
||||||
|
Infra: infra,
|
||||||
|
Type: enum.InfraEventCleanup,
|
||||||
|
}
|
||||||
|
|
||||||
|
infra.Status = enum.InfraStatusStopped
|
||||||
|
|
||||||
|
err := d.eventReporter.EmitGitspaceInfraEvent(ctx, events.GitspaceInfraEvent, event)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error emitting gitspace infra event for cleanup: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprovision is NOOP if canDeleteUserData = false
|
||||||
|
// Deprovision deletes the volume created by Provision method if canDeleteUserData = false.
|
||||||
|
// Deprovision does not stop the docker engine in any case.
|
||||||
|
func (d DockerProvider) Deprovision(ctx context.Context, infra types.Infrastructure, canDeleteUserData bool) error {
|
||||||
|
if canDeleteUserData {
|
||||||
|
err := d.deleteVolume(ctx, infra)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't delete volume for %s : %w", infra.Storage, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infra.Status = enum.InfraStatusDestroyed
|
||||||
|
|
||||||
|
event := &events.GitspaceInfraEventPayload{
|
||||||
|
Infra: infra,
|
||||||
|
Type: enum.InfraEventDeprovision,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := d.eventReporter.EmitGitspaceInfraEvent(ctx, events.GitspaceInfraEvent, event)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error emitting gitspace infra event for deprovisioning: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DockerProvider) deleteVolume(ctx context.Context, infra types.Infrastructure) error {
|
||||||
dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, types.Infrastructure{
|
dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, types.Infrastructure{
|
||||||
ProviderType: enum.InfraProviderTypeDocker,
|
ProviderType: enum.InfraProviderTypeDocker,
|
||||||
InputParameters: infra.InputParameters,
|
InputParameters: infra.InputParameters,
|
||||||
|
@ -199,26 +242,39 @@ func (d DockerProvider) Deprovision(ctx context.Context, infra types.Infrastruct
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// check if volume is available
|
||||||
|
volumeList, err := dockerClient.VolumeList(ctx, volume.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("couldn't list the volume: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !findVolume(infra.Storage, volumeList.Volumes) {
|
||||||
|
// given volume does not exist, return nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
err = dockerClient.VolumeRemove(ctx, infra.Storage, true)
|
err = dockerClient.VolumeRemove(ctx, infra.Storage, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't delete volume for %s : %w", infra.Storage, err)
|
return fmt.Errorf("couldn't delete volume for %s : %w", infra.Storage, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
infra.Status = enum.InfraStatusDestroyed
|
|
||||||
|
|
||||||
event := &events.GitspaceInfraEventPayload{
|
|
||||||
Infra: infra,
|
|
||||||
Type: enum.InfraEventDeprovision,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = d.eventReporter.EmitGitspaceInfraEvent(ctx, events.GitspaceInfraEvent, event)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error emitting gitspace infra event for deprovisioning: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func findVolume(target string, volumes []*volume.Volume) bool {
|
||||||
|
for _, vol := range volumes {
|
||||||
|
if vol == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if vol.Name == target {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// AvailableParams returns empty slice as no params are defined.
|
// AvailableParams returns empty slice as no params are defined.
|
||||||
func (d DockerProvider) AvailableParams() []types.InfraProviderParameterSchema {
|
func (d DockerProvider) AvailableParams() []types.InfraProviderParameterSchema {
|
||||||
return []types.InfraProviderParameterSchema{}
|
return []types.InfraProviderParameterSchema{}
|
||||||
|
|
|
@ -49,8 +49,13 @@ type InfraProvider interface {
|
||||||
// Stop frees up the resources allocated against a gitspace, which can be freed.
|
// Stop frees up the resources allocated against a gitspace, which can be freed.
|
||||||
Stop(ctx context.Context, infra types.Infrastructure) error
|
Stop(ctx context.Context, infra types.Infrastructure) error
|
||||||
|
|
||||||
// Deprovision removes all infrastructure provisioned against the gitspace.
|
// CleanupInstanceResources cleans up resources exclusively allocated to a gitspace instance.
|
||||||
Deprovision(ctx context.Context, infra types.Infrastructure) error
|
CleanupInstanceResources(ctx context.Context, infra types.Infrastructure) error
|
||||||
|
|
||||||
|
// Deprovision removes infrastructure provisioned against a gitspace.
|
||||||
|
// canDeleteUserData = false -> remove all resources except storage where user has stored it's data.
|
||||||
|
// canDeleteUserData = true -> remove all resources including storage.
|
||||||
|
Deprovision(ctx context.Context, infra types.Infrastructure, canDeleteUserData bool) error
|
||||||
|
|
||||||
// AvailableParams provides a schema to define the infrastructure.
|
// AvailableParams provides a schema to define the infrastructure.
|
||||||
AvailableParams() []types.InfraProviderParameterSchema
|
AvailableParams() []types.InfraProviderParameterSchema
|
||||||
|
|
|
@ -95,6 +95,11 @@ const (
|
||||||
GitspaceEventTypeInfraStopCompleted GitspaceEventType = "infra_stop_completed"
|
GitspaceEventTypeInfraStopCompleted GitspaceEventType = "infra_stop_completed"
|
||||||
GitspaceEventTypeInfraStopFailed GitspaceEventType = "infra_stop_failed"
|
GitspaceEventTypeInfraStopFailed GitspaceEventType = "infra_stop_failed"
|
||||||
|
|
||||||
|
// Infra cleanup events.
|
||||||
|
GitspaceEventTypeInfraCleanupStart GitspaceEventType = "infra_cleanup_start"
|
||||||
|
GitspaceEventTypeInfraCleanupCompleted GitspaceEventType = "infra_cleanup_completed"
|
||||||
|
GitspaceEventTypeInfraCleanupFailed GitspaceEventType = "infra_cleanup_failed"
|
||||||
|
|
||||||
// Infra deprovisioning events.
|
// Infra deprovisioning events.
|
||||||
GitspaceEventTypeInfraDeprovisioningStart GitspaceEventType = "infra_deprovisioning_start"
|
GitspaceEventTypeInfraDeprovisioningStart GitspaceEventType = "infra_deprovisioning_start"
|
||||||
GitspaceEventTypeInfraDeprovisioningCompleted GitspaceEventType = "infra_deprovisioning_completed"
|
GitspaceEventTypeInfraDeprovisioningCompleted GitspaceEventType = "infra_deprovisioning_completed"
|
||||||
|
|
|
@ -36,16 +36,19 @@ const (
|
||||||
GitspaceInstanceStateUnknown GitspaceInstanceStateType = "unknown"
|
GitspaceInstanceStateUnknown GitspaceInstanceStateType = "unknown"
|
||||||
GitspaceInstanceStateError GitspaceInstanceStateType = "error"
|
GitspaceInstanceStateError GitspaceInstanceStateType = "error"
|
||||||
GitspaceInstanceStateDeleted GitspaceInstanceStateType = "deleted"
|
GitspaceInstanceStateDeleted GitspaceInstanceStateType = "deleted"
|
||||||
|
GitspaceInstanceStateCleaned GitspaceInstanceStateType = "cleaned"
|
||||||
|
|
||||||
GitspaceInstanceStateStarting GitspaceInstanceStateType = "starting"
|
GitspaceInstanceStateStarting GitspaceInstanceStateType = "starting"
|
||||||
GitspaceInstanceStateStopping GitspaceInstanceStateType = "stopping"
|
GitspaceInstanceStateStopping GitspaceInstanceStateType = "stopping"
|
||||||
|
GitSpaceInstanceStateCleaning GitspaceInstanceStateType = "cleaning"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g GitspaceInstanceStateType) IsFinalStatus() bool {
|
func (g GitspaceInstanceStateType) IsFinalStatus() bool {
|
||||||
//nolint:exhaustive
|
//nolint:exhaustive
|
||||||
switch g {
|
switch g {
|
||||||
case GitspaceInstanceStateDeleted,
|
case GitspaceInstanceStateDeleted,
|
||||||
GitspaceInstanceStateError:
|
GitspaceInstanceStateError,
|
||||||
|
GitspaceInstanceStateCleaned:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
@ -56,7 +59,8 @@ func (g GitspaceInstanceStateType) IsBusyStatus() bool {
|
||||||
//nolint:exhaustive
|
//nolint:exhaustive
|
||||||
switch g {
|
switch g {
|
||||||
case GitspaceInstanceStateStarting,
|
case GitspaceInstanceStateStarting,
|
||||||
GitspaceInstanceStateStopping:
|
GitspaceInstanceStateStopping,
|
||||||
|
GitSpaceInstanceStateCleaning:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -67,6 +67,13 @@ func GetGitspaceStateFromInstance(
|
||||||
return GitspaceStateError, nil
|
return GitspaceStateError, nil
|
||||||
}
|
}
|
||||||
return GitspaceStateStopping, nil
|
return GitspaceStateStopping, nil
|
||||||
|
case GitSpaceInstanceStateCleaning:
|
||||||
|
if lastUpdateTimeExceeded(lastUpdateTime) {
|
||||||
|
return GitspaceStateError, nil
|
||||||
|
}
|
||||||
|
return GitspaceStateStopping, nil
|
||||||
|
case GitspaceInstanceStateCleaned:
|
||||||
|
return GitspaceStateStopped, nil
|
||||||
default:
|
default:
|
||||||
return GitspaceStateError, fmt.Errorf("unsupported gitspace instance state %s", string(instanceState))
|
return GitspaceStateError, fmt.Errorf("unsupported gitspace instance state %s", string(instanceState))
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,5 +27,6 @@ var infraEvents = []InfraEvent{
|
||||||
const (
|
const (
|
||||||
InfraEventProvision InfraEvent = "provision"
|
InfraEventProvision InfraEvent = "provision"
|
||||||
InfraEventStop InfraEvent = "stop"
|
InfraEventStop InfraEvent = "stop"
|
||||||
|
InfraEventCleanup InfraEvent = "cleanup"
|
||||||
InfraEventDeprovision InfraEvent = "deprovision"
|
InfraEventDeprovision InfraEvent = "deprovision"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue