Skip to content

Commit

Permalink
impl: filtering
Browse files Browse the repository at this point in the history
based off of mcuadros#212
  • Loading branch information
TheDevMinerTV committed Mar 28, 2023
1 parent 7027f39 commit 59c27f4
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 25 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,29 @@ docker run -it --rm \
nginx
```

**Ofelia** reads labels of all Docker containers for configuration by default. To apply on a subset of containers only, use the flag `--docker-filter` (or `-f`) similar to the [filtering for `docker ps`](https://docs.docker.com/engine/reference/commandline/ps/#filter). E.g. to apply to current docker compose project only using `label` filter:

```yaml
version: "3"
services:
ofelia:
image: mcuadros/ofelia:latest
depends_on:
- nginx
command: daemon --docker -f label=com.docker.compose.project=${COMPOSE_PROJECT_NAME}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
ofelia.job-local.my-test-job.schedule: "@every 5s"
ofelia.job-local.my-test-job.command: "date"
nginx:
image: nginx
labels:
ofelia.enabled: "true"
ofelia.job-exec.datecron.schedule: "@every 5s"
ofelia.job-exec.datecron.command: "uname -a"
```

### Dynamic Docker configuration

You can start Ofelia in its own container or on the host itself, and it will magically pick up any container that starts, stops or is modified on the fly.
Expand Down
32 changes: 21 additions & 11 deletions cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Config struct {
RunJobs map[string]*RunJobConfig `gcfg:"job-run" mapstructure:"job-run,squash"`
ServiceJobs map[string]*RunServiceConfig `gcfg:"job-service-run" mapstructure:"job-service-run,squash"`
LocalJobs map[string]*LocalJobConfig `gcfg:"job-local" mapstructure:"job-local,squash"`
Docker DockerConfig
sh *core.Scheduler
dockerHandler *DockerHandler
logger core.Logger
Expand Down Expand Up @@ -67,24 +68,29 @@ func (c *Config) InitializeApp() error {
c.buildSchedulerMiddlewares(c.sh)

var err error
c.dockerHandler, err = NewDockerHandler(c, c.logger)
c.dockerHandler, err = NewDockerHandler(c, c.logger, c.Docker.Filters)
if err != nil {
return err
}

// In order to support non dynamic job types such as Local or Run using labels
// lets parse the labels and merge the job lists
dockerLabels, err := c.dockerHandler.GetDockerLabels()
var parsedLabelConfig Config
parsedLabelConfig.buildFromDockerLabels(dockerLabels)
for name, j := range parsedLabelConfig.RunJobs {
c.RunJobs[name] = j
}
for name, j := range parsedLabelConfig.LocalJobs {
c.LocalJobs[name] = j
}
for name, j := range parsedLabelConfig.ServiceJobs {
c.ServiceJobs[name] = j
if err == nil {
parsedLabelConfig := Config{}

parsedLabelConfig.buildFromDockerLabels(dockerLabels)
for name, j := range parsedLabelConfig.RunJobs {
c.RunJobs[name] = j
}

for name, j := range parsedLabelConfig.LocalJobs {
c.LocalJobs[name] = j
}

for name, j := range parsedLabelConfig.ServiceJobs {
c.ServiceJobs[name] = j
}
}

for name, j := range c.ExecJobs {
Expand Down Expand Up @@ -297,3 +303,7 @@ func (c *RunServiceConfig) buildMiddlewares() {
c.RunServiceJob.Use(middlewares.NewSave(&c.SaveConfig))
c.RunServiceJob.Use(middlewares.NewMail(&c.MailConfig))
}

type DockerConfig struct {
Filters []string `mapstructure:"filters"`
}
12 changes: 7 additions & 5 deletions cli/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import (

// DaemonCommand daemon process
type DaemonCommand struct {
ConfigFile string `long:"config" description:"configuration file" default:"/etc/ofelia.conf"`
scheduler *core.Scheduler
signals chan os.Signal
done chan bool
Logger core.Logger
ConfigFile string `long:"config" description:"configuration file" default:"/etc/ofelia.conf"`
DockerFilters []string `short:"f" long:"docker-filter" description:"Filter for docker containers"`

scheduler *core.Scheduler
signals chan os.Signal
done chan bool
Logger core.Logger
}

// Execute runs the daemon
Expand Down
37 changes: 28 additions & 9 deletions cli/docker_config_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
var ErrNoContainerWithOfeliaEnabled = errors.New("Couldn't find containers with label 'ofelia.enabled=true'")

type DockerHandler struct {
filters []string
dockerClient *docker.Client
notifier dockerLabelsUpdate
logger core.Logger
Expand All @@ -35,18 +36,21 @@ func (c *DockerHandler) buildDockerClient() (*docker.Client, error) {
return d, nil
}

func NewDockerHandler(notifier dockerLabelsUpdate, logger core.Logger) (*DockerHandler, error) {
c := &DockerHandler{}
func NewDockerHandler(notifier dockerLabelsUpdate, logger core.Logger, filters []string) (*DockerHandler, error) {
c := &DockerHandler{
filters: filters,
notifier: notifier,
logger: logger,
}

var err error
c.dockerClient, err = c.buildDockerClient()
c.notifier = notifier
c.logger = logger
if err != nil {
return nil, err
}

// Do a sanity check on docker
_, err = c.dockerClient.Info()
if err != nil {
if _, err = c.dockerClient.Info(); err != nil {
return nil, err
}

Expand All @@ -71,10 +75,25 @@ func (c *DockerHandler) watch() {
}

func (c *DockerHandler) GetDockerLabels() (map[string]map[string]string, error) {
filters := map[string][]string{
"label": {requiredLabelFilter},
}
for _, f := range c.filters {
parts := strings.SplitN(f, "=", 2)
if len(parts) != 2 {
return nil, errors.New("invalid docker filter: " + f)
}
key, value := parts[0], parts[1]
values, ok := filters[key]
if ok {
filters[key] = append(values, value)
} else {
filters[key] = []string{value}
}
}

conts, err := c.dockerClient.ListContainers(docker.ListContainersOptions{
Filters: map[string][]string{
"label": {requiredLabelFilter},
},
Filters: filters,
})
if err != nil {
return nil, err
Expand Down

0 comments on commit 59c27f4

Please sign in to comment.