blob: 221f16e999c308ec4ea29d1bf75795b5983b985f [file]
package watcher
import (
"fmt"
"log"
"os"
"strings"
"github.com/apache/trafficserver-ingress-controller/endpoint"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
// AtsCacheHandler handles ATSCachingPolicy events
type AtsCacheHandler struct {
ResourceName string
Ep *endpoint.Endpoint
CachePath string
}
// Constructor
func NewAtsCacheHandler(resource string, ep *endpoint.Endpoint, path string) *AtsCacheHandler {
log.Println("ATS Cache Constructor initialized ")
return &AtsCacheHandler{ResourceName: resource, Ep: ep, CachePath: path}
}
// Update ATS config
func (h *AtsCacheHandler) UpdateAts() {
log.Println("Update ATS called")
msg, err := h.Ep.ATSManager.CacheSet()
if err != nil {
log.Println("UpdateAts error:", err)
} else {
log.Println("ATS updated:", msg)
}
}
// Add handles creation of ATSCachingPolicy resources
func (h *AtsCacheHandler) Add(obj interface{}) {
u := obj.(*unstructured.Unstructured)
log.Printf("[ADD] ATSCachingPolicy: %s/%s", u.GetNamespace(), u.GetName())
rules, found, err := unstructured.NestedSlice(u.Object, "spec", "rules")
if err != nil || !found {
log.Printf("Add: rules not found or error occurred: %v", err)
return
}
var lines []string
for _, rule := range rules {
ruleMap, ok := rule.(map[string]interface{})
if !ok {
continue
}
primary, found, _ := unstructured.NestedMap(ruleMap, "primarySpecifier")
if !found {
continue
}
typeval, ok1 := primary["type"].(string)
pattern, ok2 := primary["pattern"].(string)
action, ok3 := ruleMap["action"].(string)
ttl, ok4 := ruleMap["ttl"].(string)
if !ok1 || !ok2 || !ok3 || !ok4 {
continue
}
if action == "cache" {
line := fmt.Sprintf("%s=%s ttl-in-cache=%s", typeval, pattern, ttl)
lines = append(lines, line)
}
}
configPath := h.CachePath
f, err := os.OpenFile(configPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Printf("Add: Failed to open cache.config: %v", err)
return
}
defer func() { _ = f.Close() }()
for _, line := range lines {
if _, err := f.WriteString(line + "\n"); err != nil {
log.Printf("Add: Failed to write line to cache.config: %v", err)
}
}
h.UpdateAts()
}
// Update handles updates to ATSCachingPolicy resources
func (h *AtsCacheHandler) Update(oldObj, newObj interface{}) {
newU := newObj.(*unstructured.Unstructured)
log.Printf("[UPDATE] ATSCachingPolicy: %s/%s", newU.GetNamespace(), newU.GetName())
newRules, found, err := unstructured.NestedSlice(newU.Object, "spec", "rules")
if err != nil || !found {
log.Printf("Update: rules not found or error occurred: %v", err)
return
}
configPath := h.CachePath
existingData, err := os.ReadFile(configPath)
if err != nil {
log.Printf("Update: Failed to read cache.config: %v", err)
return
}
lines := strings.Split(string(existingData), "\n")
for _, rule := range newRules {
ruleMap, ok := rule.(map[string]interface{})
if !ok {
continue
}
primary, found, _ := unstructured.NestedMap(ruleMap, "primarySpecifier")
if !found {
continue
}
typeval, ok1 := primary["type"].(string)
pattern, ok2 := primary["pattern"].(string)
action, ok3 := ruleMap["action"].(string)
newTTL, ok4 := ruleMap["ttl"].(string)
if !ok1 || !ok2 || !ok3 || !ok4 || action != "cache" {
continue
}
for i, line := range lines {
if strings.Contains(line, fmt.Sprintf("%s=%s", typeval, pattern)) {
lines[i] = fmt.Sprintf("%s=%s ttl-in-cache=%s", typeval, pattern, newTTL)
break
}
}
}
err = os.WriteFile(configPath, []byte(strings.Join(lines, "\n")), 0644)
if err != nil {
log.Printf("Update: Failed to write updated cache.config: %v", err)
}
h.UpdateAts()
}
// Delete handles deletion of ATSCachingPolicy resources
func (h *AtsCacheHandler) Delete(obj interface{}) {
u := obj.(*unstructured.Unstructured)
log.Printf("[DELETE] ATSCachingPolicy: %s/%s", u.GetNamespace(), u.GetName())
configPath := h.CachePath
existingData, err := os.ReadFile(configPath)
if err != nil {
log.Printf("Delete: Failed to read cache.config: %v", err)
return
}
lines := strings.Split(string(existingData), "\n")
rules, found, err := unstructured.NestedSlice(u.Object, "spec", "rules")
if err != nil || !found {
log.Printf("Delete: rules not found or error occurred: %v", err)
return
}
patternsToDelete := make(map[string]string)
for _, rule := range rules {
ruleMap, ok := rule.(map[string]interface{})
if !ok {
continue
}
primary, found, _ := unstructured.NestedMap(ruleMap, "primarySpecifier")
if !found {
continue
}
typeval, ok1 := primary["type"].(string)
pattern, ok2 := primary["pattern"].(string)
action, ok3 := ruleMap["action"].(string)
if ok1 && ok2 && ok3 && action == "cache" {
patternsToDelete[typeval] = pattern
}
}
var updatedLines []string
for _, line := range lines {
shouldDelete := false
for typeval, pattern := range patternsToDelete {
if strings.Contains(line, fmt.Sprintf("%s=%s", typeval, pattern)) {
shouldDelete = true
break
}
}
if !shouldDelete {
updatedLines = append(updatedLines, line)
}
}
err = os.WriteFile(configPath, []byte(strings.Join(updatedLines, "\n")), 0644)
if err != nil {
log.Printf("Delete: Failed to write updated cache.config: %v", err)
}
h.UpdateAts()
}