Skip to content

Commit

Permalink
Merge pull request #11 from cd1989/cron-trigger
Browse files Browse the repository at this point in the history
Cron trigger
  • Loading branch information
cd1989 authored Sep 10, 2019
2 parents e37f0bd + 553ab13 commit 6ce0d12
Show file tree
Hide file tree
Showing 20 changed files with 1,748 additions and 6 deletions.
9 changes: 9 additions & 0 deletions Gopkg.lock

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

4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
name = "github.com/stretchr/testify"
version = "1.2.2"

[[constraint]]
name = "github.com/robfig/cron"
version = "v3.0.0"

[prune]
go-tests = true
unused-packages = true
32 changes: 29 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Clean images in Harbor by policies.
- **Delete tags without side effects** As we known when we delete a tag from a repo in docker registry, the underneath manifest is deleted, so are other tags what share the same manifest. In this tool, we protect tags from such situation.
- **Delete by policies** Support delete tags by configurable policies
- **Dry run before actual cleanup** To see what would be cleaned up before performing real cleanup.
- **Cron Schedule** Schedule the cleanup regularly by cron.

## Concepts

Expand Down Expand Up @@ -61,7 +62,7 @@ $ make image VERSION=latest
You can also pull one from DockerHub.

```bash
$ docker pull k8sdevops/harbor-cleaner:v0.1.1
$ docker pull k8sdevops/harbor-cleaner:v0.2.0
```

### Configure
Expand Down Expand Up @@ -96,6 +97,12 @@ policy:
# Tags that should be retained anyway, '?', '*' supported.
retainTags: []
# Trigger for the cleanup, if you only want to run cleanup once, remove the 'trigger' part or leave
# the 'trigger.cron' empty
trigger:
# Cron expression to trigger the cleanup, for example "0 0 * * *", leave it empty will disable the
# trigger and fallback to run cleanup once.
cron:
```

In the policy part, exact one of `numberPolicy`, `regexPolicy` should be configured according to the policy type.
Expand All @@ -105,15 +112,34 @@ In the policy part, exact one of `numberPolicy`, `regexPolicy` should be configu
```bash
$ docker run -it --rm \
-v <your-config-file>:/workspace/config.yaml \
harbor-cleaner:latest --dryrun=true
k8sdevops/harbor-cleaner:latest --dryrun=true
```

### Clean

```bash
$ docker run -it --rm \
-v <your-config-file>:/workspace/config.yaml \
harbor-cleaner:latest
k8sdevops/harbor-cleaner:latest
```

### Cron Schedule

Configure the cron trigger and run harbor cleaner container in background.

```yaml
# Trigger for the cleanup, if you only want to run cleanup once, remove the 'trigger' part or leave
# the 'trigger.cron' empty
trigger:
# Cron expression to trigger the cleanup, for example "0 0 * * *", leave it empty will disable the
# trigger and fallback to run cleanup once.
cron: 0 0 * * *
```

```bash
$ docker run -d --name=harbor-cleaner --rm \
-v <your-config-file>:/workspace/config.yaml \
k8sdevops/harbor-cleaner:latest
```

## Supported Version
Expand Down
6 changes: 6 additions & 0 deletions cmd/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,9 @@ policy:

# Tags that should be retained anyway, '?', '*' supported.
retainTags: []
# Trigger for the cleanup, if you only want to run cleanup once, remove the 'trigger' part or leave
# the 'trigger.cron' empty
trigger:
# Cron expression to trigger the cleanup, for example "0 0 * * *", leave it empty will disable the
# trigger and fallback to run cleanup once. Note: you may need to quote the cron expression with double quote
cron:
15 changes: 15 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
_ "github.com/cd1989/harbor-cleaner/pkg/policy/number"
_ "github.com/cd1989/harbor-cleaner/pkg/policy/regex"
_ "github.com/cd1989/harbor-cleaner/pkg/policy/touch"
"github.com/cd1989/harbor-cleaner/pkg/trigger"
)

var configFile *string
Expand All @@ -40,6 +41,20 @@ func main() {
}
harbor.APIClient = client

if config.HasCronSchedule() {
scheduler := trigger.NewCronScheduler(config.Config.Trigger.Cron)
scheduler.Submit(func() {
RunTask(client)
})
scheduler.Start()
<-ctx.Done()
} else {
RunTask(client)
}
}

// RunTask starts cleanup task
func RunTask(client *harbor.Client) {
runner := cleaner.NewRunner(client, config.Config)
if *dryRun {
if err := runner.DryRun(); err != nil {
Expand Down
24 changes: 21 additions & 3 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package config

import (
"io/ioutil"

"fmt"
"io/ioutil"
"strings"

"github.com/robfig/cron"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
)
Expand Down Expand Up @@ -38,12 +38,18 @@ type Policy struct {
RetainTags []string `yaml:"retainTags"`
}

type Trigger struct {
// Cron expression to regularly trigger the cleanup
Cron string `yaml:"cron"`
}

type C struct {
Host string `yaml:"host"`
Version string `yaml:"version"`
Auth Auth `yaml:"auth"`
Projects []string `yaml:"projects"`
Policy Policy `yaml:"policy"`
Trigger *Trigger `yaml:"trigger"`
}

var Config = C{}
Expand All @@ -70,10 +76,22 @@ func Load(configFile string) error {

func Normalize(c *C) error {
trimed := strings.TrimSpace(c.Version)
trimed = strings.TrimPrefix(trimed, "v")
if len(trimed) < 3 {
return fmt.Errorf("unrecoganized version %s, please provide version like 1.4, 1.7.5", c.Version)
}

c.Version = trimed[:3]

if HasCronSchedule() {
_, err := cron.ParseStandard(c.Trigger.Cron)
if err != nil {
return err
}
}

return nil
}

func HasCronSchedule() bool {
return Config.Trigger != nil && len(Config.Trigger.Cron) > 0
}
58 changes: 58 additions & 0 deletions pkg/trigger/cron.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package trigger

import (
"time"

"github.com/robfig/cron"
"github.com/sirupsen/logrus"
)

type CronScheduler interface {
Submit(task func())
Start()
}

type cronScheduler struct {
passport chan struct{}
cronStr string
cron *cron.Cron
}

func NewCronScheduler(cronStr string) CronScheduler {
passport := make(chan struct{}, 1)
passport <- struct{}{}
return &cronScheduler{
passport: passport,
cronStr: cronStr,
cron: cron.New(),
}
}

func (s *cronScheduler) Submit(task func()) {
s.cron.AddFunc(s.cronStr, func() {
logrus.Info("Attempt to perform cleanup task")
var granted bool
select {
case <-s.passport:
granted = true
case <-time.After(time.Second):
granted = false
}

if !granted {
logrus.Info("Another cleanup task is still running, skip")
return
}

defer func() {
s.passport <- struct{}{}
}()

logrus.Info("Start to run cleanup task")
task()
})
}

func (s *cronScheduler) Start() {
s.cron.Start()
}
22 changes: 22 additions & 0 deletions vendor/github.com/robfig/cron/.gitignore

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

1 change: 1 addition & 0 deletions vendor/github.com/robfig/cron/.travis.yml

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

21 changes: 21 additions & 0 deletions vendor/github.com/robfig/cron/LICENSE

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

Loading

0 comments on commit 6ce0d12

Please sign in to comment.