Skip to content
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
13 changes: 13 additions & 0 deletions provider-integration/im2/pkg/config/00_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,18 @@ type ProviderBranding struct {
Sections []ProviderBrandingSection `yaml:"sections"`
ProductDescription []ProviderBrandingProductDescription `yaml:"productDescription"`
}
type JobAuditLog struct {
RetentionPeriodInDays int `yaml:"retentionPeriodInDays"`
}

type ProviderConfiguration struct {
Id string

ProviderBranding ProviderBranding `yaml:"providerBranding"`
ProviderBrandingImageAbsolutePath map[string]string

JobAuditLog JobAuditLog `yaml:"jobAuditLog"`

Hosts struct {
UCloud HostInfo
Self HostInfo
Expand Down Expand Up @@ -395,6 +401,13 @@ func parseProvider(filePath string, provider *yaml.Node) (bool, ProviderConfigur
if providerBranding != nil {
populateProviderBranding(&cfg, filePath, providerBranding)
}

// Job audit log section
jobAuditLog, _ := cfgutil.GetChildOrNil(filePath, provider, "jobAuditLog")
if jobAuditLog != nil {
cfgutil.Decode(filePath, jobAuditLog, &cfg.JobAuditLog, &success)
}

// Hosts section
hosts := cfgutil.RequireChild(filePath, provider, "hosts", &success)
ucloudHost := cfgutil.RequireChild(filePath, hosts, "ucloud", &success)
Expand Down
1 change: 1 addition & 0 deletions provider-integration/im2/pkg/controller/00_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func Init(mux *http.ServeMux) {
initTasks()
initSshKeys()
initProviderBranding()
initJobAuditLog()

initLiveness()
if RunsServerCode() {
Expand Down
96 changes: 96 additions & 0 deletions provider-integration/im2/pkg/controller/job_audit_log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package controller

import (
"os"
"path/filepath"
"regexp"
"time"

"ucloud.dk/pkg/config"
"ucloud.dk/shared/pkg/log"
)

var jobAuditFileRegex = regexp.MustCompile(`^audit-(\d+)-(\d{4}-\d{2}-\d{2})\.jsonl$`)

func initJobAuditLog() {
k8sCfg := config.Services.Kubernetes()
if k8sCfg == nil {
log.Error("Job audit log server failed to get Kubernetes config")
return
}
jobAuditLogFolder := filepath.Join(k8sCfg.FileSystem.MountPoint, "audit")
retentionDays := config.Provider.JobAuditLog.RetentionPeriodInDays
go func() {
cleanupLogs(jobAuditLogFolder, retentionDays) // run once at startup

ticker := time.NewTicker(4 * time.Hour)
defer ticker.Stop()

for range ticker.C {
cleanupLogs(jobAuditLogFolder, retentionDays)
}
}()
}

func cleanupLogs(jobAuditLogFolder string, retentionDays int) {
cutoff := time.Now().AddDate(0, 0, -retentionDays)
today := time.Now().Format("2006-01-02")

walkErr := filepath.WalkDir(jobAuditLogFolder, func(path string, d os.DirEntry, err error) error {
if err != nil {
log.Error("Walk error: %s", err)
return nil
}
// Only process files
if !d.IsDir() {
name := d.Name()
matches := jobAuditFileRegex.FindStringSubmatch(name)
if matches == nil {
return nil
}

dateStr := matches[2]

if dateStr == today {
return nil
}

fileDate, err := time.Parse("2006-01-02", dateStr)
if err != nil {
return nil
}

if fileDate.Before(cutoff) {
err := os.Remove(path)
if err != nil {
log.Error("Could not remove file: %s", err)
} else {
log.Info("Removed audit log file: %s, since it is older than %d days", path, retentionDays)
}
}

return nil
}
// After walking a directory, check if it's empty (skip root)
if path == jobAuditLogFolder {
return nil
}

entries, err := os.ReadDir(path)
if err != nil {
return nil
}

// Delete the child folder if it is empty
if len(entries) == 0 {
err := os.Remove(path)
if err == nil {
log.Info("Removed empty audit log folder: %s", path)
}
}
return nil
})
if walkErr != nil {
log.Error("Error cleaning up job audit logs: %s", walkErr)
}
}