Skip to content

fix(purge): repair build of the purge function #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ module "my_registry" {
| <a name="input_project_id"></a> [project_id](#input_project_id) | ID of the project the namespace is associated with. Ressource will be created in the project set at the provider level if null. | `string` | `null` | no |
| <a name="input_purge_dry_run"></a> [purge_dry_run](#input_purge_dry_run) | Prevent deletion of tags & images. | `bool` | `true` | no |
| <a name="input_purge_log_level"></a> [purge_log_level](#input_purge_log_level) | Log Level of the purge function. Refer to the Go [slog package documentation](https://pkg.go.dev/log/slog#Level) for accepted values | `number` | `0` | no |
| <a name="input_purge_preserve_tag_patterns"></a> [purge_preserve_tag_patterns](#input_purge_preserve_tag_patterns) | List of regex patterns for tags to preserve. By default, preserves semantic versioning tags. | `list(string)` | ```[ "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" ]``` | no |
| <a name="input_purge_preserve_tag_patterns"></a> [purge_preserve_tag_patterns](#input_purge_preserve_tag_patterns) | List of regex patterns for tags to preserve. By default, preserves semantic versioning tags and `latest` tags. | `list(string)` | ```[ "^latest((-.+)?)$", "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" ]``` | no |
| <a name="input_purge_retention_days"></a> [purge_retention_days](#input_purge_retention_days) | Number of days to keep images before deletion. | `number` | `30` | no |
| <a name="input_purge_schedule"></a> [purge_schedule](#input_purge_schedule) | Cron schedule for the cleanup function. Set to empty string to disable scheduled cleanup. | `string` | `"0 0 * * *"` | no |
| <a name="input_purge_timeout"></a> [purge_timeout](#input_purge_timeout) | Timeout for the cleanup function in seconds. | `number` | `300` | no |
Expand Down
2 changes: 1 addition & 1 deletion functions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ resource "scaleway_function" "registry_purge" {
environment_variables = {
REGISTRY_NAMESPACE = var.name
RETENTION_DAYS = var.purge_retention_days
PRESERVE_TAG_PATTERNS = join(",", var.purge_preserve_tag_patterns)
PRESERVE_TAG_PATTERNS = join("|", var.purge_preserve_tag_patterns)
DRY_RUN = var.purge_dry_run
LOG_LEVEL = var.purge_log_level
}
Expand Down
4 changes: 3 additions & 1 deletion functions/purge/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module purge

go 1.23.8
go 1.23

toolchain go1.23.8

require github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33

Expand Down
16 changes: 8 additions & 8 deletions functions/purge/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

// Default semver pattern for tag preservation
const DefaultTagPattern string = `^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`
const DefaultTagPattern string = `^latest((-.+)?)$|^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$`

// Config holds the configuration for the purge function
type Config struct {
Expand Down Expand Up @@ -62,7 +62,7 @@ var (
)

func init() {
slog.Info("===== Init container =====")
slog.Info("===== Runing 'init' =====")
// Set log level based on environment variable
var logLevel slog.Level
slogLevel, err := strconv.Atoi(os.Getenv("LOG_LEVEL"))
Expand Down Expand Up @@ -149,7 +149,7 @@ func init() {
}

func Handle(w http.ResponseWriter, r *http.Request) {
slog.Info("===== Starting purge =====")
slog.Info("===== Runing 'Handle' =====")
// Get Retention date
retentionDate := time.Now().AddDate(0, 0, -config.RetentionDays)
slog.Info(fmt.Sprintf("Purging images older than: %s", retentionDate.Format(time.RFC3339)))
Expand Down Expand Up @@ -196,15 +196,15 @@ func Handle(w http.ResponseWriter, r *http.Request) {
for _, tag := range tags {
// Check if tag is older than retention date
if tag.UpdatedAt.Before(retentionDate) {
slog.Info(fmt.Sprintf("Tag %s:%s updated at %s is older than retention date %s",
slog.Debug(fmt.Sprintf("Tag %s:%s updated at %s is older than retention date %s",
image.Name, tag.Name, tag.UpdatedAt.Format(time.RFC3339), retentionDate.Format(time.RFC3339)))

// Check if tag is protected
if config.PreserveTagPatterns.MatchString(tag.Name) {
slog.Info(fmt.Sprintf("Tag %s match protection pattern. Preserving", tag.Name))
slog.Debug(fmt.Sprintf("Tag %s match protection pattern. Preserving", tag.Name))
preservedTags++
} else {
slog.Info(fmt.Sprintf("Tag %s doesn't match protection pattern.", tag.Name))
slog.Debug(fmt.Sprintf("Tag %s doesn't match protection pattern.", tag.Name))
// Delete tag if not dry run
if err := registryClient.DeleteTag(context.Background(), tag); err != nil {
slog.Error(fmt.Sprintf("Failed to delete tag %s (%s): %v", tag.Name, tag.ID, err))
Expand All @@ -214,7 +214,7 @@ func Handle(w http.ResponseWriter, r *http.Request) {
deletedTags++
}
} else {
slog.Info(fmt.Sprintf("Tag %s updated at %s is newer than retention date %s. Skipping",
slog.Debug(fmt.Sprintf("Tag %s updated at %s is newer than retention date %s. Skipping",
tag.Name, tag.UpdatedAt.Format(time.RFC3339), retentionDate.Format(time.RFC3339)))
skippedTags++
}
Expand All @@ -233,7 +233,7 @@ func Handle(w http.ResponseWriter, r *http.Request) {
// DeleteTag deletes a tag
func (r *RegistryClient) DeleteTag(ctx context.Context, tag *registry.Tag) error {
if r.config.DryRun {
slog.Info(fmt.Sprintf("[DRY RUN] Would delete tag: %s (%s)", tag.Name, tag.ID))
slog.Debug(fmt.Sprintf("[DRY RUN] Would delete tag: %s (%s)", tag.Name, tag.ID))
return nil
}

Expand Down
7 changes: 5 additions & 2 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ variable "purge_retention_days" {
}

variable "purge_preserve_tag_patterns" {
description = "List of regex patterns for tags to preserve. By default, preserves semantic versioning tags."
description = "List of regex patterns for tags to preserve. By default, preserves semantic versioning tags and `latest` tags."
type = list(string)
default = ["^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"]
default = [
"^latest((-.+)?)$",
"^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"
]
}

variable "purge_schedule" {
Expand Down