feat: support configuring multiple domains deployment to tencentcloud edgeone

This commit is contained in:
吃瓜的星核精 2025-07-08 21:22:29 +08:00 committed by GitHub
parent b43fcc3b61
commit 1e4cd2b9d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 159 additions and 30 deletions

View File

@ -1202,7 +1202,7 @@ func createSSLDeployerProvider(options *deployerProviderOptions) (core.SSLDeploy
SecretKey: access.SecretKey, SecretKey: access.SecretKey,
Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"), Endpoint: xmaps.GetString(options.ProviderServiceConfig, "endpoint"),
ZoneId: xmaps.GetString(options.ProviderServiceConfig, "zoneId"), ZoneId: xmaps.GetString(options.ProviderServiceConfig, "zoneId"),
Domain: xmaps.GetString(options.ProviderServiceConfig, "domain"), Domains: xslices.Filter(strings.Split(xmaps.GetString(options.ProviderServiceConfig, "domains"), ";"), func(s string) bool { return s != "" }),
}) })
return deployer, err return deployer, err

View File

@ -270,12 +270,12 @@ func init() {
Id string `json:"id"` Id string `json:"id"`
Type string `json:"type"` Type string `json:"type"`
Name string `json:"name"` Name string `json:"name"`
Config map[string]any `json:"config"` Config map[string]any `json:"config,omitempty"`
Inputs []map[string]any `json:"inputs"` Inputs []map[string]any `json:"inputs,omitempty"`
Outputs []map[string]any `json:"outputs"` Outputs []map[string]any `json:"outputs,omitempty"`
Next *dWorkflowNode `json:"next,omitempty"` Next *dWorkflowNode `json:"next,omitempty"`
Branches []dWorkflowNode `json:"branches,omitempty"` Branches []*dWorkflowNode `json:"branches,omitempty"`
Validated bool `json:"validated"` Validated bool `json:"validated,omitempty"`
} }
for _, workflowRun := range workflowRuns { for _, workflowRun := range workflowRuns {

View File

@ -0,0 +1,112 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
tracer := NewTracer("(v0.3)1751961600")
tracer.Printf("go ...")
// migrate data
{
workflows, err := app.FindAllRecords("workflow")
if err != nil {
return err
}
type dWorkflowNode struct {
Id string `json:"id"`
Type string `json:"type"`
Name string `json:"name"`
Config map[string]any `json:"config,omitempty"`
Inputs []map[string]any `json:"inputs,omitempty"`
Outputs []map[string]any `json:"outputs,omitempty"`
Next *dWorkflowNode `json:"next,omitempty"`
Branches []*dWorkflowNode `json:"branches,omitempty"`
Validated bool `json:"validated,omitempty"`
}
deepChangeFn := func(node *dWorkflowNode) bool {
stack := []*dWorkflowNode{node}
for len(stack) > 0 {
current := stack[len(stack)-1]
stack = stack[:len(stack)-1]
if current.Type == "deploy" {
configMap := current.Config
if configMap != nil {
if provider, ok := configMap["provider"]; ok {
if provider.(string) == "tencentcloud-eo" {
if providerConfig, ok := configMap["providerConfig"]; ok {
if providerConfigMap, ok := providerConfig.(map[string]any); ok {
if _, ok := providerConfigMap["domain"]; ok {
providerConfigMap["domains"] = providerConfigMap["domain"]
delete(providerConfigMap, "domain")
configMap["providerConfig"] = providerConfigMap
return true
}
}
}
}
}
}
}
if current.Next != nil {
stack = append(stack, current.Next)
}
if current.Branches != nil {
for i := len(current.Branches) - 1; i >= 0; i-- {
stack = append(stack, current.Branches[i])
}
}
}
return false
}
for _, workflow := range workflows {
changed := false
rootNodeContent := &dWorkflowNode{}
if err := workflow.UnmarshalJSONField("content", rootNodeContent); err != nil {
return err
} else {
if deepChangeFn(rootNodeContent) {
workflow.Set("content", rootNodeContent)
changed = true
}
}
rootNodeDraft := &dWorkflowNode{}
if err := workflow.UnmarshalJSONField("draft", rootNodeDraft); err != nil {
return err
} else {
if deepChangeFn(rootNodeDraft) {
workflow.Set("draft", rootNodeDraft)
changed = true
}
}
if changed {
err = app.Save(workflow)
if err != nil {
return err
}
tracer.Printf("record #%s in collection '%s' updated", workflow.Id, workflow.Collection().Name)
}
}
}
tracer.Printf("done")
return nil
}, func(app core.App) error {
return nil
})
}

