feat: plugin migration 1

This commit is contained in:
Yoan.liu
2026-07-28 20:58:21 +08:00
parent 02895bf665
commit 063a1892d2
26 changed files with 0 additions and 1625 deletions
-21
View File
@@ -98,9 +98,6 @@ require (
google.golang.org/api v0.288.0
google.golang.org/grpc v1.82.0
google.golang.org/protobuf v1.36.11
k8s.io/api v0.35.3
k8s.io/apimachinery v0.35.3
k8s.io/client-go v0.35.3
software.sslmate.com/src/go-pkcs12 v0.7.3
)
@@ -116,23 +113,17 @@ require (
github.com/aws/aws-sdk-go-v2/service/route53 v1.62.8 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
github.com/go-acme/tencentclouddnspod v1.3.24 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-openapi/jsonreference v0.21.5 // indirect
github.com/go-openapi/swag v0.25.5 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
github.com/google/gnostic-models v0.7.1 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/namedotcom/go/v4 v4.0.2 // indirect
github.com/nrdcg/bunny-go v0.1.0 // indirect
github.com/nrdcg/desec v0.11.1 // indirect
@@ -147,21 +138,11 @@ require (
github.com/stretchr/objx v0.5.3 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/vultr/govultr/v3 v3.31.2 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.mongodb.org/mongo-driver v1.17.9 // indirect
go.uber.org/ratelimit v0.3.1 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ns1/ns1-go.v2 v2.17.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/klog/v2 v2.140.0 // indirect
k8s.io/kube-openapi v0.0.0-20260330154417-16be699c7b31 // indirect
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)
require (
@@ -263,9 +244,7 @@ require (
golang.org/x/image v0.41.0 // indirect
golang.org/x/mod v0.37.0 // indirect
golang.org/x/net v0.56.0 // indirect
golang.org/x/term v0.45.0 // indirect
golang.org/x/text v0.40.0 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/tools v0.47.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260630182238-925bb5da69e7 // indirect
gopkg.in/ini.v1 v1.67.3 // indirect
-64
View File
@@ -315,8 +315,6 @@ github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -344,8 +342,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ=
github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk=
@@ -384,34 +380,6 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.22.5 h1:8on/0Yp4uTb9f4XvTrM2+1CPrV05QPZXu+rvu2o9jcA=
github.com/go-openapi/jsonpointer v0.22.5/go.mod h1:gyUR3sCvGSWchA2sUBJGluYMbe1zazrYWIkWPjjMUY0=
github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE=
github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw=
github.com/go-openapi/swag v0.25.5 h1:pNkwbUEeGwMtcgxDr+2GBPAk4kT+kJ+AaB+TMKAg+TU=
github.com/go-openapi/swag v0.25.5/go.mod h1:B3RT6l8q7X803JRxa2e59tHOiZlX1t8viplOcs9CwTA=
github.com/go-openapi/swag/cmdutils v0.25.5 h1:yh5hHrpgsw4NwM9KAEtaDTXILYzdXh/I8Whhx9hKj7c=
github.com/go-openapi/swag/cmdutils v0.25.5/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
github.com/go-openapi/swag/conv v0.25.5 h1:wAXBYEXJjoKwE5+vc9YHhpQOFj2JYBMF2DUi+tGu97g=
github.com/go-openapi/swag/conv v0.25.5/go.mod h1:CuJ1eWvh1c4ORKx7unQnFGyvBbNlRKbnRyAvDvzWA4k=
github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk=
github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc=
github.com/go-openapi/swag/jsonname v0.25.5 h1:8p150i44rv/Drip4vWI3kGi9+4W9TdI3US3uUYSFhSo=
github.com/go-openapi/swag/jsonname v0.25.5/go.mod h1:jNqqikyiAK56uS7n8sLkdaNY/uq6+D2m2LANat09pKU=
github.com/go-openapi/swag/jsonutils v0.25.5 h1:XUZF8awQr75MXeC+/iaw5usY/iM7nXPDwdG3Jbl9vYo=
github.com/go-openapi/swag/jsonutils v0.25.5/go.mod h1:48FXUaz8YsDAA9s5AnaUvAmry1UcLcNVWUjY42XkrN4=
github.com/go-openapi/swag/loading v0.25.5 h1:odQ/umlIZ1ZVRteI6ckSrvP6e2w9UTF5qgNdemJHjuU=
github.com/go-openapi/swag/loading v0.25.5/go.mod h1:I8A8RaaQ4DApxhPSWLNYWh9NvmX2YKMoB9nwvv6oW6g=
github.com/go-openapi/swag/mangling v0.25.5 h1:hyrnvbQRS7vKePQPHHDso+k6CGn5ZBs5232UqWZmJZw=
github.com/go-openapi/swag/mangling v0.25.5/go.mod h1:6hadXM/o312N/h98RwByLg088U61TPGiltQn71Iw0NY=
github.com/go-openapi/swag/netutils v0.25.5 h1:LZq2Xc2QI8+7838elRAaPCeqJnHODfSyOa7ZGfxDKlU=
github.com/go-openapi/swag/netutils v0.25.5/go.mod h1:lHbtmj4m57APG/8H7ZcMMSWzNqIQcu0RFiXrPUara14=
github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M=
github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII=
github.com/go-openapi/swag/typeutils v0.25.5 h1:EFJ+PCga2HfHGdo8s8VJXEVbeXRCYwzzr9u4rJk7L7E=
github.com/go-openapi/swag/typeutils v0.25.5/go.mod h1:itmFmScAYE1bSD8C4rS0W+0InZUBrB2xSPbWt6DLGuc=
github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ=
github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
@@ -480,8 +448,6 @@ github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c=
github.com/google/gnostic-models v0.7.1/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -715,8 +681,6 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/namedotcom/go/v4 v4.0.2 h1:4gNkPaPRG/2tqFNUUof7jAVsA6vDutFutEOd7ivnDwA=
@@ -934,8 +898,6 @@ github.com/vultr/govultr/v3 v3.31.2 h1:2l3/KDvfemG+4azw4LLquJoh9mFOAVEdBXtPPzix3
github.com/vultr/govultr/v3 v3.31.2/go.mod h1:2zyUw9yADQaGwKnwDesmIOlBNLrm7edsCfWHFJpWKf8=
github.com/wneessen/go-mail v0.8.1 h1:tVcncj02/QySVFw3zr/kXOzZcuFQqBNT6K+Rbgm/pcM=
github.com/wneessen/go-mail v0.8.1/go.mod h1:dWZ61zadzCIyvB4y1/YzC5O7MrbbzBfPkARmbosdf8w=
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/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
@@ -1001,8 +963,6 @@ go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0=
go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -1459,12 +1419,8 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8
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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.3 h1:iM9Lhz5MRSGhHVGGwCuzG9KO8PoirCXj/m/qTmOJJQw=
@@ -1494,18 +1450,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.35.3 h1:pA2fiBc6+N9PDf7SAiluKGEBuScsTzd2uYBkA5RzNWQ=
k8s.io/api v0.35.3/go.mod h1:9Y9tkBcFwKNq2sxwZTQh1Njh9qHl81D0As56tu42GA4=
k8s.io/apimachinery v0.35.3 h1:MeaUwQCV3tjKP4bcwWGgZ/cp/vpsRnQzqO6J6tJyoF8=
k8s.io/apimachinery v0.35.3/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
k8s.io/client-go v0.35.3 h1:s1lZbpN4uI6IxeTM2cpdtrwHcSOBML1ODNTCCfsP1pg=
k8s.io/client-go v0.35.3/go.mod h1:RzoXkc0mzpWIDvBrRnD+VlfXP+lRzqQjCmKtiwZ8Q9c=
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
k8s.io/kube-openapi v0.0.0-20260330154417-16be699c7b31 h1:V+sn9a/1fEYDGwnllCmqXBk8x7obZ+hl869Q3Abumkg=
k8s.io/kube-openapi v0.0.0-20260330154417-16be699c7b31/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0=
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM=
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
modernc.org/cc/v4 v4.28.2 h1:3tQ0lf2ADtoby2EtSP+J7IE2SHwEJdP8ioR59wx7XpY=
modernc.org/cc/v4 v4.28.2/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.34.0 h1:yRLPFZieg532OT4rp4JFNIVcquwalMX26G95WQDqwCQ=
@@ -1538,14 +1482,6 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8=
sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
software.sslmate.com/src/go-pkcs12 v0.7.3 h1:JBQD3FDqYjTeyDAeZQklj2ar88ykBLtALloPJHyAauU=
software.sslmate.com/src/go-pkcs12 v0.7.3/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI=
@@ -1,27 +0,0 @@
package deployers
import (
"fmt"
"github.com/certimate-go/certimate/internal/domain"
"github.com/certimate-go/certimate/pkg/core"
dplyimpl "github.com/certimate-go/certimate/pkg/core/deployer/providers/dogecloud-cdn"
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
)
func init() {
Registries.MustRegister(domain.DeploymentProviderTypeDogeCloudCDN, func(options *ProviderFactoryOptions) (core.Deployer, error) {
credentials := domain.AccessConfigForDogeCloud{}
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
provider, err := dplyimpl.NewDeployer(&dplyimpl.DeployerConfig{
AccessKey: credentials.AccessKey,
SecretKey: credentials.SecretKey,
DomainMatchPattern: xmaps.GetString(options.ProviderExtendedConfig, "domainMatchPattern"),
Domain: xmaps.GetString(options.ProviderExtendedConfig, "domain"),
})
return provider, err
})
}
@@ -1,78 +0,0 @@
package deployers
import (
"fmt"
"strings"
"github.com/certimate-go/certimate/internal/domain"
"github.com/certimate-go/certimate/pkg/core"
dplyimpl "github.com/certimate-go/certimate/pkg/core/deployer/providers/k8s-secret"
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
)
func init() {
Registries.MustRegister(domain.DeploymentProviderTypeKubernetesSecret, func(options *ProviderFactoryOptions) (core.Deployer, error) {
credentials := domain.AccessConfigForKubernetes{}
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
parseKeyValueMap := func(s string) (map[string]string, error) {
result := make(map[string]string)
lines := strings.Split(s, "\n")
for i, line := range lines {
if strings.TrimSpace(line) == "" {
continue
}
pos := strings.Index(line, ":")
if pos == -1 {
return nil, fmt.Errorf("invalid line format at line %d", i+1)
}
key := strings.TrimSpace(line[:pos])
value := strings.TrimSpace(line[pos+1:])
if key == "" {
return nil, fmt.Errorf("invalid key at line %d", i+1)
}
result[key] = value
}
return result, nil
}
secretAnnotations := make(map[string]string)
if secretAnnotationsString := xmaps.GetString(options.ProviderExtendedConfig, "secretAnnotations"); secretAnnotationsString != "" {
temp, err := parseKeyValueMap(secretAnnotationsString)
if err != nil {
return nil, fmt.Errorf("failed to parse kubernetes secret annotations: %w", err)
}
secretAnnotations = temp
}
secretLabels := make(map[string]string)
if secretLabelsString := xmaps.GetString(options.ProviderExtendedConfig, "secretLabels"); secretLabelsString != "" {
temp, err := parseKeyValueMap(secretLabelsString)
if err != nil {
return nil, fmt.Errorf("failed to parse kubernetes secret labels: %w", err)
}
secretLabels = temp
}
provider, err := dplyimpl.NewDeployer(&dplyimpl.DeployerConfig{
KubeConfig: credentials.KubeConfig,
Namespace: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "namespace", "default"),
SecretName: xmaps.GetString(options.ProviderExtendedConfig, "secretName"),
SecretType: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretType", "kubernetes.io/tls"),
SecretDataKeyForKey: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForKey", "tls.key"),
SecretDataKeyForCrt: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForCrt", "tls.crt"),
SecretDataKeyForCrtOnlyServer: xmaps.GetString(options.ProviderExtendedConfig, "secretDataKeyForCrtOnlyServer"),
SecretDataKeyForCrtOnlyIntermedia: xmaps.GetString(options.ProviderExtendedConfig, "secretDataKeyForCrtOnlyIntermedia"),
SecretAnnotations: secretAnnotations,
SecretLabels: secretLabels,
})
return provider, err
})
}
@@ -1,95 +0,0 @@
package dogecloud
import (
"context"
"fmt"
"log/slog"
"time"
"github.com/certimate-go/certimate/pkg/core"
dogecloudsdk "github.com/certimate-go/certimate/pkg/sdk3rd/dogecloud"
)
type (
Provider = core.Certmgr
UploadResult = core.CertmgrUploadResult
ReplaceResult = core.CertmgrReplaceResult
)
type CertmgrConfig struct {
// 多吉云 AccessKey。
AccessKey string `json:"accessKey"`
// 多吉云 SecretKey。
SecretKey string `json:"secretKey"`
}
type Certmgr struct {
config *CertmgrConfig
logger *slog.Logger
sdkClient *dogecloudsdk.Client
}
var _ Provider = (*Certmgr)(nil)
func NewCertmgr(config *CertmgrConfig) (*Certmgr, error) {
if config == nil {
return nil, fmt.Errorf("the configuration of the certmgr provider is nil")
}
client, err := createSDKClient(config.AccessKey, config.SecretKey)
if err != nil {
return nil, fmt.Errorf("could not create client: %w", err)
}
return &Certmgr{
config: config,
logger: slog.Default(),
sdkClient: client,
}, nil
}
func (c *Certmgr) SetLogger(logger *slog.Logger) {
if logger == nil {
c.logger = slog.New(slog.DiscardHandler)
} else {
c.logger = logger
}
}
func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*UploadResult, error) {
// 生成新证书名(需符合多吉云命名规则)
certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
// 上传新证书
// REF: https://docs.dogecloud.com/cdn/api-cert-upload
uploadSslCertReq := &dogecloudsdk.UploadCdnCertRequest{
Note: certName,
Certificate: certPEM,
PrivateKey: privkeyPEM,
}
uploadSslCertResp, err := c.sdkClient.UploadCdnCertWithContext(ctx, uploadSslCertReq)
c.logger.Debug("sdk request 'cdn.UploadCdnCert'", slog.Any("request", uploadSslCertReq), slog.Any("response", uploadSslCertResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cdn.UploadCdnCert': %w", err)
}
return &UploadResult{
CertId: fmt.Sprintf("%d", uploadSslCertResp.Data.Id),
CertName: certName,
}, nil
}
func (c *Certmgr) Replace(ctx context.Context, certIdOrName string, certPEM, privkeyPEM string) (*ReplaceResult, error) {
return nil, core.ErrUnsupported
}
func createSDKClient(accessKey, secretKey string) (*dogecloudsdk.Client, error) {
client, err := dogecloudsdk.NewClient(
dogecloudsdk.WithAkSk(accessKey, secretKey),
)
if err != nil {
return nil, err
}
return client, nil
}
@@ -1,49 +0,0 @@
package dogecloud_test
import (
"testing"
impl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/dogecloud"
tester "github.com/certimate-go/certimate/pkg/core/certmgr/testing"
)
var (
fp = tester.Args("DOGECLOUD_")
fTestCertPath string
fTestKeyPath string
fAccessKey string
fSecretKey string
)
func init() {
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
fp.DefineString(&fAccessKey, "ACCESSKEY")
fp.DefineString(&fSecretKey, "SECRETKEY")
}
/*
Shell command to run this test:
go test -v ./dogecloud_test.go -args \
--DOGECLOUD_TESTCERTPATH="/path/to/your-test-cert.pem" \
--DOGECLOUD_TESTKEYPATH="/path/to/your-test-key.pem" \
--DOGECLOUD_ACCESSKEY="your-access-key" \
--DOGECLOUD_SECRETKEY="your-secret-key"
*/
func TestProvider(t *testing.T) {
fp.Parse()
t.Run("Upload", func(t *testing.T) {
provider, err := impl.NewCertmgr(&impl.CertmgrConfig{
AccessKey: fAccessKey,
SecretKey: fSecretKey,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
tester.TestUpload(t, provider, tester.TestUploadArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
})
}
@@ -1,8 +0,0 @@
package dogecloudcdn
const (
// 匹配模式:精确匹配。
DOMAIN_MATCH_PATTERN_EXACT = "exact"
// 匹配模式:证书 SAN 匹配。
DOMAIN_MATCH_PATTERN_CERTSAN = "certsan"
)
@@ -1,187 +0,0 @@
package dogecloudcdn
import (
"context"
"fmt"
"log/slog"
"strconv"
"github.com/samber/lo"
"github.com/certimate-go/certimate/pkg/core"
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/dogecloud"
dogecloudsdk "github.com/certimate-go/certimate/pkg/sdk3rd/dogecloud"
xcerthostname "github.com/certimate-go/certimate/pkg/utils/cert/hostname"
xloop "github.com/certimate-go/certimate/pkg/utils/loop"
)
type (
Provider = core.Deployer
DeployResult = core.DeployerDeployResult
)
type DeployerConfig struct {
// 多吉云 AccessKey。
AccessKey string `json:"accessKey"`
// 多吉云 SecretKey。
SecretKey string `json:"secretKey"`
// 域名匹配模式。
// 零值时默认值 [DOMAIN_MATCH_PATTERN_EXACT]。
DomainMatchPattern string `json:"domainMatchPattern,omitempty"`
// 加速域名(不支持泛域名)。
Domain string `json:"domain"`
}
type Deployer struct {
config *DeployerConfig
logger *slog.Logger
sdkClient *dogecloudsdk.Client
sdkCertmgr core.Certmgr
}
var _ Provider = (*Deployer)(nil)
func NewDeployer(config *DeployerConfig) (*Deployer, error) {
if config == nil {
return nil, fmt.Errorf("the configuration of the deployer provider is nil")
}
client, err := createSDKClient(config.AccessKey, config.SecretKey)
if err != nil {
return nil, fmt.Errorf("could not create client: %w", err)
}
pcertmgr, err := cmgrimpl.NewCertmgr(&cmgrimpl.CertmgrConfig{
AccessKey: config.AccessKey,
SecretKey: config.SecretKey,
})
if err != nil {
return nil, fmt.Errorf("could not create certmgr: %w", err)
}
return &Deployer{
config: config,
logger: slog.Default(),
sdkClient: client,
sdkCertmgr: pcertmgr,
}, nil
}
func (d *Deployer) SetLogger(logger *slog.Logger) {
if logger == nil {
d.logger = slog.New(slog.DiscardHandler)
} else {
d.logger = logger
}
d.sdkCertmgr.SetLogger(logger)
}
func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*DeployResult, error) {
// 上传证书
upres, err := d.sdkCertmgr.Upload(ctx, certPEM, privkeyPEM)
if err != nil {
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
} else {
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
}
// 获取待部署的域名列表
var domains []string
switch d.config.DomainMatchPattern {
case "", DOMAIN_MATCH_PATTERN_EXACT:
{
if d.config.Domain == "" {
return nil, fmt.Errorf("config `domain` is required")
}
domains = []string{d.config.Domain}
}
case DOMAIN_MATCH_PATTERN_CERTSAN:
{
domainCandidates, err := d.getAllDomains(ctx)
if err != nil {
return nil, err
}
domains = lo.Filter(domainCandidates, func(domain string, _ int) bool {
return xcerthostname.IsMatchByCertificatePEM(certPEM, domain)
})
if len(domains) == 0 {
return nil, fmt.Errorf("could not find any domains matched by certificate")
}
}
default:
return nil, fmt.Errorf("unsupported domain match pattern: '%s'", d.config.DomainMatchPattern)
}
// 批量更新域名证书
if len(domains) == 0 {
d.logger.Info("no cdn domains to deploy")
} else {
d.logger.Info("found cdn domains to deploy", slog.Any("domains", domains))
if err := xloop.ForRangeAllWithContext(ctx, domains, func(ctx context.Context, domain string, _ int) error {
certId, _ := strconv.ParseInt(upres.CertId, 10, 64)
return d.updateDomainCertificate(ctx, domain, certId)
}); err != nil {
return nil, err
}
}
return &DeployResult{}, nil
}
func (d *Deployer) getAllDomains(ctx context.Context) ([]string, error) {
domains := make([]string, 0)
// 获取域名列表
// REF: https://docs.dogecloud.com/cdn/api-domain-list
listCdnDomainResp, err := d.sdkClient.ListCdnDomainWithContext(ctx)
d.logger.Debug("sdk request 'cdn.ListCdnDomain'", slog.Any("response", listCdnDomainResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cdn.ListCdnDomain': %w", err)
}
if listCdnDomainResp.Data != nil {
ignoredStatuses := []string{"offline"}
for _, domainItem := range listCdnDomainResp.Data.Domains {
if lo.Contains(ignoredStatuses, domainItem.Status) {
continue
}
domains = append(domains, domainItem.Name)
}
}
return domains, nil
}
func (d *Deployer) updateDomainCertificate(ctx context.Context, domain string, cloudCertId int64) error {
// 绑定证书
// REF: https://docs.dogecloud.com/cdn/api-cert-bind
bindCdnCertReq := &dogecloudsdk.BindCdnCertRequest{
CertId: cloudCertId,
Domain: domain,
}
bindCdnCertResp, err := d.sdkClient.BindCdnCertWithContext(ctx, bindCdnCertReq)
d.logger.Debug("sdk request 'cdn.BindCdnCert'", slog.Any("request", bindCdnCertReq), slog.Any("response", bindCdnCertResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'cdn.BindCdnCert': %w", err)
}
return nil
}
func createSDKClient(accessKey, secretKey string) (*dogecloudsdk.Client, error) {
client, err := dogecloudsdk.NewClient(
dogecloudsdk.WithAkSk(accessKey, secretKey),
)
if err != nil {
return nil, err
}
return client, nil
}
@@ -1,53 +0,0 @@
package dogecloudcdn_test
import (
"testing"
impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/dogecloud-cdn"
tester "github.com/certimate-go/certimate/pkg/core/deployer/testing"
)
var (
fp = tester.Args("DOGECLOUDCDN_")
fTestCertPath string
fTestKeyPath string
fAccessKey string
fSecretKey string
fDomain string
)
func init() {
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
fp.DefineString(&fAccessKey, "ACCESSKEY")
fp.DefineString(&fSecretKey, "SECRETKEY")
fp.DefineString(&fDomain, "DOMAIN")
}
/*
Shell command to run this test:
go test -v ./dogecloud_cdn_test.go -args \
--DOGECLOUDCDN_TESTCERTPATH="/path/to/your-test-cert.pem" \
--DOGECLOUDCDN_TESTKEYPATH="/path/to/your-test-key.pem" \
--DOGECLOUDCDN_ACCESSKEY="your-access-key" \
--DOGECLOUDCDN_SECRETKEY="your-secret-key" \
--DOGECLOUDCDN_DOMAIN="example.com"
*/
func TestProvider(t *testing.T) {
fp.Parse()
t.Run("Deploy", func(t *testing.T) {
provider, err := impl.NewDeployer(&impl.DeployerConfig{
AccessKey: fAccessKey,
SecretKey: fSecretKey,
Domain: fDomain,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
})
}
@@ -1,231 +0,0 @@
package k8ssecret
import (
"context"
"fmt"
"log/slog"
"strings"
k8score "k8s.io/api/core/v1"
k8serrs "k8s.io/apimachinery/pkg/api/errors"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"github.com/certimate-go/certimate/pkg/core"
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
)
type (
Provider = core.Deployer
DeployResult = core.DeployerDeployResult
)
type DeployerConfig struct {
// kubeconfig 文件内容。
KubeConfig string `json:"kubeConfig,omitempty"`
// Kubernetes 命名空间。
Namespace string `json:"namespace,omitempty"`
// Kubernetes Secret 名称。
SecretName string `json:"secretName"`
// Kubernetes Secret 类型。
SecretType string `json:"secretType"`
// Kubernetes Secret 中用于存放私钥的键。
SecretDataKeyForKey string `json:"secretDataKeyForKey,omitempty"`
// Kubernetes Secret 中用于存放证书的键。
SecretDataKeyForCrt string `json:"secretDataKeyForCrt,omitempty"`
// Kubernetes Secret 中用于存放证书(仅含服务器证书)的键。
// 选填。
SecretDataKeyForCrtOnlyServer string `json:"secretDataKeyForCrtOnlyServer,omitempty"`
// Kubernetes Secret 中用于存放证书(仅含中间证书)的键。
// 选填。
SecretDataKeyForCrtOnlyIntermedia string `json:"secretDataKeyForCrtOnlyIntermedia,omitempty"`
// Kubernetes Secret 注解。
SecretAnnotations map[string]string `json:"secretAnnotations,omitempty"`
// Kubernetes Secret 标签。
SecretLabels map[string]string `json:"secretLabels,omitempty"`
}
type Deployer struct {
config *DeployerConfig
logger *slog.Logger
}
var _ Provider = (*Deployer)(nil)
func NewDeployer(config *DeployerConfig) (*Deployer, error) {
if config == nil {
return nil, fmt.Errorf("the configuration of the deployer provider is nil")
}
return &Deployer{
logger: slog.Default(),
config: config,
}, nil
}
func (d *Deployer) SetLogger(logger *slog.Logger) {
if logger == nil {
d.logger = slog.New(slog.DiscardHandler)
} else {
d.logger = logger
}
}
func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*DeployResult, error) {
if d.config.Namespace == "" {
return nil, fmt.Errorf("config `namespace` is required")
}
if d.config.SecretName == "" {
return nil, fmt.Errorf("config `secretName` is required")
}
if d.config.SecretType == "" {
return nil, fmt.Errorf("config `secretType` is required")
}
// 解析证书内容
certX509, err := xcert.ParseCertificateFromPEM(certPEM)
if err != nil {
return nil, err
}
// 提取服务器证书和中间证书
serverCertPEM, issuerCertPEM, err := xcert.ExtractCertificatesFromPEM(certPEM)
if err != nil {
return nil, fmt.Errorf("failed to extract certs: %w", err)
}
// 连接到 Kubernetes
client, err := createK8sClient(d.config.KubeConfig)
if err != nil {
return nil, fmt.Errorf("failed to create kubernetes client: %w", err)
}
// 获取 Secret 实例
secretPayload := &k8score.Secret{}
secretIsNew := false
secretGetResp := client.Get().
Namespace(d.config.Namespace).
Resource("secrets").
Name(d.config.SecretName).
VersionedParams(&meta.GetOptions{}, meta.ParameterCodec).
Do(ctx)
if err := secretGetResp.Error(); err != nil {
if !k8serrs.IsNotFound(err) {
return nil, fmt.Errorf("failed to get kubernetes secret: %w", err)
}
secretPayload = &k8score.Secret{
Type: k8score.SecretType(d.config.SecretType),
TypeMeta: meta.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: meta.ObjectMeta{
Name: d.config.SecretName,
},
}
secretIsNew = true
} else if err := secretGetResp.Into(secretPayload); err != nil {
return nil, fmt.Errorf("failed to parse kubernetes secret: %w", err)
}
d.logger.Debug("kubernetes operate 'Secrets.Get'", slog.String("namespace", d.config.Namespace), slog.Any("secret", d.config.SecretName))
// 生成 Secret 注解和标签
secretAnnotations := map[string]string{
"certimate/common-name": certX509.Subject.CommonName,
"certimate/subject-sn": certX509.Subject.SerialNumber,
"certimate/subject-alt-names": strings.Join(certX509.DNSNames, ","),
"certimate/issuer-sn": certX509.Issuer.SerialNumber,
"certimate/issuer-org": strings.Join(certX509.Issuer.Organization, ","),
}
secretLabels := map[string]string{}
if d.config.SecretAnnotations != nil {
xmaps.CopyTo(d.config.SecretAnnotations, secretAnnotations)
}
if d.config.SecretLabels != nil {
xmaps.CopyTo(d.config.SecretLabels, secretLabels)
}
// 赋值 Secret 实例
secretPayload.Type = k8score.SecretType(d.config.SecretType)
if secretPayload.ObjectMeta.Annotations == nil {
secretPayload.ObjectMeta.Annotations = secretAnnotations
} else {
xmaps.CopyTo(secretAnnotations, secretPayload.ObjectMeta.Annotations)
}
if secretPayload.ObjectMeta.Labels == nil {
secretPayload.ObjectMeta.Labels = secretLabels
} else {
xmaps.CopyTo(secretLabels, secretPayload.ObjectMeta.Labels)
}
if secretPayload.Data == nil {
secretPayload.Data = make(map[string][]byte)
}
if d.config.SecretDataKeyForKey != "" {
secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPEM)
}
if d.config.SecretDataKeyForCrt != "" {
secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPEM)
}
if d.config.SecretDataKeyForCrtOnlyServer != "" {
secretPayload.Data[d.config.SecretDataKeyForCrtOnlyServer] = []byte(serverCertPEM)
}
if d.config.SecretDataKeyForCrtOnlyIntermedia != "" {
secretPayload.Data[d.config.SecretDataKeyForCrtOnlyIntermedia] = []byte(issuerCertPEM)
}
// 创建或更新 Secret 实例
if secretIsNew {
secretPostResp := client.Post().
Namespace(d.config.Namespace).
Resource("secrets").
Name(d.config.SecretName).
VersionedParams(&meta.GetOptions{}, meta.ParameterCodec).
Body(secretPayload).
Do(ctx)
d.logger.Debug("kubernetes operate 'Secrets.Post'", slog.String("namespace", d.config.Namespace), slog.Any("secret", d.config.SecretName))
if err := secretPostResp.Error(); err != nil {
return nil, fmt.Errorf("failed to create kubernetes secret: %w", err)
}
} else {
secretPutResp := client.Put().
Namespace(d.config.Namespace).
Resource("secrets").
Name(d.config.SecretName).
VersionedParams(&meta.GetOptions{}, meta.ParameterCodec).
Body(secretPayload).
Do(ctx)
d.logger.Debug("kubernetes operate 'Secrets.Put'", slog.String("namespace", d.config.Namespace), slog.Any("secret", d.config.SecretName))
if err := secretPutResp.Error(); err != nil {
return nil, fmt.Errorf("failed to update kubernetes secret: %w", err)
}
}
return &DeployResult{}, nil
}
func createK8sClient(kubeConfig string) (*rest.RESTClient, error) {
var config *rest.Config
var err error
if kubeConfig == "" {
config, err = rest.InClusterConfig()
} else {
kubeConfig, err := clientcmd.NewClientConfigFromBytes([]byte(kubeConfig))
if err != nil {
return nil, err
}
config, err = kubeConfig.ClientConfig()
}
if err != nil {
return nil, err
}
client, err := rest.RESTClientFor(config)
if err != nil {
return nil, err
}
return client, nil
}
@@ -1,57 +0,0 @@
package k8ssecret_test
import (
"testing"
impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/k8s-secret"
tester "github.com/certimate-go/certimate/pkg/core/deployer/testing"
)
var (
fp = tester.Args("K8SSECRET_")
fTestCertPath string
fTestKeyPath string
fNamespace string
fSecretName string
fSecretDataKeyForCrt string
fSecretDataKeyForKey string
)
func init() {
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
fp.DefineString(&fNamespace, "NAMESPACE", "default")
fp.DefineString(&fSecretName, "SECRETNAME")
fp.DefineString(&fSecretDataKeyForCrt, "SECRETDATAKEYFORCRT", "tls.crt")
fp.DefineString(&fSecretDataKeyForKey, "SECRETDATAKEYFORKEY", "tls.key")
}
/*
Shell command to run this test:
go test -v ./k8s_secret_test.go -args \
--K8SSECRET_TESTCERTPATH="/path/to/your-test-cert.pem" \
--K8SSECRET_TESTKEYPATH="/path/to/your-test-key.pem" \
--K8SSECRET_NAMESPACE="default" \
--K8SSECRET_SECRETNAME="secret" \
--K8SSECRET_SECRETDATAKEYFORCRT="tls.crt" \
--K8SSECRET_SECRETDATAKEYFORKEY="tls.key"
*/
func TestProvider(t *testing.T) {
fp.Parse()
t.Run("Deploy", func(t *testing.T) {
provider, err := impl.NewDeployer(&impl.DeployerConfig{
Namespace: fNamespace,
SecretName: fSecretName,
SecretDataKeyForCrt: fSecretDataKeyForCrt,
SecretDataKeyForKey: fSecretDataKeyForKey,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
})
}
-36
View File
@@ -1,36 +0,0 @@
package dogecloud
import (
"context"
"net/http"
)
type BindCdnCertRequest struct {
CertId int64 `json:"id"`
Domain string `json:"domain"`
}
type BindCdnCertResponse struct {
sdkResponseBase
}
func (c *Client) BindCdnCert(req *BindCdnCertRequest) (*BindCdnCertResponse, error) {
return c.BindCdnCertWithContext(context.Background(), req)
}
func (c *Client) BindCdnCertWithContext(ctx context.Context, req *BindCdnCertRequest) (*BindCdnCertResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/cdn/cert/bind.json")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &BindCdnCertResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}
@@ -1,44 +0,0 @@
package dogecloud
import (
"context"
"encoding/json"
"net/http"
)
type ListCdnDomainResponse struct {
sdkResponseBase
Data *struct {
Domains []*struct {
Id int64 `json:"id"`
Name string `json:"name"`
Cname string `json:"cname"`
ServiceType string `json:"service_type"`
Status string `json:"status"`
Source json.RawMessage `json:"source"`
CreateTime string `json:"ctime"`
CertId int64 `json:"cert_id"`
} `json:"domains"`
} `json:"data,omitempty"`
}
func (c *Client) ListCdnDomain() (*ListCdnDomainResponse, error) {
return c.ListCdnDomainWithContext(context.Background())
}
func (c *Client) ListCdnDomainWithContext(ctx context.Context) (*ListCdnDomainResponse, error) {
httpreq, err := c.newRequest(http.MethodGet, "/cdn/domain/list.json")
if err != nil {
return nil, err
} else {
httpreq.SetContext(ctx)
}
result := &ListCdnDomainResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}
@@ -1,41 +0,0 @@
package dogecloud
import (
"context"
"net/http"
)
type UploadCdnCertRequest struct {
Note string `json:"note"`
Certificate string `json:"cert"`
PrivateKey string `json:"private"`
}
type UploadCdnCertResponse struct {
sdkResponseBase
Data *struct {
Id int64 `json:"id"`
} `json:"data,omitempty"`
}
func (c *Client) UploadCdnCert(req *UploadCdnCertRequest) (*UploadCdnCertResponse, error) {
return c.UploadCdnCertWithContext(context.Background(), req)
}
func (c *Client) UploadCdnCertWithContext(ctx context.Context, req *UploadCdnCertRequest) (*UploadCdnCertResponse, error) {
httpreq, err := c.newRequest(http.MethodPost, "/cdn/cert/upload.json")
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &UploadCdnCertResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}
-114
View File
@@ -1,114 +0,0 @@
// A simple SDK client for DogeCloud.
// API documentation: https://docs.dogecloud.com/
package dogecloud
import (
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/go-resty/resty/v2"
"github.com/certimate-go/certimate/internal/app"
)
type Client struct {
rc *resty.Client
}
func NewClient(optFns ...OptionsFunc) (*Client, error) {
opts := &Options{}
for _, fn := range optFns {
fn(opts)
}
if opts.AccessKey == "" {
return nil, fmt.Errorf("sdkerr: unset accessKey")
}
if opts.SecretKey == "" {
return nil, fmt.Errorf("sdkerr: unset secretKey")
}
signer := &signer{
accessKey: opts.AccessKey,
secretKey: opts.SecretKey,
}
httper := resty.New().
SetBaseURL("https://api.dogecloud.com").
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", app.AppUserAgent).
SetPreRequestHook(func(ctx *resty.Client, req *http.Request) error {
if err := signer.Sign(req); err != nil {
return fmt.Errorf("sdkerr: sign error: %w", err)
}
return nil
})
return &Client{httper}, nil
}
func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.rc.SetTimeout(timeout)
return c
}
func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
if method == "" {
return nil, fmt.Errorf("sdkerr: unset method")
}
if path == "" {
return nil, fmt.Errorf("sdkerr: unset path")
}
req := c.rc.R()
req.Method = method
req.URL = path
// WARN:
// DO NOT CALL `req.SetResult` or `req.SetError` AGAIN! USE `doRequestWithResult` INSTEAD.
return req, nil
}
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
resp, err := req.Send()
if err != nil {
return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
} else if resp.IsError() {
return resp, fmt.Errorf("sdkerr: unexpected status code: %d (resp: %s)", resp.StatusCode(), resp.String())
}
return resp, nil
}
func (c *Client) doRequestWithResult(req *resty.Request, res sdkResponse) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
resp, err := c.doRequest(req)
if err != nil {
if resp != nil {
json.Unmarshal(resp.Body(), &res)
}
return resp, err
}
if len(resp.Body()) != 0 {
if err := json.Unmarshal(resp.Body(), &res); err != nil {
return resp, fmt.Errorf("sdkerr: failed to unmarshal response: %w (resp: %s)", err, resp.String())
} else {
if rCode := res.GetCode(); rCode != 0 && rCode != 200 {
return resp, fmt.Errorf("sdkerr: api error: code='%d', msg='%s'", rCode, res.GetMessage())
}
}
}
return resp, nil
}
-15
View File
@@ -1,15 +0,0 @@
package dogecloud
type Options struct {
AccessKey string
SecretKey string
}
type OptionsFunc func(*Options)
func WithAkSk(ak, sk string) OptionsFunc {
return func(o *Options) {
o.AccessKey = ak
o.SecretKey = sk
}
}
-50
View File
@@ -1,50 +0,0 @@
package dogecloud
import (
"bytes"
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"fmt"
"io"
"net/http"
)
type signer struct {
accessKey string
secretKey string
}
func (s *signer) Sign(req *http.Request) error {
// API 签名机制:
// https://docs.dogecloud.com/cdn/api-access-token
path := req.URL.Path
queryStr := req.URL.Query().Encode()
if queryStr != "" {
path += "?" + queryStr
}
payloadStr := ""
if req.Body != nil {
payloadb, err := io.ReadAll(req.Body)
if err != nil {
return err
}
payloadStr = string(payloadb)
req.Body = io.NopCloser(bytes.NewReader(payloadb))
}
stringToSign := fmt.Sprintf("%s\n%s", path, payloadStr)
h := hmac.New(sha1.New, []byte(s.secretKey))
h.Write([]byte(stringToSign))
signature := hex.EncodeToString(h.Sum(nil))
authorization := fmt.Sprintf("TOKEN %s:%s", s.accessKey, signature)
req.Header.Set("Authorization", authorization)
return nil
}
-29
View File
@@ -1,29 +0,0 @@
package dogecloud
type sdkResponse interface {
GetCode() int
GetMessage() string
}
type sdkResponseBase struct {
Code *int `json:"code,omitempty"`
Message *string `json:"msg,omitempty"`
}
func (r *sdkResponseBase) GetCode() int {
if r.Code == nil {
return 0
}
return *r.Code
}
func (r *sdkResponseBase) GetMessage() string {
if r.Message == nil {
return ""
}
return *r.Message
}
var _ sdkResponse = (*sdkResponseBase)(nil)
@@ -60,7 +60,6 @@ import BizDeployNodeConfigFieldsProviderCTCCCloudELB from "./BizDeployNodeConfig
import BizDeployNodeConfigFieldsProviderCTCCCloudFaaS from "./BizDeployNodeConfigFieldsProviderCTCCCloudFaaS";
import BizDeployNodeConfigFieldsProviderCTCCCloudICDN from "./BizDeployNodeConfigFieldsProviderCTCCCloudICDN";
import BizDeployNodeConfigFieldsProviderCTCCCloudLVDN from "./BizDeployNodeConfigFieldsProviderCTCCCloudLVDN";
import BizDeployNodeConfigFieldsProviderDogeCloudCDN from "./BizDeployNodeConfigFieldsProviderDogeCloudCDN";
import BizDeployNodeConfigFieldsProviderFlexCDN from "./BizDeployNodeConfigFieldsProviderFlexCDN";
import BizDeployNodeConfigFieldsProviderFlyIO from "./BizDeployNodeConfigFieldsProviderFlyIO";
import BizDeployNodeConfigFieldsProviderFTP from "./BizDeployNodeConfigFieldsProviderFTP";
@@ -82,7 +81,6 @@ import BizDeployNodeConfigFieldsProviderJDCloudWAF from "./BizDeployNodeConfigFi
import BizDeployNodeConfigFieldsProviderKong from "./BizDeployNodeConfigFieldsProviderKong";
import BizDeployNodeConfigFieldsProviderKsyunCDN from "./BizDeployNodeConfigFieldsProviderKsyunCDN";
import BizDeployNodeConfigFieldsProviderKsyunSLB from "./BizDeployNodeConfigFieldsProviderKsyunSLB";
import BizDeployNodeConfigFieldsProviderKubernetesSecret from "./BizDeployNodeConfigFieldsProviderKubernetesSecret";
import BizDeployNodeConfigFieldsProviderLeCDN from "./BizDeployNodeConfigFieldsProviderLeCDN";
import BizDeployNodeConfigFieldsProviderLinodeLOS from "./BizDeployNodeConfigFieldsProviderLinodeLOS";
import BizDeployNodeConfigFieldsProviderLocal from "./BizDeployNodeConfigFieldsProviderLocal";
@@ -207,7 +205,6 @@ const providerComponentMap: Partial<Record<DeploymentProviderType, React.Compone
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_FAAS]: BizDeployNodeConfigFieldsProviderCTCCCloudFaaS,
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_ICDN]: BizDeployNodeConfigFieldsProviderCTCCCloudICDN,
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_LVDN]: BizDeployNodeConfigFieldsProviderCTCCCloudLVDN,
[DEPLOYMENT_PROVIDERS.DOGECLOUD_CDN]: BizDeployNodeConfigFieldsProviderDogeCloudCDN,
[DEPLOYMENT_PROVIDERS.FLEXCDN]: BizDeployNodeConfigFieldsProviderFlexCDN,
[DEPLOYMENT_PROVIDERS.FLYIO]: BizDeployNodeConfigFieldsProviderFlyIO,
[DEPLOYMENT_PROVIDERS.FTP]: BizDeployNodeConfigFieldsProviderFTP,
@@ -227,7 +224,6 @@ const providerComponentMap: Partial<Record<DeploymentProviderType, React.Compone
[DEPLOYMENT_PROVIDERS.JDCLOUD_VOD]: BizDeployNodeConfigFieldsProviderJDCloudVOD,
[DEPLOYMENT_PROVIDERS.JDCLOUD_WAF]: BizDeployNodeConfigFieldsProviderJDCloudWAF,
[DEPLOYMENT_PROVIDERS.KONG]: BizDeployNodeConfigFieldsProviderKong,
[DEPLOYMENT_PROVIDERS.KUBERNETES_SECRET]: BizDeployNodeConfigFieldsProviderKubernetesSecret,
[DEPLOYMENT_PROVIDERS.KSYUN_CDN]: BizDeployNodeConfigFieldsProviderKsyunCDN,
[DEPLOYMENT_PROVIDERS.KSYUN_SLB]: BizDeployNodeConfigFieldsProviderKsyunSLB,
[DEPLOYMENT_PROVIDERS.LECDN]: BizDeployNodeConfigFieldsProviderLeCDN,
@@ -1,98 +0,0 @@
import { getI18n, useTranslation } from "react-i18next";
import { Form, Input, Radio } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import Show from "@/components/Show";
import { isDomain } from "@/utils/validator";
import { useFormNestedFieldsContext } from "./_context";
const DOMAIN_MATCH_PATTERN_EXACT = "exact" as const;
const DOMAIN_MATCH_PATTERN_CERTSAN = "certsan" as const;
const BizDeployNodeConfigFieldsProviderDogeCloudCDN = () => {
const { i18n, t } = useTranslation();
const { parentNamePath } = useFormNestedFieldsContext();
const formSchema = z.object({
[parentNamePath]: getSchema({ i18n }),
});
const formRule = createSchemaFieldRule(formSchema);
const formInst = Form.useFormInstance();
const initialValues = getInitialValues();
const fieldDomainMatchPattern = Form.useWatch([parentNamePath, "domainMatchPattern"], { form: formInst, preserve: true });
return (
<>
<Form.Item
name={[parentNamePath, "domainMatchPattern"]}
initialValue={initialValues.domainMatchPattern}
label={t("workflow_node.deploy.form.shared_domain_match_pattern.label")}
rules={[formRule]}
>
<Radio.Group
options={[DOMAIN_MATCH_PATTERN_EXACT, DOMAIN_MATCH_PATTERN_CERTSAN].map((s) => ({
label: t(`workflow_node.deploy.form.shared_domain_match_pattern.option.${s}.label`),
value: s,
}))}
/>
</Form.Item>
<Show when={fieldDomainMatchPattern !== DOMAIN_MATCH_PATTERN_CERTSAN}>
<Form.Item
name={[parentNamePath, "domain"]}
initialValue={initialValues.domain}
label={t("workflow_node.deploy.form.dogecloud_cdn_domain.label")}
rules={[formRule]}
>
<Input placeholder={t("workflow_node.deploy.form.dogecloud_cdn_domain.placeholder")} />
</Form.Item>
</Show>
</>
);
};
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
return {
domainMatchPattern: DOMAIN_MATCH_PATTERN_EXACT,
domain: "",
};
};
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
const { t } = i18n;
return z
.object({
domainMatchPattern: z.string().nonempty().default(DOMAIN_MATCH_PATTERN_EXACT),
domain: z.string().nullish(),
})
.superRefine((values, ctx) => {
if (values.domainMatchPattern) {
switch (values.domainMatchPattern) {
case DOMAIN_MATCH_PATTERN_EXACT:
{
const scDomain = z.string().refine((v) => isDomain(v), t("common.errmsg.domain_invalid"));
const spDomain = scDomain.safeParse(values.domain);
if (!spDomain.success) {
ctx.addIssue({
code: "custom",
message: z.treeifyError(spDomain.error).errors.join(),
path: ["domain"],
});
}
}
break;
}
}
});
};
const _default = Object.assign(BizDeployNodeConfigFieldsProviderDogeCloudCDN, {
getInitialValues,
getSchema,
});
export default _default;
@@ -1,202 +0,0 @@
import { getI18n, useTranslation } from "react-i18next";
import { Form, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import CodeTextInput from "@/components/CodeTextInput";
import { useFormNestedFieldsContext } from "./_context";
const BizDeployNodeConfigFieldsProviderKubernetesSecret = () => {
const { i18n, t } = useTranslation();
const { parentNamePath } = useFormNestedFieldsContext();
const formSchema = z.object({
[parentNamePath]: getSchema({ i18n }),
});
const formRule = createSchemaFieldRule(formSchema);
const formInst = Form.useFormInstance();
const initialValues = getInitialValues();
const handleSecretAnnotationsBlur = () => {
let value = formInst.getFieldValue([parentNamePath, "secretAnnotations"]);
value = value.trim();
value = value.replace(/(?<!\r)\n/g, "\r\n");
formInst.setFieldValue([parentNamePath, "secretAnnotations"], value);
};
const handleSecretLabelsBlur = () => {
let value = formInst.getFieldValue([parentNamePath, "secretLabels"]);
value = value.trim();
value = value.replace(/(?<!\r)\n/g, "\r\n");
formInst.setFieldValue([parentNamePath, "secretLabels"], value);
};
return (
<>
<Form.Item
name={[parentNamePath, "namespace"]}
initialValue={initialValues.namespace}
label={t("workflow_node.deploy.form.k8s_namespace.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_namespace.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.k8s_namespace.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "secretName"]}
initialValue={initialValues.secretName}
label={t("workflow_node.deploy.form.k8s_secret_name.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_name.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_name.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "secretType"]}
initialValue={initialValues.secretType}
label={t("workflow_node.deploy.form.k8s_secret_type.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_type.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_type.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "secretDataKeyForKey"]}
initialValue={initialValues.secretDataKeyForKey}
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_key.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_data_key_for_key.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "secretDataKeyForCrt"]}
initialValue={initialValues.secretDataKeyForCrt}
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_crt.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_data_key_for_crt.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_crt.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "secretDataKeyForCrtOnlyServer"]}
initialValue={initialValues.secretDataKeyForCrtOnlyServer}
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_servercrt.label")}
extra={t("workflow_node.deploy.form.k8s_secret_data_key_for_servercrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_servercrt.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "secretDataKeyForCrtOnlyIntermedia"]}
initialValue={initialValues.secretDataKeyForCrtOnlyIntermedia}
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_intermediacrt.label")}
extra={t("workflow_node.deploy.form.k8s_secret_data_key_for_intermediacrt.help")}
rules={[formRule]}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_intermediacrt.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "secretAnnotations"]}
initialValue={initialValues.secretAnnotations}
label={t("workflow_node.deploy.form.k8s_secret_annotations.label")}
extra={t("workflow_node.deploy.form.k8s_secret_annotations.help")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_annotations.tooltip") }}></span>}
>
<CodeTextInput
lineWrapping={false}
height="auto"
minHeight="64px"
maxHeight="256px"
placeholder={t("workflow_node.deploy.form.k8s_secret_annotations.placeholder")}
onBlur={handleSecretAnnotationsBlur}
/>
</Form.Item>
<Form.Item
name={[parentNamePath, "secretLabels"]}
initialValue={initialValues.secretLabels}
label={t("workflow_node.deploy.form.k8s_secret_labels.label")}
extra={t("workflow_node.deploy.form.k8s_secret_labels.help")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_labels.tooltip") }}></span>}
>
<CodeTextInput
lineWrapping={false}
height="auto"
minHeight="64px"
maxHeight="256px"
placeholder={t("workflow_node.deploy.form.k8s_secret_labels.placeholder")}
onBlur={handleSecretLabelsBlur}
/>
</Form.Item>
</>
);
};
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
return {
namespace: "default",
secretType: "kubernetes.io/tls",
secretDataKeyForCrt: "tls.crt",
secretDataKeyForKey: "tls.key",
};
};
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
const { t } = i18n;
return z.object({
namespace: z.string().nonempty(),
secretName: z.string().nonempty(),
secretType: z.string().nonempty(),
secretDataKeyForCrt: z.string().nonempty(),
secretDataKeyForKey: z.string().nonempty(),
secretDataKeyForCrtOnlyServer: z.string().nullish(),
secretDataKeyForCrtOnlyIntermedia: z.string().nullish(),
secretAnnotations: z
.string()
.nullish()
.refine((v) => {
if (!v) return true;
const lines = v.split(/\r?\n/);
for (const line of lines) {
if (line.split(":").length < 2) {
return false;
}
}
return true;
}, t("workflow_node.deploy.form.k8s_secret_annotations.errmsg.invalid")),
secretLabels: z
.string()
.nullish()
.refine((v) => {
if (!v) return true;
const lines = v.split(/\r?\n/);
for (const line of lines) {
if (line.split(":").length < 2) {
return false;
}
}
return true;
}, t("workflow_node.deploy.form.k8s_secret_labels.errmsg.invalid")),
});
};
const _default = Object.assign(BizDeployNodeConfigFieldsProviderKubernetesSecret, {
getInitialValues,
getSchema,
});
export default _default;
-4
View File
@@ -664,7 +664,6 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
CTCCCLOUD_FAAS: `${ACCESS_PROVIDERS.CTCCCLOUD}-faas`,
CTCCCLOUD_ICDN: `${ACCESS_PROVIDERS.CTCCCLOUD}-icdn`,
CTCCCLOUD_LVDN: `${ACCESS_PROVIDERS.CTCCCLOUD}-lvdn`,
DOGECLOUD_CDN: `${ACCESS_PROVIDERS.DOGECLOUD}-cdn`,
DIGITALOCEAN_CERTIFICATE: `${ACCESS_PROVIDERS.DIGITALOCEAN}-certificate`,
DOKPLOY: `${ACCESS_PROVIDERS.DOKPLOY}`,
FLEXCDN: `${ACCESS_PROVIDERS.FLEXCDN}`,
@@ -689,7 +688,6 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
JDCLOUD_SSL: `${ACCESS_PROVIDERS.JDCLOUD}-ssl`,
JDCLOUD_WAF: `${ACCESS_PROVIDERS.JDCLOUD}-waf`,
KONG: `${ACCESS_PROVIDERS.KONG}`,
KUBERNETES_SECRET: `${ACCESS_PROVIDERS.KUBERNETES}-secret`,
KSYUN_CDN: `${ACCESS_PROVIDERS.KSYUN}-cdn`,
KSYUN_KCM: `${ACCESS_PROVIDERS.KSYUN}-kcm`,
KSYUN_SLB: `${ACCESS_PROVIDERS.KSYUN}-slb`,
@@ -790,7 +788,6 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
[DEPLOYMENT_PROVIDERS.LOCAL, "provider.local", DEPLOYMENT_CATEGORIES.OTHER, "builtin"],
[DEPLOYMENT_PROVIDERS.SSH, "provider.ssh", DEPLOYMENT_CATEGORIES.OTHER],
[DEPLOYMENT_PROVIDERS.FTP, "provider.ftp", DEPLOYMENT_CATEGORIES.OTHER],
[DEPLOYMENT_PROVIDERS.KUBERNETES_SECRET, "provider.kubernetes_secret", DEPLOYMENT_CATEGORIES.OTHER],
[DEPLOYMENT_PROVIDERS.WEBHOOK, "provider.webhook", DEPLOYMENT_CATEGORIES.OTHER],
[DEPLOYMENT_PROVIDERS.S3, "provider.s3_upload", DEPLOYMENT_CATEGORIES.STORAGE],
[DEPLOYMENT_PROVIDERS.ALIYUN_OSS, "provider.aliyun_oss", DEPLOYMENT_CATEGORIES.STORAGE],
@@ -905,7 +902,6 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
[DEPLOYMENT_PROVIDERS.UCLOUD_UEWAF, "provider.ucloud_uewaf", DEPLOYMENT_CATEGORIES.FIREWALL],
[DEPLOYMENT_PROVIDERS.UCLOUD_UPATHX, "provider.ucloud_upathx", DEPLOYMENT_CATEGORIES.ACCELERATOR],
[DEPLOYMENT_PROVIDERS.BAISHAN_CDN, "provider.baishan_cdn", DEPLOYMENT_CATEGORIES.CDN],
[DEPLOYMENT_PROVIDERS.DOGECLOUD_CDN, "provider.dogecloud_cdn", DEPLOYMENT_CATEGORIES.CDN],
[DEPLOYMENT_PROVIDERS.WANGSU_CDN, "provider.wangsu_cdn", DEPLOYMENT_CATEGORIES.CDN],
[DEPLOYMENT_PROVIDERS.WANGSU_CDNPRO, "provider.wangsu_cdnpro", DEPLOYMENT_CATEGORIES.CDN],
[DEPLOYMENT_PROVIDERS.WANGSU_CERTIFICATE, "provider.wangsu_certificate_upload", DEPLOYMENT_CATEGORIES.SSL],
@@ -141,7 +141,6 @@
"dnsexit": "DNSExit",
"dnsla": "DNS.LA",
"dnsmadeeasy": "DNS Made Easy",
"dogecloud_cdn": "Doge Cloud - CDN (Content Delivery Network)",
"dogecloud": "Doge Cloud",
"dokploy": "Dokploy",
"duckdns": "Duck DNS",
@@ -190,7 +189,6 @@
"jdcloud_waf": "JD Cloud - WAF (Web Application Firewall)",
"kong": "Kong",
"kubernetes": "Kubernetes",
"kubernetes_secret": "Kubernetes - Secret",
"ksyun": "Kingsoft Cloud",
"ksyun_cdn": "Kingsoft Cloud - CDN (Content Delivery Network)",
"ksyun_kcm_upload": "Kingsoft Cloud - Upload to KCM (SSL Certificate Manager)",
@@ -1544,10 +1544,6 @@
"label": "CTCC StateCloud LVDN domain",
"placeholder": "Please enter CTCC StateCloud LVDN domain name"
},
"dogecloud_cdn_domain": {
"label": "Doge Cloud CDN domain",
"placeholder": "Please enter Doge Cloud CDN domain name"
},
"flexcdn_deploy_target": {
"option": {
"certificate": {
@@ -1779,59 +1775,6 @@
"label": "JD Cloud WAF domain",
"placeholder": "Please enter JD Cloud WAF domain name"
},
"k8s_namespace": {
"label": "Kubernetes Namespace",
"placeholder": "Please enter Kubernetes Namespace",
"tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/\" target=\"_blank\">https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/</a>"
},
"k8s_secret_name": {
"label": "Kubernetes Secret name",
"placeholder": "Please enter Kubernetes Secret name",
"tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>"
},
"k8s_secret_type": {
"label": "Kubernetes Secret type",
"placeholder": "Please enter Kubernetes Secret type",
"tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>"
},
"k8s_secret_data_key_for_key": {
"label": "Kubernetes Secret data key for private key",
"placeholder": "Please enter Kubernetes Secret data key for private key",
"tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>"
},
"k8s_secret_data_key_for_crt": {
"label": "Kubernetes Secret data key for certificate",
"placeholder": "Please enter Kubernetes Secret data key for certificate",
"tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>"
},
"k8s_secret_data_key_for_servercrt": {
"label": "Kubernetes Secret data key for certificate (includes the end-entity parts only) (Optional)",
"placeholder": "Please enter Kubernetes Secret data key for server certificate",
"help": ""
},
"k8s_secret_data_key_for_intermediacrt": {
"label": "Kubernetes Secret data key for certificate (includes the CA parts only) (Optional)",
"placeholder": "Please enter Kubernetes Secret data key for intermediate certificate",
"help": ""
},
"k8s_secret_annotations": {
"label": "Kubernetes Secret annotations (Optional)",
"placeholder": "Please enter Kubernetes Secret annotations",
"help": "Notes: One key value pair per line, separated by colon.",
"errmsg": {
"invalid": "Invalid annotations"
},
"tooltip": "Example: <br><i>environment: production<br>app: nginx</i>"
},
"k8s_secret_labels": {
"label": "Kubernetes Secret labels (Optional)",
"placeholder": "Please enter Kubernetes Secret labels",
"help": "Notes: One key value pair per line, separated by colon.",
"errmsg": {
"invalid": "Invalid labels"
},
"tooltip": "Example: <br><i>environment: production<br>app: nginx</i>"
},
"kong": {
"guide": "Requires Kong v2.0 or higher."
},
@@ -142,7 +142,6 @@
"dnsla": "帝恩爱斯(DNS.LA)",
"dnsmadeeasy": "DNS Made Easy",
"dogecloud": "多吉云",
"dogecloud_cdn": "多吉云 - 内容分发网络 CDN",
"dokploy": "Dokploy",
"duckdns": "Duck DNS",
"dynadot": "Dynadot",
@@ -190,7 +189,6 @@
"jdcloud_waf": "京东云 - Web 应用防火墙 WAF",
"kong": "Kong",
"kubernetes": "Kubernetes",
"kubernetes_secret": "Kubernetes - Secret",
"ksyun": "金山云",
"ksyun_cdn": "金山云 - 内容分发网络 CDN",
"ksyun_kcm_upload": "金山云 - 上传到 SSL 证书管理",
@@ -1543,10 +1543,6 @@
"label": "天翼云 LVDN 加速域名",
"placeholder": "请输入天翼云 LVDN 加速域名"
},
"dogecloud_cdn_domain": {
"label": "多吉云 CDN 加速域名",
"placeholder": "请输入多吉云 CDN 加速域名"
},
"flexcdn_deploy_target": {
"option": {
"certificate": {
@@ -1778,59 +1774,6 @@
"label": "京东云 WAF 防护域名",
"placeholder": "请输入京东云 WAF 防护域名"
},
"k8s_namespace": {
"label": "Kubernetes 命名空间",
"placeholder": "请输入 Kubernetes 命名空间",
"tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/</a>"
},
"k8s_secret_name": {
"label": "Kubernetes Secret 名称",
"placeholder": "请输入 Kubernetes Secret 名称",
"tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>"
},
"k8s_secret_type": {
"label": "Kubernetes Secret 类型",
"placeholder": "请输入 Kubernetes Secret 类型",
"tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>"
},
"k8s_secret_data_key_for_key": {
"label": "Kubernetes Secret 数据键(用于存放私钥的字段)",
"placeholder": "请输入 Kubernetes Secret 中用于存放私钥的数据键",
"tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>"
},
"k8s_secret_data_key_for_crt": {
"label": "Kubernetes Secret 数据键之存放证书的字段",
"placeholder": "请输入 Kubernetes Secret 中用于存放证书的数据键",
"tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>"
},
"k8s_secret_data_key_for_servercrt": {
"label": "Kubernetes Secret 数据键之存放仅服务器证书的字段(可选)",
"placeholder": "请输入 Kubernetes Secret 中用于存放服务器证书的数据键",
"help": "提示:不填写时将不会保存服务器证书。"
},
"k8s_secret_data_key_for_intermediacrt": {
"label": "Kubernetes Secret 数据键之存放仅中间证书的字段(可选)",
"placeholder": "请输入 Kubernetes Secret 中用于存放中间证书的数据键",
"help": "提示:不填写时将不会保存中间证书。"
},
"k8s_secret_annotations": {
"label": "Kubernetes Secret 注解(可选)",
"placeholder": "请输入 Kubernetes Secret 注解",
"help": "提示:每行一个键值对,以分号分隔。",
"errmsg": {
"invalid": "无效的注解键值对"
},
"tooltip": "示例:<br><i>environment: production<br>app: nginx</i>"
},
"k8s_secret_labels": {
"label": "Kubernetes Secret 标签(可选)",
"placeholder": "请输入 Kubernetes Secret 标签",
"help": "提示:每行一个键值对,以分号分隔。",
"errmsg": {
"invalid": "无效的标签键值对"
},
"tooltip": "示例:<br><i>environment: production<br>app: nginx</i>"
},
"kong": {
"guide": "需要 Kong v2.0 或更高版本。"
},