Skip to content

Commit

Permalink
delete app images on app deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
motoki317 committed Oct 17, 2023
1 parent fa97606 commit 41a6e03
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 10 deletions.
3 changes: 2 additions & 1 deletion cmd/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 34 additions & 0 deletions pkg/usecase/apiserver/app_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package apiserver
import (
"context"
"fmt"
"github.com/regclient/regclient/types/ref"
"github.com/traPtitech/neoshowcase/pkg/util/regutil"
"strconv"

"github.com/friendsofgo/errors"
Expand Down Expand Up @@ -274,7 +276,31 @@ func (s *Service) deleteApplicationDatabase(ctx context.Context, app *domain.App
return nil
}

func (s *Service) deleteApplicationImages(ctx context.Context, app *domain.Application) error {
if app.DeployType != domain.DeployTypeRuntime {
return nil
}

imageName := s.image.ImageName(app.ID)
tags, err := regutil.TagList(ctx, s.registry, imageName)
if err != nil {
return err
}
for _, tag := range tags {
tagRef, err := ref.New(imageName + ":" + tag)
if err != nil {
return err
}
err = s.registry.TagDelete(ctx, tagRef)
if err != nil {
return err
}
}
return nil
}

func (s *Service) DeleteApplication(ctx context.Context, id string) error {
// Validate
err := s.isApplicationOwner(ctx, id)
if err != nil {
return err
Expand All @@ -288,6 +314,7 @@ func (s *Service) DeleteApplication(ctx context.Context, id string) error {
return newError(ErrorTypeBadRequest, "stop the application first before deleting", nil)
}

// Delete app database
env, err := s.envRepo.GetEnv(ctx, domain.GetEnvCondition{ApplicationID: optional.From(id)})
if err != nil {
return err
Expand All @@ -296,6 +323,13 @@ func (s *Service) DeleteApplication(ctx context.Context, id string) error {
if err != nil {
return err
}
// Delete runtime app image in background
go func() {
err := s.deleteApplicationImages(context.WithoutCancel(ctx), app)
if err != nil {
log.Errorf("Deleting application %v (id: %v) image: %+v", app.Name, app.ID, err)
}
}()

// delete artifacts
artifacts, err := s.artifactRepo.GetArtifacts(ctx, domain.GetArtifactCondition{ApplicationID: optional.From(app.ID)})
Expand Down
7 changes: 7 additions & 0 deletions pkg/usecase/apiserver/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package apiserver

import (
"context"
"github.com/regclient/regclient"
"github.com/traPtitech/neoshowcase/pkg/domain/builder"

"github.com/friendsofgo/errors"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
Expand Down Expand Up @@ -35,6 +37,8 @@ type Service struct {
containerLogger domain.ContainerLogger
controller domain.ControllerServiceClient
fallbackKey *ssh.PublicKeys
image builder.ImageConfig
registry *regclient.RegClient

systemInfo func(ctx context.Context) (*domain.SystemInfo, error)
tmpKeys *tmpKeyPairService
Expand All @@ -53,6 +57,7 @@ func NewService(
metricsService domain.MetricsService,
containerLogger domain.ContainerLogger,
controller domain.ControllerServiceClient,
image builder.ImageConfig,
fallbackKey *ssh.PublicKeys,
) (*Service, error) {
return &Service{
Expand All @@ -69,6 +74,8 @@ func NewService(
containerLogger: containerLogger,
controller: controller,
fallbackKey: fallbackKey,
image: image,
registry: image.NewRegistry(),

systemInfo: scutil.Once(controller.GetSystemInfo),
tmpKeys: newTmpKeyPairService(),
Expand Down
14 changes: 7 additions & 7 deletions pkg/usecase/cleaner/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func NewService(
c.start = func() {
go loop.Loop(ctx, func(ctx context.Context) {
start := time.Now()
err := c.pruneImages(ctx, r, image.Registry.Addr)
err := c.pruneImages(ctx, r)
if err != nil {
log.Errorf("failed to prune images: %+v", err)
return
Expand Down Expand Up @@ -91,14 +91,14 @@ func (c *cleanerService) Shutdown(_ context.Context) error {
return nil
}

func (c *cleanerService) pruneImages(ctx context.Context, r *regclient.RegClient, regHost string) error {
func (c *cleanerService) pruneImages(ctx context.Context, r *regclient.RegClient) error {
applications, err := c.appRepo.GetApplications(ctx, domain.GetApplicationCondition{DeployType: optional.From(domain.DeployTypeRuntime)})
if err != nil {
return err
}

for _, app := range applications {
err = c.pruneImage(ctx, r, regHost, c.image.NamePrefix, app)
err = c.pruneImage(ctx, r, app)
if err != nil {
log.Errorf("pruning image %v: %+v", c.image.NamePrefix+app.ID, err)
// fail-safe for each image
Expand All @@ -108,9 +108,9 @@ func (c *cleanerService) pruneImages(ctx context.Context, r *regclient.RegClient
return nil
}

func (c *cleanerService) pruneImage(ctx context.Context, r *regclient.RegClient, regHost string, imagePrefix string, app *domain.Application) error {
imageName := imagePrefix + app.ID
tags, err := regutil.TagList(ctx, r, regHost, imageName)
func (c *cleanerService) pruneImage(ctx context.Context, r *regclient.RegClient, app *domain.Application) error {
imageName := c.image.ImageName(app.ID)
tags, err := regutil.TagList(ctx, r, imageName)
if err != nil {
return errors.Wrap(err, "getting tags")
}
Expand All @@ -127,7 +127,7 @@ func (c *cleanerService) pruneImage(ctx context.Context, r *regclient.RegClient,
// NOTE: needs manual execution of "registry garbage-collect <config> --delete-untagged" in docker registry side
// to actually delete the layers
// https://docs.docker.com/registry/garbage-collection/
tagRef, err := ref.New(regHost + "/" + imageName + ":" + tag)
tagRef, err := ref.New(imageName + ":" + tag)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/util/regutil/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ func RepoList(ctx context.Context, r *regclient.RegClient, regHost string) ([]st
}
}

func TagList(ctx context.Context, r *regclient.RegClient, regHost string, imageName string) ([]string, error) {
func TagList(ctx context.Context, r *regclient.RegClient, imageName string) ([]string, error) {
const limit = 100
var tags []string
for {
opts := []scheme.TagOpts{scheme.WithTagLimit(limit)}
if len(tags) > 0 {
opts = append(opts, scheme.WithTagLast(tags[len(tags)-1]))
}
repoRef, err := ref.New(regHost + "/" + imageName)
repoRef, err := ref.New(imageName)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 41a6e03

Please sign in to comment.