feat(go-traefik-certmanager): initial commit
This commit is contained in:
parent
913eaceaa4
commit
e2101672f8
13 changed files with 809 additions and 0 deletions
41
.woodpecker/.build.yaml
Normal file
41
.woodpecker/.build.yaml
Normal file
|
@ -0,0 +1,41 @@
|
|||
steps:
|
||||
- name: docker
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
registry: git.ar21.de
|
||||
username:
|
||||
from_secret: REGISTRY_USER
|
||||
password:
|
||||
from_secret: REGISTRY_PASS
|
||||
repo: git.ar21.de/yolokube/go-traefik-certmanager
|
||||
platforms:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
tags:
|
||||
- latest
|
||||
- ${CI_PIPELINE_NUMBER}
|
||||
when:
|
||||
- branch: main
|
||||
event: [push, manual]
|
||||
- name: docker-staging
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
registry: git.ar21.de
|
||||
username:
|
||||
from_secret: REGISTRY_USER
|
||||
password:
|
||||
from_secret: REGISTRY_PASS
|
||||
repo: git.ar21.de/yolokube/go-traefik-certmanager
|
||||
platforms:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
tags:
|
||||
- staging
|
||||
- staging-${CI_PIPELINE_NUMBER}
|
||||
dry_run: true
|
||||
when:
|
||||
- branch:
|
||||
exclude: main
|
||||
event: [push, manual]
|
||||
depends_on:
|
||||
- lint
|
57
.woodpecker/.deploy.yaml
Normal file
57
.woodpecker/.deploy.yaml
Normal file
|
@ -0,0 +1,57 @@
|
|||
skip_clone: true
|
||||
steps:
|
||||
- name: bump tag in deployment-repo (prod)
|
||||
image: git.ar21.de/aaron/kustomize-ci
|
||||
commands:
|
||||
- git clone https://git.ar21.de/yolokube/core-deployments.git deployment-repo
|
||||
- cd deployment-repo/traefik-certmanager/overlay
|
||||
- kustomize edit set image git.ar21.de/yolokube/go-traefik-certmanager=git.ar21.de/yolokube/go-traefik-certmanager:${CI_PIPELINE_NUMBER}
|
||||
when:
|
||||
- branch: main
|
||||
event: [push, manual]
|
||||
- name: push new tag to deployment-repo (prod)
|
||||
image: appleboy/drone-git-push
|
||||
settings:
|
||||
branch: "${CI_PIPELINE_NUMBER}_traefik-certmanager_prod"
|
||||
remote: ssh://git@git.ar21.de:2222/yolokube/core-deployments.git
|
||||
path: deployment-repo
|
||||
force: false
|
||||
commit: true
|
||||
commit_message: "traefik-certmanager: update image tag to ${CI_PIPELINE_NUMBER} (done automagically via Woodpecker pipeline)"
|
||||
ssh_key:
|
||||
from_secret: FORGEJO_SSH_KEY
|
||||
when:
|
||||
- branch: main
|
||||
event: [push, manual]
|
||||
- name: create pull request (prod)
|
||||
image: git.ar21.de/tom/push-message-randomizer:latest
|
||||
pull: true
|
||||
settings:
|
||||
gitea_address: https://git.ar21.de
|
||||
gitea_token:
|
||||
from_secret: FORGEJO_API
|
||||
owner: ${CI_REPO_OWNER}
|
||||
repo: core-deployments
|
||||
branch: "${CI_PIPELINE_NUMBER}_traefik-certmanager_prod"
|
||||
base_branch: main
|
||||
pr_title: "traefik-certmanager: update image tag to ${CI_PIPELINE_NUMBER}"
|
||||
pr_body: |
|
||||
### ℹ traefik-certmanager image update
|
||||
|
||||
{- random-pr-message -}
|
||||
|
||||
### Configuration
|
||||
|
||||
📅 **Schedule**: Branch creation - At any time, Automerge - At any time.
|
||||
|
||||
🚦 **Automerge**: Enabled.
|
||||
skip_on_missing_branch: true
|
||||
close_pr_if_empty: true
|
||||
delete_branch_if_pr_empty: true
|
||||
merge_when_checks_succeed: true
|
||||
delete_branch_after_merge: true
|
||||
when:
|
||||
- branch: main
|
||||
event: [push, manual]
|
||||
depends_on:
|
||||
- build
|
20
.woodpecker/.lint.yaml
Normal file
20
.woodpecker/.lint.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
steps:
|
||||
- name: gofmt
|
||||
image: golang:1.23.5
|
||||
commands:
|
||||
- gofmt -l -s .
|
||||
when:
|
||||
- event: [push, manual]
|
||||
- name: vuln-check
|
||||
image: golang:1.23.5
|
||||
commands:
|
||||
- go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||
- govulncheck ./...
|
||||
when:
|
||||
- event: [push, manual]
|
||||
- name: golangci-linter
|
||||
image: golangci/golangci-lint:v1.63.4
|
||||
commands:
|
||||
- golangci-lint run ./...
|
||||
when:
|
||||
- event: [push, manual]
|
39
go.mod
Normal file
39
go.mod
Normal file
|
@ -0,0 +1,39 @@
|
|||
module git.ar21.de/yolokube/go-traefik-certmanager
|
||||
|
||||
go 1.23.4
|
||||
|
||||
require (
|
||||
github.com/alecthomas/kong v1.6.0
|
||||
github.com/cert-manager/cert-manager v1.16.2
|
||||
k8s.io/api v0.32.0
|
||||
k8s.io/apimachinery v0.32.0
|
||||
k8s.io/client-go v0.32.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/term v0.25.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.31.1 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
|
||||
sigs.k8s.io/gateway-api v1.1.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
146
go.sum
Normal file
146
go.sum
Normal file
|
@ -0,0 +1,146 @@
|
|||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/kong v1.6.0 h1:mwOzbdMR7uv2vul9J0FU3GYxE7ls/iX1ieMg5WIM6gE=
|
||||
github.com/alecthomas/kong v1.6.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/cert-manager/cert-manager v1.16.2 h1:c9UU2E+8XWGruyvC/mdpc1wuLddtgmNr8foKdP7a8Jg=
|
||||
github.com/cert-manager/cert-manager v1.16.2/go.mod h1:MfLVTL45hFZsqmaT1O0+b2ugaNNQQZttSFV9hASHUb0=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
|
||||
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
|
||||
k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40=
|
||||
k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ=
|
||||
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
|
||||
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
||||
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
|
||||
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
|
||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/gateway-api v1.1.0 h1:DsLDXCi6jR+Xz8/xd0Z1PYl2Pn0TyaFMOPPZIj4inDM=
|
||||
sigs.k8s.io/gateway-api v1.1.0/go.mod h1:ZH4lHrL2sDi0FHZ9jjneb8kKnGzFWyrTya35sWUTrRs=
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
|
||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 h1:MdmvkGuXi/8io6ixD5wud3vOLwc1rj0aNqRlpuvjmwA=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.2/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
36
internal/cmd/cli.go
Normal file
36
internal/cmd/cli.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"git.ar21.de/yolokube/go-traefik-certmanager/internal/config"
|
||||
"github.com/alecthomas/kong"
|
||||
)
|
||||
|
||||
//nolint:lll // ignore line length
|
||||
type CLI struct {
|
||||
CertIssuerName string `name:"cert-issuer-name" env:"CERT_ISSUER_NAME" help:"Name for the certificate issuer" default:"${default_cert_issuer_name}"`
|
||||
CertIssuerKind string `name:"cert-issuer-kind" env:"CERT_ISSUER_KIND" help:"Kind for the certificate issuer" default:"${default_cert_issuer_kind}"`
|
||||
CertCleanup bool `name:"cert-cleanup" env:"CERT_CLEANUP" help:"Delete outdated / removed certificates" default:"${default_cert_cleanup}"`
|
||||
PatchSecretName bool `name:"patch-secret-name" env:"PATCH_SECRET_NAME" help:"Adjust secret names" default:"${default_patch_secret_name}"`
|
||||
}
|
||||
|
||||
func (c *CLI) Parse() *config.AppSettings {
|
||||
_ = kong.Parse(
|
||||
c,
|
||||
kong.Vars{
|
||||
"default_cert_issuer_name": "letsencrypt",
|
||||
"default_cert_issuer_kind": "ClusterIssuer",
|
||||
"default_cert_cleanup": "false",
|
||||
"default_patch_secret_name": "false",
|
||||
},
|
||||
kong.Name("go-traefik-certmanager"),
|
||||
kong.Description("🚀 Start a simple service to sync certificates for traefik CRs"),
|
||||
kong.UsageOnError(),
|
||||
)
|
||||
|
||||
return &config.AppSettings{
|
||||
CertIssuerName: c.CertIssuerName,
|
||||
CertIssuerKind: c.CertIssuerKind,
|
||||
CertCleanup: c.CertCleanup,
|
||||
PatchSecretName: c.PatchSecretName,
|
||||
}
|
||||
}
|
8
internal/config/config.go
Normal file
8
internal/config/config.go
Normal file
|
@ -0,0 +1,8 @@
|
|||
package config
|
||||
|
||||
type AppSettings struct {
|
||||
CertIssuerName string
|
||||
CertIssuerKind string
|
||||
CertCleanup bool
|
||||
PatchSecretName bool
|
||||
}
|
51
main.go
Normal file
51
main.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"git.ar21.de/yolokube/go-traefik-certmanager/internal/cmd"
|
||||
"git.ar21.de/yolokube/go-traefik-certmanager/pkg/certmanager"
|
||||
"git.ar21.de/yolokube/go-traefik-certmanager/pkg/ingressroute"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cli := cmd.CLI{}
|
||||
appSettings := cli.Parse()
|
||||
|
||||
config, err := rest.InClusterConfig()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
client, err := dynamic.NewForConfig(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
cmClient := certmanager.NewClient(
|
||||
*client,
|
||||
certmanager.WithCertIssuerKind(appSettings.CertIssuerKind),
|
||||
certmanager.WithCertIssuerName(appSettings.CertIssuerName),
|
||||
)
|
||||
|
||||
irClient := ingressroute.NewClient(
|
||||
*client,
|
||||
cmClient,
|
||||
ingressroute.WithCertCleanup(),
|
||||
)
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
defer close(stopCh)
|
||||
|
||||
go irClient.IngressRoutes.Watch(stopCh)
|
||||
|
||||
signalCh := make(chan os.Signal, 1)
|
||||
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-signalCh
|
||||
log.Print("Shutting down gracefully")
|
||||
}
|
153
pkg/certmanager/certificate.go
Normal file
153
pkg/certmanager/certificate.go
Normal file
|
@ -0,0 +1,153 @@
|
|||
package certmanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
cmv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
|
||||
cmmetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
const (
|
||||
certGroup = "cert-manager.io"
|
||||
certVersion = "v1"
|
||||
certKind = "Certificate"
|
||||
certResource = "certificates"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCertificateAlreadyExist = errors.New("certificate already exists")
|
||||
ErrCertificateToUnstructured = errors.New("certificate cannot get converted to unstructured")
|
||||
ErrCertificateCreation = errors.New("certificate creation error")
|
||||
ErrCertificateToJSON = errors.New("certificate cannot get converted to JSON")
|
||||
)
|
||||
|
||||
type certificateClient struct {
|
||||
client *Client
|
||||
gvr schema.GroupVersionResource
|
||||
}
|
||||
|
||||
func newCertificateClient(client *Client) certificateClient {
|
||||
return certificateClient{
|
||||
client: client,
|
||||
gvr: schema.GroupVersionResource{
|
||||
Group: certGroup,
|
||||
Version: certVersion,
|
||||
Resource: certResource,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *certificateClient) Create(
|
||||
ctx context.Context,
|
||||
namespace, secretName string,
|
||||
routes []map[string]interface{},
|
||||
) error {
|
||||
_, err := c.client.crdClient.Resource(c.gvr).Namespace(namespace).Get(ctx, secretName, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
return ErrCertificateAlreadyExist
|
||||
}
|
||||
|
||||
hosts := extractHosts(routes)
|
||||
|
||||
cert := cmv1.Certificate{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: certKind,
|
||||
APIVersion: fmt.Sprintf("%s/%s", certGroup, certVersion),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: secretName,
|
||||
},
|
||||
Spec: cmv1.CertificateSpec{
|
||||
DNSNames: hosts,
|
||||
SecretName: secretName,
|
||||
IssuerRef: cmmetav1.ObjectReference{
|
||||
Name: c.client.certIssuerName,
|
||||
Kind: c.client.certIssuerKind,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(cert)
|
||||
if err != nil {
|
||||
return errors.Join(ErrCertificateToUnstructured, err)
|
||||
}
|
||||
|
||||
_, err = c.client.crdClient.Resource(c.gvr).Namespace(namespace).Create(
|
||||
ctx,
|
||||
&unstructured.Unstructured{Object: obj},
|
||||
metav1.CreateOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Join(ErrCertificateCreation, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *certificateClient) Delete(ctx context.Context, namespace, name string) error {
|
||||
return c.client.crdClient.Resource(c.gvr).Namespace(namespace).Delete(ctx, name, metav1.DeleteOptions{})
|
||||
}
|
||||
|
||||
func (c *certificateClient) Patch(ctx context.Context, namespace, name string, cert cmv1.Certificate) error {
|
||||
data, err := json.Marshal(cert)
|
||||
if err != nil {
|
||||
return errors.Join(ErrCertificateToJSON, err)
|
||||
}
|
||||
|
||||
_, err = c.client.crdClient.Resource(c.gvr).Namespace(namespace).Patch(
|
||||
ctx,
|
||||
name,
|
||||
types.JSONPatchType,
|
||||
data,
|
||||
metav1.PatchOptions{},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *certificateClient) PatchSecretName(ctx context.Context, namespace, name, secretName string) error {
|
||||
cert := cmv1.Certificate{
|
||||
Spec: cmv1.CertificateSpec{
|
||||
SecretName: secretName,
|
||||
},
|
||||
}
|
||||
|
||||
return c.Patch(ctx, namespace, name, cert)
|
||||
}
|
||||
|
||||
func extractHosts(routes []map[string]interface{}) []string {
|
||||
var hosts []string
|
||||
re := regexp.MustCompile(`Host\(([^)]*)\)`)
|
||||
|
||||
for _, route := range routes {
|
||||
var (
|
||||
kind string
|
||||
match string
|
||||
ok bool
|
||||
)
|
||||
|
||||
kind, ok = route["kind"].(string)
|
||||
if !ok || kind != "Rule" {
|
||||
continue
|
||||
}
|
||||
|
||||
if match, ok = route["match"].(string); ok {
|
||||
hostMatches := re.FindAllStringSubmatch(match, -1)
|
||||
for _, match := range hostMatches {
|
||||
if len(match) > 1 {
|
||||
hosts = append(hosts, strings.Split(match[1], ",")...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hosts
|
||||
}
|
41
pkg/certmanager/client.go
Normal file
41
pkg/certmanager/client.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package certmanager
|
||||
|
||||
import (
|
||||
"k8s.io/client-go/dynamic"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
crdClient dynamic.DynamicClient
|
||||
certIssuerName string
|
||||
certIssuerKind string
|
||||
|
||||
Certificates certificateClient
|
||||
}
|
||||
|
||||
type ClientOption func(*Client)
|
||||
|
||||
func WithCertIssuerName(name string) ClientOption {
|
||||
return func(c *Client) {
|
||||
c.certIssuerName = name
|
||||
}
|
||||
}
|
||||
|
||||
func WithCertIssuerKind(kind string) ClientOption {
|
||||
return func(c *Client) {
|
||||
c.certIssuerKind = kind
|
||||
}
|
||||
}
|
||||
|
||||
func NewClient(crdClient dynamic.DynamicClient, options ...ClientOption) *Client {
|
||||
client := &Client{
|
||||
crdClient: crdClient,
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(client)
|
||||
}
|
||||
|
||||
client.Certificates = newCertificateClient(client)
|
||||
|
||||
return client
|
||||
}
|
37
pkg/ingressroute/client.go
Normal file
37
pkg/ingressroute/client.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package ingressroute
|
||||
|
||||
import (
|
||||
"git.ar21.de/yolokube/go-traefik-certmanager/pkg/certmanager"
|
||||
"k8s.io/client-go/dynamic"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
crdClient dynamic.DynamicClient
|
||||
certmanager *certmanager.Client
|
||||
certCleanup bool
|
||||
|
||||
IngressRoutes ingressRouteClient
|
||||
}
|
||||
|
||||
type ClientOption func(*Client)
|
||||
|
||||
func WithCertCleanup() ClientOption {
|
||||
return func(c *Client) {
|
||||
c.certCleanup = true
|
||||
}
|
||||
}
|
||||
|
||||
func NewClient(crdClient dynamic.DynamicClient, cmClient *certmanager.Client, options ...ClientOption) *Client {
|
||||
client := &Client{
|
||||
crdClient: crdClient,
|
||||
certmanager: cmClient,
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(client)
|
||||
}
|
||||
|
||||
client.IngressRoutes = ingressRouteClient{client: client}
|
||||
|
||||
return client
|
||||
}
|
161
pkg/ingressroute/ingressroute.go
Normal file
161
pkg/ingressroute/ingressroute.go
Normal file
|
@ -0,0 +1,161 @@
|
|||
package ingressroute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"git.ar21.de/yolokube/go-traefik-certmanager/pkg/certmanager"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
)
|
||||
|
||||
const (
|
||||
group = "traefik.io"
|
||||
version = "v1alpha1"
|
||||
resource = "ingressroutes"
|
||||
)
|
||||
|
||||
type ingressRouteClient struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (i *ingressRouteClient) Watch(stopCh chan struct{}) {
|
||||
gvr := schema.GroupVersionResource{
|
||||
Group: group,
|
||||
Version: version,
|
||||
Resource: resource,
|
||||
}
|
||||
|
||||
listWatch := &cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return i.client.crdClient.Resource(gvr).Namespace(corev1.NamespaceAll).List(context.Background(), options)
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return i.client.crdClient.Resource(gvr).Namespace(corev1.NamespaceAll).Watch(context.Background(), options)
|
||||
},
|
||||
}
|
||||
|
||||
queue := workqueue.NewTypedRateLimitingQueue(workqueue.DefaultTypedControllerRateLimiter[any]())
|
||||
|
||||
informer := cache.NewSharedInformer(listWatch, &unstructured.Unstructured{}, 0)
|
||||
_, err := informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
key, err := cache.MetaNamespaceKeyFunc(obj)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
convObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rawRoutes, found, err := unstructured.NestedSlice(convObj, "spec", "routes")
|
||||
if err != nil || !found {
|
||||
return
|
||||
}
|
||||
|
||||
routes, err := routeInterfaceToMapSlice(rawRoutes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
queue.Add(event{key: key, eventType: watch.Added, routes: routes})
|
||||
},
|
||||
UpdateFunc: func(_, newObj interface{}) {
|
||||
key, err := cache.MetaNamespaceKeyFunc(newObj)
|
||||
if err == nil {
|
||||
queue.Add(event{key: key, eventType: watch.Modified})
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
if !i.client.certCleanup {
|
||||
return
|
||||
}
|
||||
|
||||
key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)
|
||||
if err == nil {
|
||||
queue.Add(event{key: key, eventType: watch.Deleted})
|
||||
}
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Cannot add event handler: %v", err)
|
||||
}
|
||||
|
||||
go informer.Run(stopCh)
|
||||
|
||||
wait.Until(func() {
|
||||
for i.processNextItem(queue) {
|
||||
}
|
||||
}, time.Second, stopCh)
|
||||
}
|
||||
|
||||
func (i *ingressRouteClient) processNextItem(queue workqueue.TypedRateLimitingInterface[any]) bool {
|
||||
item, quit := queue.Get()
|
||||
if quit {
|
||||
return false
|
||||
}
|
||||
defer queue.Done(item)
|
||||
|
||||
log.Printf("Processing key %v", item)
|
||||
|
||||
event, ok := item.(event)
|
||||
if !ok {
|
||||
log.Printf("Invalid data struct: %v", item)
|
||||
return true
|
||||
}
|
||||
|
||||
namespace, name, err := cache.SplitMetaNamespaceKey(event.key)
|
||||
if err != nil {
|
||||
log.Printf("Failed to split namespace and name: %v", err)
|
||||
return true
|
||||
}
|
||||
|
||||
//nolint:exhaustive // ignore missing switch cases
|
||||
switch event.eventType {
|
||||
case watch.Added, watch.Modified:
|
||||
createErr := i.client.certmanager.Certificates.Create(context.Background(), namespace, name, event.routes)
|
||||
if createErr != nil {
|
||||
if errors.Is(createErr, certmanager.ErrCertificateAlreadyExist) {
|
||||
log.Printf("Certificate %s already exists", event.key)
|
||||
} else {
|
||||
log.Printf("Failed to create certificate %s: %v", event.key, createErr)
|
||||
}
|
||||
}
|
||||
case watch.Deleted:
|
||||
if deleteErr := i.client.certmanager.Certificates.Delete(context.Background(), namespace, name); deleteErr != nil {
|
||||
log.Printf("Failed to delete certificate %s: %v", event.key, deleteErr)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type event struct {
|
||||
key string
|
||||
eventType watch.EventType
|
||||
routes []map[string]interface{}
|
||||
}
|
||||
|
||||
func routeInterfaceToMapSlice(input []interface{}) ([]map[string]interface{}, error) {
|
||||
var result []map[string]interface{}
|
||||
for _, item := range input {
|
||||
match, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("item is not of type map[string]interface{}: %v", item)
|
||||
}
|
||||
result = append(result, match)
|
||||
}
|
||||
return result, nil
|
||||
}
|
19
renovate.json
Normal file
19
renovate.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base",
|
||||
"regexManagers:dockerfileVersions"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"matchPackagePatterns": ["*"],
|
||||
"automerge": true,
|
||||
"automergeType": "pr",
|
||||
"platformAutomerge": true,
|
||||
"dependencyDashboard": true
|
||||
}
|
||||
],
|
||||
"postUpdateOptions": [
|
||||
"gomodTidy"
|
||||
]
|
||||
}
|
Loading…
Add table
Reference in a new issue