View File

@ -25,8 +25,8 @@ type SSLDeployerProviderConfig struct {
Endpoint string `json:"endpoint,omitempty"` Endpoint string `json:"endpoint,omitempty"`
// 站点 ID。 // 站点 ID。
ZoneId string `json:"zoneId"` ZoneId string `json:"zoneId"`
// 加速域名(支持泛域名)。 // 加速域名列表(支持泛域名)。
Domain string `json:"domain"` Domains []string `json:"domains"`
} }
type SSLDeployerProvider struct { type SSLDeployerProvider struct {
@ -82,8 +82,8 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
if d.config.ZoneId == "" { if d.config.ZoneId == "" {
return nil, errors.New("config `zoneId` is required") return nil, errors.New("config `zoneId` is required")
} }
if d.config.Domain == "" { if len(d.config.Domains) == 0 {
return nil, errors.New("config `domain` is required") return nil, errors.New("config `domains` is required")
} }
// 上传证书 // 上传证书
@ -99,7 +99,7 @@ func (d *SSLDeployerProvider) Deploy(ctx context.Context, certPEM string, privke
modifyHostsCertificateReq := tcteo.NewModifyHostsCertificateRequest() modifyHostsCertificateReq := tcteo.NewModifyHostsCertificateRequest()
modifyHostsCertificateReq.ZoneId = common.StringPtr(d.config.ZoneId) modifyHostsCertificateReq.ZoneId = common.StringPtr(d.config.ZoneId)
modifyHostsCertificateReq.Mode = common.StringPtr("sslcert") modifyHostsCertificateReq.Mode = common.StringPtr("sslcert")
modifyHostsCertificateReq.Hosts = common.StringPtrs([]string{d.config.Domain}) modifyHostsCertificateReq.Hosts = common.StringPtrs(d.config.Domains)
modifyHostsCertificateReq.ServerCertInfo = []*tcteo.ServerCertInfo{{CertId: common.StringPtr(upres.CertId)}} modifyHostsCertificateReq.ServerCertInfo = []*tcteo.ServerCertInfo{{CertId: common.StringPtr(upres.CertId)}}
modifyHostsCertificateResp, err := d.sdkClient.ModifyHostsCertificate(modifyHostsCertificateReq) modifyHostsCertificateResp, err := d.sdkClient.ModifyHostsCertificate(modifyHostsCertificateReq)
d.logger.Debug("sdk request 'teo.ModifyHostsCertificate'", slog.Any("request", modifyHostsCertificateReq), slog.Any("response", modifyHostsCertificateResp)) d.logger.Debug("sdk request 'teo.ModifyHostsCertificate'", slog.Any("request", modifyHostsCertificateReq), slog.Any("response", modifyHostsCertificateResp))

View File

@ -17,7 +17,7 @@ var (
fSecretId string fSecretId string
fSecretKey string fSecretKey string
fZoneId string fZoneId string
fDomain string fDomains string
) )
func init() { func init() {
@ -28,7 +28,7 @@ func init() {
flag.StringVar(&fSecretId, argsPrefix+"SECRETID", "", "") flag.StringVar(&fSecretId, argsPrefix+"SECRETID", "", "")
flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "") flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "")
flag.StringVar(&fZoneId, argsPrefix+"ZONEID", "", "") flag.StringVar(&fZoneId, argsPrefix+"ZONEID", "", "")
flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") flag.StringVar(&fDomains, argsPrefix+"DOMAINS", "", "")
} }
/* /*
@ -40,7 +40,7 @@ Shell command to run this test:
--CERTIMATE_SSLDEPLOYER_TENCENTCLOUDEO_SECRETID="your-secret-id" \ --CERTIMATE_SSLDEPLOYER_TENCENTCLOUDEO_SECRETID="your-secret-id" \
--CERTIMATE_SSLDEPLOYER_TENCENTCLOUDEO_SECRETKEY="your-secret-key" \ --CERTIMATE_SSLDEPLOYER_TENCENTCLOUDEO_SECRETKEY="your-secret-key" \
--CERTIMATE_SSLDEPLOYER_TENCENTCLOUDEO_ZONEID="your-zone-id" \ --CERTIMATE_SSLDEPLOYER_TENCENTCLOUDEO_ZONEID="your-zone-id" \
--CERTIMATE_SSLDEPLOYER_TENCENTCLOUDEO_DOMAIN="example.com" --CERTIMATE_SSLDEPLOYER_TENCENTCLOUDEO_DOMAINS="example.com"
*/ */
func TestDeploy(t *testing.T) { func TestDeploy(t *testing.T) {
flag.Parse() flag.Parse()
@ -53,14 +53,14 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("SECRETID: %v", fSecretId), fmt.Sprintf("SECRETID: %v", fSecretId),
fmt.Sprintf("SECRETKEY: %v", fSecretKey), fmt.Sprintf("SECRETKEY: %v", fSecretKey),
fmt.Sprintf("ZONEID: %v", fZoneId), fmt.Sprintf("ZONEID: %v", fZoneId),
fmt.Sprintf("DOMAIN: %v", fDomain), fmt.Sprintf("DOMAINS: %v", fDomains),
}, "\n")) }, "\n"))
deployer, err := provider.NewSSLDeployerProvider(&provider.SSLDeployerProviderConfig{ deployer, err := provider.NewSSLDeployerProvider(&provider.SSLDeployerProviderConfig{
SecretId: fSecretId, SecretId: fSecretId,
SecretKey: fSecretKey, SecretKey: fSecretKey,
ZoneId: fZoneId, ZoneId: fZoneId,
Domain: fDomain, Domains: strings.Split(fDomains, ";"),
}) })
if err != nil { if err != nil {
t.Errorf("err: %+v", err) t.Errorf("err: %+v", err)

View File

@ -4,11 +4,12 @@ import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod/v4"; import { z } from "zod/v4";
import { validDomainName } from "@/utils/validators"; import { validDomainName } from "@/utils/validators";
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
type DeployNodeConfigFormTencentCloudEOConfigFieldValues = Nullish<{ type DeployNodeConfigFormTencentCloudEOConfigFieldValues = Nullish<{
endpoint?: string; endpoint?: string;
zoneId: string; zoneId: string;
domain: string; domains: string;
}>; }>;
export type DeployNodeConfigFormTencentCloudEOConfigProps = { export type DeployNodeConfigFormTencentCloudEOConfigProps = {
@ -23,6 +24,8 @@ const initFormModel = (): DeployNodeConfigFormTencentCloudEOConfigFieldValues =>
return {}; return {};
}; };
const MULTIPLE_INPUT_SEPARATOR = ";";
const DeployNodeConfigFormTencentCloudEOConfig = ({ const DeployNodeConfigFormTencentCloudEOConfig = ({
form: formInst, form: formInst,
formName, formName,
@ -37,9 +40,14 @@ const DeployNodeConfigFormTencentCloudEOConfig = ({
zoneId: z zoneId: z
.string(t("workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder")) .string(t("workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder"))
.nonempty(t("workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder")), .nonempty(t("workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder")),
domain: z domains: z
.string(t("workflow_node.deploy.form.tencentcloud_eo_domain.placeholder")) .string(t("workflow_node.deploy.form.tencentcloud_eo_domains.placeholder"))
.refine((v) => validDomainName(v, { allowWildcard: true }), t("common.errmsg.domain_invalid")), .refine((v) => {
if (!v) return false;
return String(v)
.split(MULTIPLE_INPUT_SEPARATOR)
.every((e) => validDomainName(e, { allowWildcard: true }));
}, t("common.errmsg.domain_invalid")),
}); });
const formRule = createSchemaFieldRule(formSchema); const formRule = createSchemaFieldRule(formSchema);
@ -75,12 +83,17 @@ const DeployNodeConfigFormTencentCloudEOConfig = ({
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="domain" name="domains"
label={t("workflow_node.deploy.form.tencentcloud_eo_domain.label")} label={t("workflow_node.deploy.form.tencentcloud_eo_domains.label")}
rules={[formRule]} rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_eo_domain.tooltip") }}></span>} tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_eo_domains.tooltip") }}></span>}
> >
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_eo_domain.placeholder")} /> <MultipleSplitValueInput
modalTitle={t("workflow_node.deploy.form.tencentcloud_eo_domains.multiple_input_modal.title")}
placeholder={t("workflow_node.deploy.form.tencentcloud_eo_domains.placeholder")}
placeholderInModal={t("workflow_node.deploy.form.tencentcloud_eo_domains.multiple_input_modal.placeholder")}
splitOptions={{ trim: true, removeEmpty: true }}
/>
</Form.Item> </Form.Item>
</Form> </Form>
); );

