diff --git a/_traefik3_labels.yml.jinja b/_traefik3_labels.yml.jinja new file mode 100644 index 00000000..1d24d183 --- /dev/null +++ b/_traefik3_labels.yml.jinja @@ -0,0 +1,108 @@ +{%- import "_macros.jinja" as macros -%} +{# Echo all domains of a group, in a Traefik rule #} +{%- macro domains_rule(hosts, path_prefixes=(), paths=()) -%} + Host(`{{ hosts | join("` || Host(`") }}`) + {%- if path_prefixes or paths -%} + {{" "}}&& ( + {%- if path_prefixes -%} + {{ path_prefix_rule(path_prefixes) }} + {%- if paths %} || {% endif %} + {%- endif %} + {%- if paths -%} + {{ path_rule(paths) }} + {%- endif -%} + ) + {%- endif %} +{%- endmacro %} + +{# Echo all path prefixes in a Traefik rule #} +{%- macro path_prefix_rule(path_prefixes) -%} + {%- for path in path_prefixes -%} + {%- if path.endswith("/") -%} + PathPrefix(`{{ path }}`) + {%- else -%} + PathPrefix(`{{ path }}`) || Path(`{{ path }}`) + {%- endif -%} + {%- if not loop.last %} || {% endif %} + {%- endfor %} +{%- endmacro %} + +{# Echo all paths in a Traefik rule #} +{%- macro path_rule(paths) -%} + {%- for path in paths -%} + Path(`{{ path }}`) + {%- if not loop.last %} || {% endif %} + {%- endfor %} +{%- endmacro %} + +{%- macro odoo(domain_groups_list, paths_without_crawlers, odoo_version, traefik_version) %} + traefik.domain: {{ macros.first_main_domain(domain_groups_list)|tojson }} + {%- call(domain_group) macros.domains_loop_grouped(domain_groups_list) %} + + {#- Route redirections #} + {%- if domain_group.redirect_to %} + traefik.alt-{{ domain_group.loop.index0 }}.frontend.redirect.regex: ^(.*)://([^/]+)/(.*)$$ + traefik.alt-{{ domain_group.loop.index0 }}.frontend.redirect.replacement: $$1://{{ domain_group.redirect_to }}/$$3 + {{- + router( + prefix="alt", + index0=domain_group.loop.index0, + rule=domains_rule(domain_group.hosts, domain_group.path_prefixes), + entrypoints=domain_group.entrypoints, + ) + }} + {%- else %} + + {#- Forbidden crawler routers #} + {%- if traefik_version < 3%} + {%- if paths_without_crawlers and not domain_group.path_prefixes %} + traefik.forbiddenCrawlers-{{ domain_group.loop.index0 }}.frontend.headers.customResponseHeaders: + "X-Robots-Tag:noindex, nofollow" + {{- + router( + prefix="forbiddenCrawlers", + index0=domain_group.loop.index0, + rule=domains_rule(domain_group.hosts, paths_without_crawlers), + entrypoints=domain_group.entrypoints, + ) + }} + {%- endif %} + {%- endif %} + + {#- Normal routers #} + {%- if paths_without_crawlers != ["/"] or domain_group.path_prefixes %} + {{- + router( + prefix="main", + index0=domain_group.loop.index0, + rule=domains_rule(domain_group.hosts, domain_group.path_prefixes), + entrypoints=domain_group.entrypoints, + ) + }} + {%- endif %} + {%- if not domain_group.path_prefixes %} + {%- set longpolling_route = "/longpolling/" if odoo_version < 16 else "/websocket" -%} + {{- + router( + prefix="longpolling", + index0=domain_group.loop.index0, + rule=domains_rule(domain_group.hosts, [longpolling_route]), + entrypoints=domain_group.entrypoints, + port=8072, + ) + }} + {%- endif %} + {%- endif %} + {%- endcall %} +{%- endmacro %} +{#- Basic labels for a single router #} +{%- macro router(prefix, index0, rule, entrypoints=(), port=none) %} + traefik.{{ prefix }}-{{ index0 }}.frontend.rule: {{ rule }} + {%- if entrypoints %} + traefik.{{ prefix }}-{{ index0 }}.frontend.entryPoints: + {{ entrypoints|sort|join(",") }} + {%- endif %} + {%- if port %} + traefik.{{ prefix }}-{{ index0 }}.port: {{ port }} + {%- endif %} +{%- endmacro %} diff --git a/copier.yml b/copier.yml index 3bfd7b6f..42491ce1 100644 --- a/copier.yml +++ b/copier.yml @@ -125,6 +125,17 @@ odoo_proxy: Which proxy will you use to deploy odoo? +traefik_version: + default: 3 + type: int + when: &odoo_proxy_specific "{{ odoo_proxy == 'traefik' }}" + help: >- + Indicate traefik version + choices: + - 1 + - 2 + - 3 + odoo_initial_lang: default: en_US type: str diff --git a/docs/scaffolding2copier.sh b/docs/scaffolding2copier.sh index b74bc4cb..084d0396 100755 --- a/docs/scaffolding2copier.sh +++ b/docs/scaffolding2copier.sh @@ -33,6 +33,7 @@ copier $CUSTOM_COPIER_FLAGS \ -d smtp_relay_user="$SMTP_REAL_RELAY_USER" \ -d smtp_canonical_default="$SMTP_REAL_NON_CANONICAL_DEFAULT" \ -d smtp_canonical_domains="[$SMTP_REAL_CANONICAL_DOMAINS]" \ + -d traefik_version="$TRAEFIK_VERSION" \ -d backup_dst="boto3+s3://$BACKUP_S3_BUCKET" \ -d backup_email_from="$BACKUP_EMAIL_FROM" \ -d backup_email_to="$BACKUP_EMAIL_TO" \ diff --git a/prod.yaml.jinja b/prod.yaml.jinja index d8147be5..013544a6 100644 --- a/prod.yaml.jinja +++ b/prod.yaml.jinja @@ -1,6 +1,8 @@ {%- import "_macros.jinja" as macros -%} {%- import "_traefik1_labels.yml.jinja" as traefik1_labels -%} {%- import "_traefik2_labels.yml.jinja" as traefik2_labels -%} +{%- import "_traefik3_labels.yml.jinja" as traefik3_labels -%} + {%- set _key = traefik2_labels.key(project_name, odoo_version, "prod") -%} version: "2.4" @@ -37,7 +39,7 @@ services: doodba.domain.main: {{ macros.first_main_domain(domains_prod)|tojson }} {%- if odoo_proxy == "traefik" and domains_prod %} traefik.enable: "true" - {{- traefik1_labels.odoo(domains_prod, paths_without_crawlers, odoo_version) }} + {{- (traefik3_labels.odoo(domains_prod, paths_without_crawlers, odoo_version, traefik_version) if traefik_version == 3 else traefik1_labels.odoo(domains_prod, paths_without_crawlers, odoo_version)) }} {{- traefik2_labels.common_middlewares(_key, cidr_whitelist) }} {{- traefik2_labels.odoo( domains_prod, diff --git a/test.yaml.jinja b/test.yaml.jinja index 3c746f59..f45a063c 100644 --- a/test.yaml.jinja +++ b/test.yaml.jinja @@ -1,6 +1,7 @@ {%- import "_macros.jinja" as macros -%} {%- import "_traefik1_labels.yml.jinja" as traefik1_labels -%} {%- import "_traefik2_labels.yml.jinja" as traefik2_labels -%} +{%- import "_traefik3_labels.yml.jinja" as traefik3_labels -%} {%- set _key = traefik2_labels.key(project_name, odoo_version, "test") -%} version: "2.4"