GithubHelp home page GithubHelp logo

canonical / traefik-route-k8s-operator Goto Github PK

View Code? Open in Web Editor NEW
0.0 7.0 3.0 220 KB

Configuration charm for traefik-k8s.

Home Page: https://charmhub.io/traefik-route-k8s

License: Apache License 2.0

Python 100.00%
kubernetes ingress juju juju-charm routing

traefik-route-k8s-operator's People

Contributors

ca-scribner avatar lucabello avatar mehdi-bendriss avatar mmkay avatar observability-noctua-bot avatar pietropasotti avatar rbarry82 avatar sed-i avatar simskij avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

traefik-route-k8s-operator's Issues

Traefik-route-k8s renders rules without `stripPrefix` middleware

Bug Description

The traefik-route-k8s doesn't generate rules with the stripPrefix middleware, while the "ingress-per-app" does so.
Is this intentional? Is that middleware not needed with ingress-per-unit?

An example rule rendered by

  • route charm:
http:
  routers:
    juju-prometheus-k8s-0-test-router:
      entryPoints:
      - web
      rule: Host(`prometheus-k8s-operator-0.prometheus-k8s-operator-endpoints.test.svc.cluster.local`)
      service: juju-prometheus-k8s-0-test-service
    juju-prometheus-k8s-0-test-router-tls:
      entryPoints:
      - websecure
      rule: Host(`prometheus-k8s-operator-0.prometheus-k8s-operator-endpoints.test.svc.cluster.local`)
      service: juju-prometheus-k8s-0-test-service
      tls:
        domains:
        - main: 10.64.140.43
          sans:
          - '*.10.64.140.43'
  services:
    juju-prometheus-k8s-0-test-service:
      loadBalancer:
        servers:
        - url: http://prometheus-k8s-operator-0.prometheus-k8s-operator-endpoints.test.svc.cluster.local:8080
  • ingress-per-app:
http:
  middlewares:
    juju-sidecar-noprefix-test-identity-platform-login-ui-operator:
      stripPrefix:
        forceSlash: false
        prefixes:
        - /test-identity-platform-login-ui-operator
  routers:
    juju-test-identity-platform-login-ui-operator-router:
      entryPoints:
      - web
      middlewares:
      - juju-sidecar-noprefix-test-identity-platform-login-ui-operator
      rule: PathPrefix(`/test-identity-platform-login-ui-operator`)
      service: juju-test-identity-platform-login-ui-operator-service
    juju-test-identity-platform-login-ui-operator-router-tls:
      entryPoints:
      - websecure
      rule: PathPrefix(`/test-identity-platform-login-ui-operator`)
      service: juju-test-identity-platform-login-ui-operator-service
      tls:
        domains:
        - main: 10.64.140.43
          sans:
          - '*.10.64.140.43'
  services:
    juju-test-identity-platform-login-ui-operator-service:
      loadBalancer:
        servers:
        - url: http://identity-platform-login-ui-operator-0.identity-platform-login-ui-operator-endpoints.test.svc.cluster.local:8080

To Reproduce

  1. juju deploy traefik-route-k8s root_url=...
  2. juju deploy traefik-k8s
  3. juju deploy prometheus-k8s
  4. juju relate traefik-route-k8s prometheus-k8s
  5. juju relate traefik-route-k8s traefik-k8s

Environment

n/a

Relevant log output

n/a

Additional context

No response

Emit `revoked` so users won't need to observe relation_departed

Currently, traefik_route only emits ready

def _on_relation_changed(self, event: RelationEvent):
if self.is_ready(event.relation):
# todo check data is valid here?
self._update_requirers_with_external_host()
self.on.ready.emit(event.relation)

IPU and IPA also emit revoked

It could be handy to have a revoked here as well so users could only observe self.ingress.revoked.

support path-only root url

If the root_url begins with /, we will fill in the host and port for you:

root_url="/baz/" will become: http://{external-hostname | loadbalancer ip}:{port}/baz/

