mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-03 06:23:54 +08:00
feat(provider): new deployment provider: axisnow
This commit is contained in:
24
internal/certmgmt/deployers/sp_axisnow.go
Normal file
24
internal/certmgmt/deployers/sp_axisnow.go
Normal file
@@ -0,0 +1,24 @@
|
||||
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/axisnow"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Registries.MustRegister(domain.DeploymentProviderTypeAxisNow, func(options *ProviderFactoryOptions) (core.Deployer, error) {
|
||||
credentials := domain.AccessConfigForAxisNow{}
|
||||
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{
|
||||
ApiToken: credentials.ApiToken,
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
}
|
||||
@@ -87,6 +87,10 @@ type AccessConfigForAWS struct {
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
}
|
||||
|
||||
type AccessConfigForAxisNow struct {
|
||||
ApiToken string `json:"apiToken"`
|
||||
}
|
||||
|
||||
type AccessConfigForAzure struct {
|
||||
TenantId string `json:"tenantId"`
|
||||
ClientId string `json:"clientId"`
|
||||
|
||||
@@ -25,6 +25,7 @@ const (
|
||||
AccessProviderTypeAPISIX = AccessProviderType("apisix")
|
||||
AccessProviderTypeArvanCloud = AccessProviderType("arvancloud")
|
||||
AccessProviderTypeAWS = AccessProviderType("aws")
|
||||
AccessProviderTypeAxisNow = AccessProviderType("axisnow")
|
||||
AccessProviderTypeAzure = AccessProviderType("azure")
|
||||
AccessProviderTypeBaiduCloud = AccessProviderType("baiducloud")
|
||||
AccessProviderTypeBaishan = AccessProviderType("baishan")
|
||||
@@ -342,6 +343,7 @@ const (
|
||||
DeploymentProviderTypeAWSCloudFront = DeploymentProviderType(AccessProviderTypeAWS + "-cloudfront")
|
||||
DeploymentProviderTypeAWSIAM = DeploymentProviderType(AccessProviderTypeAWS + "-iam")
|
||||
DeploymentProviderTypeAWSNLB = DeploymentProviderType(AccessProviderTypeAWS + "-nlb")
|
||||
DeploymentProviderTypeAxisNow = DeploymentProviderType(AccessProviderTypeAxisNow)
|
||||
DeploymentProviderTypeAzureKeyVault = DeploymentProviderType(AccessProviderTypeAzure + "-keyvault")
|
||||
DeploymentProviderTypeBaiduCloudAppBLB = DeploymentProviderType(AccessProviderTypeBaiduCloud + "-appblb")
|
||||
DeploymentProviderTypeBaiduCloudBLB = DeploymentProviderType(AccessProviderTypeBaiduCloud + "-blb")
|
||||
|
||||
138
pkg/core/certmgr/providers/axisnow/axisnow.go
Normal file
138
pkg/core/certmgr/providers/axisnow/axisnow.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package axisnow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/samber/lo"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
axisnowsdk "github.com/certimate-go/certimate/pkg/sdk3rd/axisnow"
|
||||
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||
)
|
||||
|
||||
type (
|
||||
Provider = core.Certmgr
|
||||
UploadResult = core.CertmgrUploadResult
|
||||
ReplaceResult = core.CertmgrReplaceResult
|
||||
)
|
||||
|
||||
type CertmgrConfig struct {
|
||||
// AxisNow API 令牌。
|
||||
ApiToken string `json:"apiToken"`
|
||||
}
|
||||
|
||||
type Certmgr struct {
|
||||
config *CertmgrConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *axisnowsdk.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.ApiToken)
|
||||
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) {
|
||||
// 查询证书列表,避免重复上传
|
||||
// REF: https://developers.axisnow.io/api-reference/main/client/v1/#/operations/certificate-setting-list-certificates
|
||||
listCertificatesPage := 1
|
||||
listCertificatesPerPage := 100
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
listCertificatesReq := &axisnowsdk.ListCertificatesRequest{
|
||||
Page: lo.ToPtr(listCertificatesPage),
|
||||
PerPage: lo.ToPtr(listCertificatesPerPage),
|
||||
}
|
||||
listCertificatesResp, err := c.sdkClient.ListCertificatesWithContext(ctx, listCertificatesReq)
|
||||
c.logger.Debug("sdk request 'Certificates.ListCertificates'", slog.Any("request", listCertificatesReq), slog.Any("response", listCertificatesResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'Certificates.ListCertificates': %w", err)
|
||||
} else {
|
||||
if listCertificatesResp.Results == nil {
|
||||
break
|
||||
}
|
||||
|
||||
for _, certItem := range listCertificatesResp.Results {
|
||||
if xcert.EqualCertificatesFromPEM(certPEM, certItem.Certificate) {
|
||||
// 如果已存在相同证书,直接返回
|
||||
c.logger.Info("ssl certificate already exists")
|
||||
return &UploadResult{
|
||||
CertId: certItem.UUID,
|
||||
CertName: certItem.Name,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(listCertificatesResp.Results) < listCertificatesPerPage ||
|
||||
(listCertificatesResp.ResultInfo != nil && listCertificatesPage*listCertificatesPerPage >= listCertificatesResp.ResultInfo.TotalCount) {
|
||||
break
|
||||
}
|
||||
|
||||
listCertificatesPage++
|
||||
}
|
||||
}
|
||||
|
||||
// 添加证书
|
||||
// REF: https://developers.axisnow.io/api-reference/main/client/v1/#/operations/certificate-setting-add-certificate
|
||||
addCertificateReq := &axisnowsdk.AddCertificateRequest{
|
||||
Type: lo.ToPtr("upload"),
|
||||
Name: lo.ToPtr(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())),
|
||||
Certificate: lo.ToPtr(certPEM),
|
||||
PrivateKey: lo.ToPtr(privkeyPEM),
|
||||
}
|
||||
addCertificateResp, err := c.sdkClient.AddCertificateWithContext(ctx, addCertificateReq)
|
||||
c.logger.Debug("sdk request 'Certificates.AddCertificate'", slog.Any("request", addCertificateReq), slog.Any("response", addCertificateResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'Certificates.AddCertificate': %w", err)
|
||||
}
|
||||
|
||||
return &UploadResult{
|
||||
CertId: addCertificateResp.Result.UUID,
|
||||
CertName: addCertificateResp.Result.Name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Certmgr) Replace(ctx context.Context, certIdOrName string, certPEM, privkeyPEM string) (*ReplaceResult, error) {
|
||||
return nil, core.ErrUnsupported
|
||||
}
|
||||
|
||||
func createSDKClient(apiToken string) (*axisnowsdk.Client, error) {
|
||||
client, err := axisnowsdk.NewClient(
|
||||
axisnowsdk.WithApiToken(apiToken),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
44
pkg/core/certmgr/providers/axisnow/axisnow_test.go
Normal file
44
pkg/core/certmgr/providers/axisnow/axisnow_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package axisnow_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
impl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/axisnow"
|
||||
it "github.com/certimate-go/certimate/pkg/core/certmgr/testing"
|
||||
)
|
||||
|
||||
var (
|
||||
fp = it.Args("AXISNOW_")
|
||||
fTestCertPath string
|
||||
fTestKeyPath string
|
||||
fApiToken string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
|
||||
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
|
||||
fp.DefineString(&fApiToken, "APITOKEN")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./axisnow_test.go -args \
|
||||
--AXISNOW_TESTCERTPATH="/path/to/your-test-cert.pem" \
|
||||
--AXISNOW_TESTKEYPATH="/path/to/your-test-key.pem" \
|
||||
--AXISNOW_APITOKEN="your-api-token"
|
||||
*/
|
||||
func TestProvider(t *testing.T) {
|
||||
fp.Parse()
|
||||
|
||||
t.Run("Upload", func(t *testing.T) {
|
||||
provider, err := impl.NewCertmgr(&impl.CertmgrConfig{
|
||||
ApiToken: fApiToken,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
it.TestUpload(t, provider, it.TestUploadArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
|
||||
})
|
||||
}
|
||||
69
pkg/core/deployer/providers/axisnow/axisnow.go
Normal file
69
pkg/core/deployer/providers/axisnow/axisnow.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package axisnow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/axisnow"
|
||||
)
|
||||
|
||||
type (
|
||||
Provider = core.Deployer
|
||||
DeployResult = core.DeployerDeployResult
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// AxisNow API 令牌。
|
||||
ApiToken string `json:"apiToken"`
|
||||
}
|
||||
|
||||
type Deployer struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
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")
|
||||
}
|
||||
|
||||
pcertmgr, err := cmgrimpl.NewCertmgr(&cmgrimpl.CertmgrConfig{
|
||||
ApiToken: config.ApiToken,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create certmgr: %w", err)
|
||||
}
|
||||
|
||||
return &Deployer{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
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))
|
||||
}
|
||||
|
||||
return &DeployResult{}, nil
|
||||
}
|
||||
40
pkg/sdk3rd/axisnow/api_add_certificate.go
Normal file
40
pkg/sdk3rd/axisnow/api_add_certificate.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package axisnow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type AddCertificateRequest struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Certificate *string `json:"certificate,omitempty"`
|
||||
PrivateKey *string `json:"private_key,omitempty"`
|
||||
}
|
||||
|
||||
type AddCertificateResponse struct {
|
||||
sdkResponseBase
|
||||
|
||||
Result *Certificate `json:"result,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) AddCertificate(req *AddCertificateRequest) (*AddCertificateResponse, error) {
|
||||
return c.AddCertificateWithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func (c *Client) AddCertificateWithContext(ctx context.Context, req *AddCertificateRequest) (*AddCertificateResponse, error) {
|
||||
httpreq, err := c.newRequest(http.MethodPost, "/certificates")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
httpreq.SetBody(req)
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &AddCertificateResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
53
pkg/sdk3rd/axisnow/api_list_certificates.go
Normal file
53
pkg/sdk3rd/axisnow/api_list_certificates.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package axisnow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
qs "github.com/google/go-querystring/query"
|
||||
)
|
||||
|
||||
type ListCertificatesRequest struct {
|
||||
Filter *string `json:"filter,omitempty" url:"filter,omitempty"`
|
||||
Page *int `json:"page,omitempty" url:"page,omitempty"`
|
||||
PerPage *int `json:"per_page,omitempty" url:"per_page,omitempty"`
|
||||
}
|
||||
|
||||
type ListCertificatesResponse struct {
|
||||
sdkResponseBase
|
||||
|
||||
ResultInfo *struct {
|
||||
Page int `json:"page"`
|
||||
PerPage int `json:"per_page"`
|
||||
Count int `json:"count"`
|
||||
TotalCount int `json:"total_count"`
|
||||
SubscribedTotal int `json:"subscribed_total"`
|
||||
} `json:"result_info,omitempty"`
|
||||
Results []*Certificate `json:"result,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) ListCertificates(req *ListCertificatesRequest) (*ListCertificatesResponse, error) {
|
||||
return c.ListCertificatesWithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func (c *Client) ListCertificatesWithContext(ctx context.Context, req *ListCertificatesRequest) (*ListCertificatesResponse, error) {
|
||||
httpreq, err := c.newRequest(http.MethodGet, "/certificates")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
values, err := qs.Values(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpreq.SetQueryParamsFromValues(values)
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &ListCertificatesResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
100
pkg/sdk3rd/axisnow/client.go
Normal file
100
pkg/sdk3rd/axisnow/client.go
Normal file
@@ -0,0 +1,100 @@
|
||||
// A simple SDK client for AxisNow.
|
||||
// API documentation: https://developers.axisnow.io/api-reference/main/client/v1/#/
|
||||
package axisnow
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"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.ApiToken == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset apiToken")
|
||||
}
|
||||
|
||||
httper := resty.New().
|
||||
SetBaseURL("https://api.axisnow.io/client/v1").
|
||||
SetHeader("Accept", "application/json").
|
||||
SetHeader("Authorization", "Bearer "+opts.ApiToken).
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader("User-Agent", app.AppUserAgent)
|
||||
|
||||
return &Client{rc: 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 err := res.GetAPIError(); err != nil {
|
||||
return resp, fmt.Errorf("sdkerr: api error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
29
pkg/sdk3rd/axisnow/models.go
Normal file
29
pkg/sdk3rd/axisnow/models.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package axisnow
|
||||
|
||||
type Certificate struct {
|
||||
UUID string `json:"uuid,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
SubjectName []string `json:"subject_name,omitempty"`
|
||||
Issuer CertificateIssuer `json:"issuer,omitempty"`
|
||||
Subject CertificateSubject `json:"subject,omitempty"`
|
||||
IssueTime int64 `json:"issue_time,omitempty"`
|
||||
ExpireTime int64 `json:"expire_time,omitempty"`
|
||||
Certificate string `json:"certificate,omitempty"`
|
||||
ReferencedCount int `json:"referenced_count,omitempty"`
|
||||
CreatedAt string `json:"created_at,omitempty"`
|
||||
UpdatedAt string `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
type CertificateIssuer struct {
|
||||
Country string `json:"country,omitempty"`
|
||||
Organization string `json:"organization,omitempty"`
|
||||
OrganizationUnit string `json:"organization_unit,omitempty"`
|
||||
CommonName string `json:"common_name,omitempty"`
|
||||
}
|
||||
|
||||
type CertificateSubject struct {
|
||||
Organization string `json:"organization,omitempty"`
|
||||
OrganizationUnit string `json:"organization_unit,omitempty"`
|
||||
CommonName string `json:"common_name,omitempty"`
|
||||
}
|
||||
13
pkg/sdk3rd/axisnow/options.go
Normal file
13
pkg/sdk3rd/axisnow/options.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package axisnow
|
||||
|
||||
type Options struct {
|
||||
ApiToken string
|
||||
}
|
||||
|
||||
type OptionsFunc func(*Options)
|
||||
|
||||
func WithApiToken(apiToken string) OptionsFunc {
|
||||
return func(o *Options) {
|
||||
o.ApiToken = apiToken
|
||||
}
|
||||
}
|
||||
46
pkg/sdk3rd/axisnow/types.go
Normal file
46
pkg/sdk3rd/axisnow/types.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package axisnow
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type sdkResponse interface {
|
||||
GetAPIError() error
|
||||
GetSuccess() bool
|
||||
}
|
||||
|
||||
type sdkResponseBase struct {
|
||||
Success bool `json:"success"`
|
||||
Errors sdkAPIErrors `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
type sdkAPIError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type sdkAPIErrors []sdkAPIError
|
||||
|
||||
func (e sdkAPIErrors) Error() string {
|
||||
builder := &strings.Builder{}
|
||||
|
||||
for _, item := range e {
|
||||
fmt.Fprintf(builder, "[%d] %s", item.Code, item.Message)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(builder.String())
|
||||
}
|
||||
|
||||
func (r *sdkResponseBase) GetSuccess() bool {
|
||||
return r.Success
|
||||
}
|
||||
|
||||
func (r *sdkResponseBase) GetAPIError() error {
|
||||
if len(r.Errors) > 0 {
|
||||
return r.Errors
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ sdkResponse = (*sdkResponseBase)(nil)
|
||||
BIN
ui/public/imgs/providers/axisnow.png
Normal file
BIN
ui/public/imgs/providers/axisnow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
@@ -14,6 +14,7 @@ import AccessConfigFieldsProviderAliyun from "./AccessConfigFieldsProviderAliyun
|
||||
import AccessConfigFieldsProviderAPISIX from "./AccessConfigFieldsProviderAPISIX";
|
||||
import AccessConfigFieldsProviderArvanCloud from "./AccessConfigFieldsProviderArvanCloud";
|
||||
import AccessConfigFieldsProviderAWS from "./AccessConfigFieldsProviderAWS";
|
||||
import AccessConfigFieldsProviderAxisNow from "./AccessConfigFieldsProviderAxisNow";
|
||||
import AccessConfigFieldsProviderAzure from "./AccessConfigFieldsProviderAzure";
|
||||
import AccessConfigFieldsProviderBaiduCloud from "./AccessConfigFieldsProviderBaiduCloud";
|
||||
import AccessConfigFieldsProviderBaishan from "./AccessConfigFieldsProviderBaishan";
|
||||
@@ -141,6 +142,7 @@ const providerComponentMap: Partial<Record<AccessProviderType, React.ComponentTy
|
||||
[ACCESS_PROVIDERS.APISIX]: AccessConfigFieldsProviderAPISIX,
|
||||
[ACCESS_PROVIDERS.ARVANCLOUD]: AccessConfigFieldsProviderArvanCloud,
|
||||
[ACCESS_PROVIDERS.AWS]: AccessConfigFieldsProviderAWS,
|
||||
[ACCESS_PROVIDERS.AXISNOW]: AccessConfigFieldsProviderAxisNow,
|
||||
[ACCESS_PROVIDERS.AZURE]: AccessConfigFieldsProviderAzure,
|
||||
[ACCESS_PROVIDERS.BAIDUCLOUD]: AccessConfigFieldsProviderBaiduCloud,
|
||||
[ACCESS_PROVIDERS.BAISHAN]: AccessConfigFieldsProviderBaishan,
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const AccessConfigFormFieldsProviderAxisNow = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const { parentNamePath } = useFormNestedFieldsContext();
|
||||
const formSchema = z.object({
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const initialValues = getInitialValues();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "apiToken"]}
|
||||
initialValue={initialValues.apiToken}
|
||||
label={t("access.form.axisnow_api_token.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.axisnow_api_token.tooltip") }}></span>}
|
||||
>
|
||||
<Input.Password autoComplete="new-password" placeholder={t("access.form.axisnow_api_token.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
apiToken: "",
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n: ReturnType<typeof getI18n> }) => {
|
||||
const { t: _ } = i18n;
|
||||
|
||||
return z.object({
|
||||
apiToken: z.string().nonempty(),
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(AccessConfigFormFieldsProviderAxisNow, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@@ -29,6 +29,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
|
||||
APISIX: "apisix",
|
||||
ARVANCLOUD: "arvancloud",
|
||||
AWS: "aws",
|
||||
AXISNOW: "axisnow",
|
||||
AZURE: "azure",
|
||||
BAIDUCLOUD: "baiducloud",
|
||||
BAISHAN: "baishan",
|
||||
@@ -216,6 +217,7 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
||||
[ACCESS_PROVIDERS.BAOTAPANELGO, "provider.baotapanelgo", "/imgs/providers/baota.svg", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.BAOTAWAF, "provider.baotawaf", "/imgs/providers/baota.svg", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.DOKPLOY, "provider.dokploy", "/imgs/providers/dokploy.svg", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.AXISNOW, "provider.axisnow", "/imgs/providers/axisnow.png", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.CDNFLY, "provider.cdnfly", "/imgs/providers/cdnfly.svg", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.GOEDGE, "provider.goedge", "/imgs/providers/goedge.png", [ACCESS_USAGES.HOSTING]],
|
||||
[ACCESS_PROVIDERS.KONG, "provider.kong", "/imgs/providers/kong.svg", [ACCESS_USAGES.HOSTING]],
|
||||
@@ -636,6 +638,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
AWS_CLOUDFRONT: `${ACCESS_PROVIDERS.AWS}-cloudfront`,
|
||||
AWS_IAM: `${ACCESS_PROVIDERS.AWS}-iam`,
|
||||
AWS_NLB: `${ACCESS_PROVIDERS.AWS}-nlb`,
|
||||
AXISNOW: `${ACCESS_PROVIDERS.AXISNOW}`,
|
||||
AZURE_KEYVAULT: `${ACCESS_PROVIDERS.AZURE}-keyvault`,
|
||||
BAIDUCLOUD_APPBLB: `${ACCESS_PROVIDERS.BAIDUCLOUD}-appblb`,
|
||||
BAIDUCLOUD_BLB: `${ACCESS_PROVIDERS.BAIDUCLOUD}-blb`,
|
||||
@@ -928,6 +931,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[DEPLOYMENT_PROVIDERS.RAINYUN_SSLCENTER, "provider.rainyun_sslcenter_upload", DEPLOYMENT_CATEGORIES.SSL],
|
||||
[DEPLOYMENT_PROVIDERS.UNICLOUD_WEBHOST, "provider.unicloud_webhost", DEPLOYMENT_CATEGORIES.WEBSITE],
|
||||
[DEPLOYMENT_PROVIDERS.MOHUA_MVH, "provider.mohua_mvh", DEPLOYMENT_CATEGORIES.WEBSITE],
|
||||
[DEPLOYMENT_PROVIDERS.AXISNOW, "provider.axisnow", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.CDNFLY, "provider.cdnfly", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.FLEXCDN, "provider.flexcdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.GOEDGE, "provider.goedge", DEPLOYMENT_CATEGORIES.CDN],
|
||||
|
||||
@@ -243,6 +243,11 @@
|
||||
"placeholder": "Please enter AWS SecretAccessKey",
|
||||
"tooltip": "For more information, see <a href=\"https://docs.aws.amazon.com/en_us/IAM/latest/UserGuide/id_credentials_access-keys.html\" target=\"_blank\">https://docs.aws.amazon.com/en_us/IAM/latest/UserGuide/id_credentials_access-keys.html</a>"
|
||||
},
|
||||
"axisnow_api_token": {
|
||||
"label": "AxisNow API token",
|
||||
"placeholder": "Please enter AxisNow API token",
|
||||
"tooltip": "For more information, see <a href=\"https://www.axisnow.io/zh/docs/edge/tenant/api-tokens\" target=\"_blank\">https://www.axisnow.io/zh/docs/edge/tenant/api-tokens</a>"
|
||||
},
|
||||
"azure_tenant_id": {
|
||||
"label": "Azure tenant ID",
|
||||
"placeholder": "Please enter Azure tenant ID",
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
"aws_lightsail": "AWS - Lightsail",
|
||||
"aws_nlb": "AWS - NLB (Network Load Balancer)",
|
||||
"aws_route53": "AWS - Route53",
|
||||
"axisnow": "AxisNow",
|
||||
"azure": "Azure (Microsoft Azure)",
|
||||
"azure_dns": "Azure - DNS",
|
||||
"azure_keyvault": "Azure - KeyVault",
|
||||
|
||||
@@ -243,6 +243,11 @@
|
||||
"placeholder": "请输入 AWS SecretAccessKey",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_credentials_access-keys.html\" target=\"_blank\">https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_credentials_access-keys.html</a>"
|
||||
},
|
||||
"axisnow_api_token": {
|
||||
"label": "AxisNow API 令牌",
|
||||
"placeholder": "请输入 AxisNow API 令牌",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://www.axisnow.io/zh/docs/edge/tenant/api-tokens\" target=\"_blank\">https://www.axisnow.io/zh/docs/edge/tenant/api-tokens</a>"
|
||||
},
|
||||
"azure_tenant_id": {
|
||||
"label": "Azure 租户 ID",
|
||||
"placeholder": "请输入 Azure 租户 ID",
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
"aws_lightsail": "AWS - Lightsail",
|
||||
"aws_nlb": "AWS - 网络负载均衡器 NLB",
|
||||
"aws_route53": "AWS - Route53",
|
||||
"axisnow": "AxisNow",
|
||||
"azure": "Azure(Microsoft Azure)",
|
||||
"azure_dns": "Azure - DNS",
|
||||
"azure_keyvault": "Azure - KeyVault",
|
||||
|
||||
Reference in New Issue
Block a user