refactor(provider): re-implement apisix deployment provider

This commit is contained in:
Fu Diwei 2025-11-17 20:30:56 +08:00
parent 84109a760c
commit ef8df2d9b1
6 changed files with 27 additions and 171 deletions

1
go.mod
View File

@ -46,6 +46,7 @@ require (
github.com/go-resty/resty/v2 v2.16.5
github.com/go-viper/mapstructure/v2 v2.4.0
github.com/google/go-querystring v1.1.0
github.com/holubovskyi/apisix-client-go v1.4.1
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.175
github.com/jdcloud-api/jdcloud-sdk-go v1.64.0
github.com/kong/go-kong v0.69.0

2
go.sum
View File

@ -531,6 +531,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/holubovskyi/apisix-client-go v1.4.1 h1:Z0Vqfubo0nleuChfLcsWLr/ZQ1J3+g4UMttfAx/8E9Y=
github.com/holubovskyi/apisix-client-go v1.4.1/go.mod h1:MYo1juyaHbX6RWe9S3DoqWqL0Ko/2pr3ZpDQVNKVXqI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.175 h1:J7R4aqAplVyrcHqgFANTB7G3p+FvK4mKBWNcOZDg/fg=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.175/go.mod h1:M+yna96Fx9o5GbIUnF3OvVvQGjgfVSyeJbV9Yb1z/wI=

View File

@ -7,11 +7,12 @@ import (
"fmt"
"log/slog"
apisix "github.com/holubovskyi/apisix-client-go"
"github.com/samber/lo"
"github.com/certimate-go/certimate/pkg/core/deployer"
apisixsdk "github.com/certimate-go/certimate/pkg/sdk3rd/apisix"
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
xhttp "github.com/certimate-go/certimate/pkg/utils/http"
)
type DeployerConfig struct {
@ -31,7 +32,7 @@ type DeployerConfig struct {
type Deployer struct {
config *DeployerConfig
logger *slog.Logger
sdkClient *apisixsdk.Client
sdkClient *apisix.ApiClient
}
var _ deployer.Provider = (*Deployer)(nil)
@ -89,30 +90,39 @@ func (d *Deployer) deployToCertificate(ctx context.Context, certPEM string, priv
// 更新 SSL 证书
// REF: https://apisix.apache.org/zh/docs/apisix/admin-api/#ssl
updateSSLReq := &apisixsdk.UpdateSSLRequest{
Cert: lo.ToPtr(certPEM),
Key: lo.ToPtr(privkeyPEM),
SNIs: lo.ToPtr(certX509.DNSNames),
Type: lo.ToPtr("server"),
Status: lo.ToPtr(int32(1)),
updateSSLCertificateReq := &apisix.SSLCertificate{
ID: lo.ToPtr(d.config.CertificateId),
Certificate: lo.ToPtr(certPEM),
PrivateKey: lo.ToPtr(privkeyPEM),
SNIs: lo.ToPtr(certX509.DNSNames),
Type: lo.ToPtr("server"),
Status: lo.ToPtr(int64(1)),
}
updateSSLResp, err := d.sdkClient.UpdateSSL(d.config.CertificateId, updateSSLReq)
d.logger.Debug("sdk request 'apisix.UpdateSSL'", slog.String("sslId", d.config.CertificateId), slog.Any("request", updateSSLReq), slog.Any("response", updateSSLResp))
updateSSLCertificateResp, err := d.sdkClient.UpdateSslCertificate(d.config.CertificateId, *updateSSLCertificateReq)
d.logger.Debug("sdk request 'apisix.UpdateSslCertificate'", slog.Any("request", updateSSLCertificateReq), slog.Any("response", updateSSLCertificateResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'apisix.UpdateSSL': %w", err)
return fmt.Errorf("failed to execute sdk request 'apisix.UpdateSslCertificate': %w", err)
}
return nil
}
func createSDKClient(serverUrl, apiKey string, skipTlsVerify bool) (*apisixsdk.Client, error) {
client, err := apisixsdk.NewClient(serverUrl, apiKey)
func createSDKClient(serverUrl, apiKey string, skipTlsVerify bool) (*apisix.ApiClient, error) {
client, err := apisix.NewClient(&serverUrl, &apiKey)
if err != nil {
return nil, err
}
if skipTlsVerify {
client.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
transport := xhttp.NewDefaultTransport()
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
if client.HTTPClient.Transport == nil {
client.HTTPClient.Transport = transport
} else {
transport := client.HTTPClient.Transport.(*apisix.AddHeadersRoundtripper)
transport.Nested = transport
client.HTTPClient.Transport = transport
}
}
return client, nil

View File

@ -1,44 +0,0 @@
package apisix
import (
"context"
"fmt"
"net/http"
)
type UpdateSSLRequest struct {
Cert *string `json:"cert,omitempty"`
Key *string `json:"key,omitempty"`
SNIs *[]string `json:"snis,omitempty"`
Type *string `json:"type,omitempty"`
Status *int32 `json:"status,omitempty"`
}
type UpdateSSLResponse struct {
apiResponseBase
}
func (c *Client) UpdateSSL(sslId string, req *UpdateSSLRequest) (*UpdateSSLResponse, error) {
return c.UpdateSSLWithContext(context.Background(), sslId, req)
}
func (c *Client) UpdateSSLWithContext(ctx context.Context, sslId string, req *UpdateSSLRequest) (*UpdateSSLResponse, error) {
if sslId == "" {
return nil, fmt.Errorf("sdkerr: unset sslId")
}
httpreq, err := c.newRequest(http.MethodPut, fmt.Sprintf("/ssls/%s", sslId))
if err != nil {
return nil, err
} else {
httpreq.SetBody(req)
httpreq.SetContext(ctx)
}
result := &UpdateSSLResponse{}
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
return result, nil
}

View File

@ -1,106 +0,0 @@
package apisix
import (
"crypto/tls"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/go-resty/resty/v2"
)
type Client struct {
client *resty.Client
}
func NewClient(serverUrl, apiKey string) (*Client, error) {
if serverUrl == "" {
return nil, fmt.Errorf("sdkerr: unset serverUrl")
}
if _, err := url.Parse(serverUrl); err != nil {
return nil, fmt.Errorf("sdkerr: invalid serverUrl: %w", err)
}
if apiKey == "" {
return nil, fmt.Errorf("sdkerr: unset apiKey")
}
client := resty.New().
SetBaseURL(strings.TrimRight(serverUrl, "/")+"/apisix/admin").
SetHeader("Accept", "application/json").
SetHeader("Content-Type", "application/json").
SetHeader("User-Agent", "certimate").
SetPreRequestHook(func(c *resty.Client, req *http.Request) error {
req.Header.Set("X-API-KEY", apiKey)
return nil
})
return &Client{client}, nil
}
func (c *Client) SetTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout)
return c
}
func (c *Client) SetTLSConfig(config *tls.Config) *Client {
c.client.SetTLSClientConfig(config)
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.client.R()
req.Method = method
req.URL = path
return req, nil
}
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
if req == nil {
return nil, fmt.Errorf("sdkerr: nil request")
}
// WARN:
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
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 apiResponse) (*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", err)
}
}
return resp, nil
}

View File

@ -1,7 +0,0 @@
package apisix
type apiResponse interface{}
type apiResponseBase struct{}
var _ apiResponse = (*apiResponseBase)(nil)