View File

@ -727,9 +727,11 @@
"workflow_node.deploy.form.tencentcloud_eo_zone_id.label": "Tencent Cloud EdgeOne zone ID", "workflow_node.deploy.form.tencentcloud_eo_zone_id.label": "Tencent Cloud EdgeOne zone ID",
"workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder": "Please enter Tencent Cloud EdgeOne zone ID", "workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder": "Please enter Tencent Cloud EdgeOne zone ID",
"workflow_node.deploy.form.tencentcloud_eo_zone_id.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/edgeone\" target=\"_blank\">https://console.tencentcloud.com/edgeone</a>", "workflow_node.deploy.form.tencentcloud_eo_zone_id.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/edgeone\" target=\"_blank\">https://console.tencentcloud.com/edgeone</a>",
"workflow_node.deploy.form.tencentcloud_eo_domain.label": "Tencent Cloud EdgeOne domain", "workflow_node.deploy.form.tencentcloud_eo_domains.label": "Tencent Cloud EdgeOne domains",
"workflow_node.deploy.form.tencentcloud_eo_domain.placeholder": "Please enter Tencent Cloud EdgeOne domain name", "workflow_node.deploy.form.tencentcloud_eo_domains.placeholder": "Please enter Tencent Cloud EdgeOne domain names (separated by semicolons)",
"workflow_node.deploy.form.tencentcloud_eo_domain.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/edgeone\" target=\"_blank\">https://console.tencentcloud.com/edgeone</a>", "workflow_node.deploy.form.tencentcloud_eo_domains.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/edgeone\" target=\"_blank\">https://console.tencentcloud.com/edgeone</a>",
"workflow_node.deploy.form.tencentcloud_eo_domains.multiple_input_modal.title": "Change Tencent Cloud EdgeOne domain",
"workflow_node.deploy.form.tencentcloud_eo_domains.multiple_input_modal.placeholder": "Please enter Tencent Cloud EdgeOne domain name",
"workflow_node.deploy.form.tencentcloud_gaap_endpoint.label": "Tencent Cloud GAAP API endpoint (Optional)", "workflow_node.deploy.form.tencentcloud_gaap_endpoint.label": "Tencent Cloud GAAP API endpoint (Optional)",
"workflow_node.deploy.form.tencentcloud_gaap_endpoint.placeholder": "Please enter Tencent Cloud GAAP API endpoint (e.g. gaap.intl.tencentcloudapi.com)", "workflow_node.deploy.form.tencentcloud_gaap_endpoint.placeholder": "Please enter Tencent Cloud GAAP API endpoint (e.g. gaap.intl.tencentcloudapi.com)",
"workflow_node.deploy.form.tencentcloud_gaap_endpoint.tooltip": "<ul style=\"margin-left: 1.25em; list-style: disc;\"><li><strong>gaap.intl.tencentcloudapi.com</strong> for Tencent Cloud International</li><li><strong>gaap.tencentcloudapi.com</strong> for Tencent Cloud in China</li></ul>", "workflow_node.deploy.form.tencentcloud_gaap_endpoint.tooltip": "<ul style=\"margin-left: 1.25em; list-style: disc;\"><li><strong>gaap.intl.tencentcloudapi.com</strong> for Tencent Cloud International</li><li><strong>gaap.tencentcloudapi.com</strong> for Tencent Cloud in China</li></ul>",