This requires passing the host and port data from traefik to traefik-route, or passing the url template from Route to Traefik and the rendered url back to Route. (I guess the first is fine).

Should this charm be archived?

  • it looks like the charm isn't actively used by the community.
  • it contains a library that is used heavily (traefik_route_k8s but in combination with traefik-k8s-operator so it might be a better place to own this library - ref canonical/traefik-k8s-operator#379 )

It looks like we should consider archiving this charm and moving traefik_route_k8s library to traefik-k8s-operator.

[design] Avoid possible races

In directly-related Charm <--> Traefik scenarios, what happens is:

  1. Charm initiates by sharing some ingress data (name, model, port, host...)
  2. Traefik uses that data to render a config template, with which it configures Traefik to start routing for the remote units. After that it sends back to Charm the root url at which ingress has been made available.

However let's add Traefik Route to the picture (Route henceforth) and that complicates things:
The event timeline is as follows:

  1. Admin sets up Traefik, Route, and Charm and relates them.
  2. Admin configures Route.
  3. Charm shares its ingress data (name, model, port, host...)
  4. In Route:
    a. Given that Route is already configured, it knows what url should be sent back to Charm.
    b. It also knows what traefik config to send to Traefik.

PROBLEM: if at this point Route does both, there is a chance that the charm will believe it has ingress BEFORE Traefik has had the time to update its config and the service (or whatever it needs to do to actually start routing for that url).

Alternative design could be:
1-3. Stay the same

  1. Route sends config to Traefik.
  2. Traefik sends back an OK message to inform Route that that unit is being routed to.
  3. Route receives the OK and sends to Charm the url it already knew after 3.

traefik-route errors out on startup

Bug Description

The charm errors out when deployed with grafana (e.g. in cos-lite) because traefik-route does not guard against 'external-host' possibly being None

image

image

image

To Reproduce

juju deploy cos-lite --trust

Environment

juju 3.1-beta1 on local microk8s cluster.

Relevant log output

File "/var/lib/juju/agents/unit-traefik-0/charm/venv/ops/framework.py", line 316, in emit    
    framework._emit(event)                                                                     
  File "/var/lib/juju/agents/unit-traefik-0/charm/venv/ops/framework.py", line 784, in _emit   
    self._reemit(event_path)                                                                   
  File "/var/lib/juju/agents/unit-traefik-0/charm/venv/ops/framework.py", line 857, in _reemit 
    custom_handler(event)                                                                      
  File "/var/lib/juju/agents/unit-traefik-0/charm/lib/charms/traefik_route_k8s/v0/traefik_route
.py", line 166, in _on_relation_changed                                                        
    self._update_requirers_with_external_host()                                                
  File "/var/lib/juju/agents/unit-traefik-0/charm/lib/charms/traefik_route_k8s/v0/traefik_route
.py", line 175, in _update_requirers_with_external_host                                        
    relation.data[self.charm.app]["external_host"] = self._stored.external_host                
  File "/var/lib/juju/agents/unit-traefik-0/charm/venv/ops/model.py", line 945, in __setitem__ 
    raise RelationDataError('relation data values must be strings')                            


### Additional context

_No response_

Validate `root_url` against `rule` if both are provided

Investigate if it's at all possible to test from within the charm if the root_url is valid in combination with a rule.
E.g. can we fire a get request to the url and see if it is routed correctly? Or at least if it responds?

Provider seems to have redundant logic, cloned from the requirer

  • _stored gets overwritten every loop iteration.
  • Why the provider needs to extract this from relation data? Seems like this was cloned from the requirer. Not sure.

for relation in self._charm.model.relations[self._relation_name]:
if not relation.app:
self._stored.external_host = ""
self._stored.scheme = ""
return
external_host = relation.data[relation.app].get("external_host", "")
self._stored.external_host = external_host or self._stored.external_host
scheme = relation.data[relation.app].get("scheme", "")
self._stored.scheme = scheme or self._stored.scheme

Originally posted in canonical/traefik-k8s-operator#234 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.