2022-03-24 23:56:05 +01:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
import (
|
2022-03-25 12:40:13 +01:00
|
|
|
"git.ztn.sh/gwendolyn/docker-event-handler/events"
|
2022-03-25 12:17:05 +01:00
|
|
|
|
2022-03-24 23:56:05 +01:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
"text/template"
|
2022-03-25 12:17:05 +01:00
|
|
|
|
|
|
|
"gopkg.in/ini.v1"
|
2022-03-24 23:56:05 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
type Volume struct {
|
|
|
|
Action []string
|
|
|
|
Name []string
|
|
|
|
Driver []string
|
|
|
|
Destination []string
|
|
|
|
ID []string
|
|
|
|
Label map[string]*string
|
|
|
|
ContainerName []string
|
|
|
|
ContainerImage []string
|
|
|
|
ContainerID []string
|
|
|
|
ContainerHostname []string
|
|
|
|
ContainerLabel map[string]*string
|
|
|
|
Run *template.Template
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h Volume) Matches(event events.Event) bool {
|
|
|
|
e, ok := event.(events.Volume)
|
|
|
|
if !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if !stringListMatches(h.Action, e.Action) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if !stringListMatches(h.ID, e.ID) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if e.Volume == nil {
|
|
|
|
if len(h.Name) > 0 || len(h.Driver) > 0 || len(h.Label) > 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if !stringListMatches(h.Name, e.Volume.Name) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if !stringListMatches(h.Driver, e.Volume.Driver) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if !labelsMatch(h.Label, e.Volume.Labels) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if e.Destination == nil {
|
|
|
|
if len(h.Destination) > 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if !stringListMatches(h.Destination, *e.Destination) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if e.Container == nil {
|
|
|
|
if len(h.ContainerID) > 0 || len(h.ContainerName) > 0 || len(h.ContainerImage) > 0 || len(h.ContainerHostname) > 0 || len(h.ContainerLabel) > 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if !stringListMatches(h.ContainerID, e.Container.ID) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if !stringListMatches(h.ContainerName, e.Container.Name) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if !stringListMatches(h.ContainerImage, e.Container.Image) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if !stringListMatches(h.ContainerHostname, e.Container.Config.Hostname) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if !labelsMatch(h.ContainerLabel, e.Container.Config.Labels) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h Volume) Invoke(event events.Event) error {
|
|
|
|
e := event.(events.Volume) // enforce that the event is a volume event
|
|
|
|
return runTemplatedScript(h.Run, e)
|
|
|
|
}
|
|
|
|
|
|
|
|
func readVolumeFromConfig(section *ini.Section) (Volume, error) {
|
|
|
|
var handler Volume
|
|
|
|
var err error
|
|
|
|
handler.Label = make(map[string]*string)
|
|
|
|
handler.ContainerLabel = make(map[string]*string)
|
|
|
|
for _, key := range section.Keys() {
|
|
|
|
values := key.ValueWithShadows()
|
|
|
|
switch key.Name() {
|
|
|
|
case "Action":
|
|
|
|
handler.Action = values
|
|
|
|
break
|
|
|
|
case "Name":
|
|
|
|
handler.Name = values
|
|
|
|
break
|
|
|
|
case "ID":
|
|
|
|
handler.ID = values
|
|
|
|
break
|
|
|
|
case "Driver":
|
|
|
|
handler.Driver = values
|
|
|
|
break
|
|
|
|
case "Destination":
|
|
|
|
handler.Destination = values
|
|
|
|
break
|
|
|
|
case "Label":
|
|
|
|
for _, val := range values {
|
|
|
|
parts := strings.SplitN(val, "=", 2)
|
|
|
|
var k string
|
|
|
|
var v *string
|
|
|
|
if len(parts) == 2 {
|
|
|
|
k = parts[0]
|
|
|
|
v = &parts[1]
|
|
|
|
} else {
|
|
|
|
k = parts[0]
|
|
|
|
v = nil
|
|
|
|
}
|
|
|
|
handler.Label[k] = v
|
|
|
|
}
|
|
|
|
break
|
|
|
|
|
|
|
|
case "ContainerName":
|
|
|
|
handler.ContainerName = values
|
|
|
|
break
|
|
|
|
case "ContainerID":
|
|
|
|
handler.ContainerID = values
|
|
|
|
break
|
|
|
|
case "ContainerImage":
|
|
|
|
handler.ContainerImage = values
|
|
|
|
break
|
|
|
|
case "ContainerHostname":
|
|
|
|
handler.ContainerHostname = values
|
|
|
|
break
|
|
|
|
case "ContainerLabel":
|
|
|
|
for _, val := range values {
|
|
|
|
parts := strings.SplitN(val, "=", 2)
|
|
|
|
var k string
|
|
|
|
var v *string
|
|
|
|
if len(parts) == 2 {
|
|
|
|
k = parts[0]
|
|
|
|
v = &parts[1]
|
|
|
|
} else {
|
|
|
|
k = parts[0]
|
|
|
|
v = nil
|
|
|
|
}
|
|
|
|
handler.ContainerLabel[k] = v
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case "Run":
|
|
|
|
if len(values) > 1 {
|
|
|
|
return handler, errors.New(fmt.Sprintf("duplicate key %v in section %v", key.Name(), section.Name()))
|
|
|
|
}
|
|
|
|
handler.Run, err = template.New("Run").Parse(values[0])
|
|
|
|
if err != nil {
|
|
|
|
return handler, err
|
|
|
|
}
|
|
|
|
break
|
|
|
|
default:
|
|
|
|
return handler, errors.New(fmt.Sprintf("unknown key %v in section %v", key.Name(), section.Name()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return handler, nil
|
|
|
|
}
|