View File

@ -725,9 +725,11 @@
"workflow_node.deploy.form.tencentcloud_eo_zone_id.label": "腾讯云 EdgeOne 站点 ID", "workflow_node.deploy.form.tencentcloud_eo_zone_id.label": "腾讯云 EdgeOne 站点 ID",
"workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder": "请输入腾讯云 EdgeOne 站点 ID", "workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder": "请输入腾讯云 EdgeOne 站点 ID",
"workflow_node.deploy.form.tencentcloud_eo_zone_id.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/edgeone\" target=\"_blank\">https://console.cloud.tencent.com/edgeone</a>", "workflow_node.deploy.form.tencentcloud_eo_zone_id.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/edgeone\" target=\"_blank\">https://console.cloud.tencent.com/edgeone</a>",
"workflow_node.deploy.form.tencentcloud_eo_domain.label": "腾讯云 EdgeOne 加速域名", "workflow_node.deploy.form.tencentcloud_eo_domains.label": "腾讯云 EdgeOne 加速域名",
"workflow_node.deploy.form.tencentcloud_eo_domain.placeholder": "请输入腾讯云 EdgeOne 加速域名(支持泛域名)", "workflow_node.deploy.form.tencentcloud_eo_domains.placeholder": "请输入腾讯云 EdgeOne 加速域名(支持泛域名;多个值请用半角分号隔开)",
"workflow_node.deploy.form.tencentcloud_eo_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/edgeone\" target=\"_blank\">https://console.cloud.tencent.com/edgeone</a>", "workflow_node.deploy.form.tencentcloud_eo_domains.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/edgeone\" target=\"_blank\">https://console.cloud.tencent.com/edgeone</a>",
"workflow_node.deploy.form.tencentcloud_eo_domains.multiple_input_modal.title": "修改腾讯云 EdgeOne 加速域名",
"workflow_node.deploy.form.tencentcloud_eo_domains.multiple_input_modal.placeholder": "请输入腾讯云 EdgeOne 加速域名(支持泛域名)",
"workflow_node.deploy.form.tencentcloud_gaap_endpoint.label": "腾讯云 GAAP 接口端点(可选)", "workflow_node.deploy.form.tencentcloud_gaap_endpoint.label": "腾讯云 GAAP 接口端点(可选)",
"workflow_node.deploy.form.tencentcloud_gaap_endpoint.placeholder": "请输入腾讯云 GAAP 接口端点例如gaap.tencentcloudapi.com", "workflow_node.deploy.form.tencentcloud_gaap_endpoint.placeholder": "请输入腾讯云 GAAP 接口端点例如gaap.tencentcloudapi.com",
"workflow_node.deploy.form.tencentcloud_gaap_endpoint.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/608/36934\" target=\"_blank\">https://cloud.tencent.com/document/product/608/36934</a><br><br>国际站用户请填写 <em>gaap.intl.tencentcloudapi.com</em>。", "workflow_node.deploy.form.tencentcloud_gaap_endpoint.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/608/36934\" target=\"_blank\">https://cloud.tencent.com/document/product/608/36934</a><br><br>国际站用户请填写 <em>gaap.intl.tencentcloudapi.com</em>。",