Skip to content
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

allow filtering by source annotation #354

Merged
merged 7 commits into from
Nov 9, 2017
Merged

allow filtering by source annotation #354

merged 7 commits into from
Nov 9, 2017

Conversation

khrisrichardson
Copy link
Contributor

In certain scenarios, there may be multiple ingress controllers running in the same Kubernetes cluster with different ingress classes (e.g. - ALB + Tectonic ingress), and it would be desirable to toggle which controllers' resources had their DNS records managed by external-dns. The intention of this PR is to manage that scenario via pattern matching on the ingress class annotation: kubernetes.io/ingress.class.

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Oct 9, 2017
@linki
Copy link
Member

linki commented Oct 10, 2017

@khrisrichardson Thanks for your contribution.

I would like to avoid tying ExternalDNS to a specific annotation that's used by another project. However, these two projects are related to each other so I'm not opposed to the idea.

Though, we could solve the issue more generic by allowing people to filter Ingresses (and Services etc.) by arbitrary annotation selectors. This way people could invoke ExternalDNS with:

$ ./external-dns --source=Ingress --source-annotation-filter=kubernetes.io/ingress.class=foo --provider=...

This would allow people to run ExternalDNS on a subset of Ingresses for any reason and wouldn't tie us to the particular ingress.class annotation.

We did the same thing in mate to work in combination with ExternalDNS: https://github.com/linki/mate#compatibility-with-other-controllers

I see, though, that ingress.class is a common case so it could justify a separate flag (like this PR).

Let me know what you think.

@khrisrichardson
Copy link
Contributor Author

Hi @linki. I had similar reservations about using a filter on an annotation outside the project's scope. I think we can make this generic pretty easily.

@khrisrichardson khrisrichardson changed the title allow filtering by ingress class allow filtering by source annotation Oct 10, 2017
main.go Outdated
FQDNTemplate: cfg.FQDNTemplate,
Compatibility: cfg.Compatibility,
PublishInternal: cfg.PublishInternal,
SourceAnnotationFilter: cfg.SourceAnnotationFilter,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's omit the Source prefix because we're already using the Config from the source package.

LogFormat string
MetricsAddress string
LogLevel string
SourceAnnotationFilter string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to maintain a cosistent ordering. Let's add this under/behind the source's namespace parameter. So, in all the structs, tests and kingpin definitionions.

@@ -139,6 +141,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("log-format", "The format in which log messages are printed (default: text, options: text, json)").Default(defaultConfig.LogFormat).EnumVar(&cfg.LogFormat, "text", "json")
app.Flag("metrics-address", "Specify where to serve the metrics and health check endpoint (default: :7979)").Default(defaultConfig.MetricsAddress).StringVar(&cfg.MetricsAddress)
app.Flag("log-level", "Set the level of logging. (default: info, options: panic, debug, info, warn, error, fatal").Default(defaultConfig.LogLevel).EnumVar(&cfg.LogLevel, allLogLevelsAsStrings()...)
app.Flag("source-annotation-filter", "Filter sources managed by external-dns via annotation regexp pattern (default: all sources)").Default(defaultConfig.SourceAnnotationFilter).StringVar(&cfg.SourceAnnotationFilter)
Copy link
Member

@linki linki Oct 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just use --annotation-filter. It currently fits better with --namespace which is also a filter on the source side. I think we won't have annotation filtering stuff on the provider side for a while.

log.Debugf("Skipping ingress %s/%s because '%s' annotation does not match pattern, found: %s, expected: %s",
ing.Namespace, ing.Name, annotation, string, pattern)
continue
}
Copy link
Member

@linki linki Oct 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend adopting this pattern: https://github.com/linki/chaoskube/blob/v0.6.0/chaoskube/chaoskube.go#L180-L199

With this you get all the matching functionality from Kubernetes itself for free, including matching multiple labels, checking for existence (--filter=foo) as well as exclusion (--filter=ingress.class!=nginx).

@khrisrichardson
Copy link
Contributor Author

@linki, are there any other changes you would propose following my latest updates. Do you think we should rename annotationFilter to annotationSelector?

@@ -70,6 +73,10 @@ func (sc *ingressSource) Endpoints() ([]*endpoint.Endpoint, error) {
if err != nil {
return nil, err
}
ingresses.Items, err = sc.filterByAnnotations(ingresses.Items, sc.annotationFilter)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you call a method of "sc", you should not pass sc.annotationFilter as parameter, but use it in the method from your receiver.

@@ -75,6 +78,10 @@ func (sc *serviceSource) Endpoints() ([]*endpoint.Endpoint, error) {
if err != nil {
return nil, err
}
services.Items, err = sc.filterByAnnotations(services.Items, sc.annotationFilter)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is the same case, passing sc.annotationFilter to a function receiver of sc.

@@ -148,6 +155,37 @@ func (sc *serviceSource) endpoints(svc *v1.Service) []*endpoint.Endpoint {
return endpoints
}

// filterByAnnotations filters a list of services by a given annotation selector.
func (sc *serviceSource) filterByAnnotations(services []v1.Service, annotationFilter string) ([]v1.Service, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there was no case to pass the filter as parameter, because it's already member of serviceSource.

@szuecs
Copy link
Contributor

szuecs commented Oct 28, 2017

For me this looks good. Only a tiny nitpick and we can merge it.
@linki @ideahitme

@linki
Copy link
Member

linki commented Oct 29, 2017

LGTM 👍

Thanks @khrisrichardson and @szuecs for the implementation and reviews.

@linki linki added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 29, 2017
@hjacobs
Copy link
Contributor

hjacobs commented Nov 8, 2017

Should we merge? Any reason not to?

@szuecs
Copy link
Contributor

szuecs commented Nov 9, 2017

please merge @hjacobs , I just don't have the right to do so

@szuecs
Copy link
Contributor

szuecs commented Nov 9, 2017

@ideahitme can you merge this please?

@ideahitme ideahitme merged commit b23765e into kubernetes-sigs:master Nov 9, 2017
@khrisrichardson khrisrichardson deleted the ingress-class-pattern branch November 27, 2017 17:51
ffledgling pushed a commit to ffledgling/external-dns that referenced this pull request Jan 18, 2018
* allow filtering by ingress class

* generic source annotation filter as opposed to ingress class filter

* rename and fix argument ordering, switch to label selector semantics

* remove redundant parameters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants