From 8248bcd67ebbdd0c80ab5ba32bdb692fa190a376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E8=BD=A9?= Date: Wed, 16 Jul 2025 19:55:21 +0800 Subject: [PATCH] fix(region): support ssl delete (#22912) --- go.mod | 4 +- go.sum | 8 +- pkg/compute/models/sslcertificate.go | 46 ++++++++++++ .../ssl_certificate_create_task.go | 27 ++++--- .../ssl_certificate_delete_task.go | 75 +++++++++++++++++++ vendor/modules.txt | 4 +- .../x/cloudmux/pkg/cloudprovider/resources.go | 2 + .../x/cloudmux/pkg/cloudprovider/ssl.go | 1 + .../pkg/multicloud/certificate_base.go | 9 +++ .../x/cloudmux/pkg/multicloud/google/eip.go | 2 +- .../x/pkg/util/stringutils/stringutils.go | 19 +++++ 11 files changed, 176 insertions(+), 21 deletions(-) create mode 100644 pkg/compute/tasks/ssl_certificate/ssl_certificate_delete_task.go diff --git a/go.mod b/go.mod index 78767967d7..5a1f9b8fc2 100644 --- a/go.mod +++ b/go.mod @@ -96,12 +96,12 @@ require ( k8s.io/cri-api v0.22.17 k8s.io/klog/v2 v2.20.0 moul.io/http2curl/v2 v2.3.0 - yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250714101351-0817913263fc + yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250716110021-9441f2355a22 yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1 yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91 yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 - yunion.io/x/pkg v1.10.4-0.20250715023532-99a31ea00303 + yunion.io/x/pkg v1.10.4-0.20250715170922-d5b8a92716b6 yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833 yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c diff --git a/go.sum b/go.sum index b08333c696..1241762d1d 100644 --- a/go.sum +++ b/go.sum @@ -1408,8 +1408,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250714101351-0817913263fc h1:+tsZhjPki2ewy/ihdm1ETCqkAa+jD7qFplRhRggWwz0= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250714101351-0817913263fc/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250716110021-9441f2355a22 h1:yttqal9APls/yeyM954EmNsFR/AiD/r5tUsyS6yT120= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250716110021-9441f2355a22/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ= yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU= yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws= yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634= @@ -1423,8 +1423,8 @@ yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 h1:Hu/4ERvoWaN6aiFs4h4/yvVB yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc= yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E= yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E= -yunion.io/x/pkg v1.10.4-0.20250715023532-99a31ea00303 h1:gbAWm7tVNr0mZjLMJa1A6P85tHsuEpDEEnUHz0+mBhw= -yunion.io/x/pkg v1.10.4-0.20250715023532-99a31ea00303/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM= +yunion.io/x/pkg v1.10.4-0.20250715170922-d5b8a92716b6 h1:bcvKeB+j9oc1wS7/AjonkUlh+Dl6HSw/hfQuFI2JUXw= +yunion.io/x/pkg v1.10.4-0.20250715170922-d5b8a92716b6/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM= yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4= yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo= yunion.io/x/sqlchemy v1.1.3-0.20250531010554-ce98f840b833 h1:XTFC1naKYkciCQDLm9izpzHXfTenmmtYsTpVKrsN5hE= diff --git a/pkg/compute/models/sslcertificate.go b/pkg/compute/models/sslcertificate.go index 0ad24aa78b..0197a005be 100644 --- a/pkg/compute/models/sslcertificate.go +++ b/pkg/compute/models/sslcertificate.go @@ -331,6 +331,28 @@ func (s *SSSLCertificate) syncRemoveCloudSSLCertificate(ctx context.Context, use return nil } +// 删除证书 +func (s *SSSLCertificate) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input jsonutils.JSONObject) error { + err := s.StartSSLCertificateDeleteTask(ctx, userCred, nil) + if err != nil { + return errors.Wrapf(err, "StartSSLCertificateDeleteTask") + } + return nil +} + +func (s *SSSLCertificate) StartSSLCertificateDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict) error { + task, err := taskman.TaskManager.NewTask(ctx, "SSLCertificateDeleteTask", s, userCred, params, "", "", nil) + if err != nil { + return errors.Wrapf(err, "NewTask") + } + s.SetStatus(ctx, userCred, apis.STATUS_DELETING, "") + return task.ScheduleRun(nil) +} + +func (s *SSSLCertificate) Delete(ctx context.Context, userCred mcclient.TokenCredential) error { + return nil +} + func (s *SSSLCertificate) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error { return s.SVirtualResourceBase.Delete(ctx, userCred) } @@ -457,6 +479,30 @@ func (r *SCloudprovider) newFromCloudSSLCertificate( return &s, nil } +func (s *SSSLCertificate) GetICloudSSLCertificate(ctx context.Context) (cloudprovider.ICloudSSLCertificate, error) { + if len(s.ExternalId) == 0 { + return nil, errors.Wrapf(cloudprovider.ErrNotFound, "ExternalId is empty") + } + provider := s.GetCloudprovider() + if provider == nil { + return nil, errors.Wrapf(cloudprovider.ErrNotFound, "Cloudprovider is empty") + } + drv, err := provider.GetProvider(ctx) + if err != nil { + return nil, errors.Wrapf(err, "GetProvider") + } + certs, err := drv.GetISSLCertificates() + if err != nil { + return nil, errors.Wrapf(err, "GetICloudSSLCertificate") + } + for i := range certs { + if certs[i].GetGlobalId() == s.ExternalId { + return certs[i], nil + } + } + return nil, errors.Wrapf(cloudprovider.ErrNotFound, "GetICloudSSLCertificate") +} + func (man *SSSLCertificateManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, diff --git a/pkg/compute/tasks/ssl_certificate/ssl_certificate_create_task.go b/pkg/compute/tasks/ssl_certificate/ssl_certificate_create_task.go index c6075ab41a..a72d727b93 100644 --- a/pkg/compute/tasks/ssl_certificate/ssl_certificate_create_task.go +++ b/pkg/compute/tasks/ssl_certificate/ssl_certificate_create_task.go @@ -98,7 +98,7 @@ func (self *SSLCertificateCreateTask) OnInit(ctx context.Context, obj db.IStanda addr := "" switch sc.Issuer { case api.SSL_ISSUER_LETSENCRYPT: - addr = acme.LetsEncryptStaging + addr = acme.LetsEncryptProduction case api.SSL_ISSUER_ZEROSSL: addr = acme.ZeroSSLProduction } @@ -254,17 +254,19 @@ func (self *SSLCertificateCreateTask) OnInit(ctx context.Context, obj db.IStanda start, end, country, province, city := time.Time{}, time.Time{}, "", "", "" var pemData []string - for _, c := range certs { - start = c.NotBefore - end = c.NotAfter - if len(c.Subject.Country) > 0 { - country = c.Subject.Country[0] - } - if len(c.Subject.Province) > 0 { - province = c.Subject.Province[0] - } - if len(c.Subject.Locality) > 0 { - city = c.Subject.Locality[0] + for i, c := range certs { + if i == 0 { + start = c.NotBefore + end = c.NotAfter + if len(c.Subject.Country) > 0 { + country = c.Subject.Country[0] + } + if len(c.Subject.Province) > 0 { + province = c.Subject.Province[0] + } + if len(c.Subject.Locality) > 0 { + city = c.Subject.Locality[0] + } } pemData = append(pemData, strings.TrimSpace(string(pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", @@ -294,6 +296,7 @@ func (self *SSLCertificateCreateTask) OnInit(ctx context.Context, obj db.IStanda return errors.Wrapf(err, "GetProvider") } opts := &cloudprovider.SSLCertificateCreateOptions{ + Name: sc.Name, DnsZoneId: zone.ExternalId, Certificate: sc.Certificate, PrivateKey: sc.PrivateKey, diff --git a/pkg/compute/tasks/ssl_certificate/ssl_certificate_delete_task.go b/pkg/compute/tasks/ssl_certificate/ssl_certificate_delete_task.go new file mode 100644 index 0000000000..6832efb700 --- /dev/null +++ b/pkg/compute/tasks/ssl_certificate/ssl_certificate_delete_task.go @@ -0,0 +1,75 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ssl_certificate + +import ( + "context" + + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" + + "yunion.io/x/onecloud/pkg/apis" + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" + "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient" + "yunion.io/x/onecloud/pkg/compute/models" + "yunion.io/x/onecloud/pkg/util/logclient" +) + +type SSLCertificateDeleteTask struct { + taskman.STask +} + +func init() { + taskman.RegisterTask(SSLCertificateDeleteTask{}) +} + +func (self *SSLCertificateDeleteTask) taskFailed(ctx context.Context, cert *models.SSSLCertificate, err error) { + cert.SetStatus(ctx, self.UserCred, apis.STATUS_DELETE_FAILED, err.Error()) + logclient.AddActionLogWithStartable(self, cert, logclient.ACT_DELOCATE, err, self.UserCred, false) + self.SetStageFailed(ctx, jsonutils.NewString(err.Error())) +} + +func (self *SSLCertificateDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) { + cert := obj.(*models.SSSLCertificate) + + iCert, err := cert.GetICloudSSLCertificate(ctx) + if err != nil { + if errors.Cause(err) == cloudprovider.ErrNotFound { + self.taskComplete(ctx, cert) + return + } + self.taskFailed(ctx, cert, errors.Wrapf(err, "cert.GetICloudSSLCertificate")) + return + } + + err = iCert.Delete() + if err != nil { + self.taskFailed(ctx, cert, errors.Wrapf(err, "iCert.Delete")) + return + } + + self.taskComplete(ctx, cert) +} + +func (self *SSLCertificateDeleteTask) taskComplete(ctx context.Context, cert *models.SSSLCertificate) { + cert.RealDelete(ctx, self.GetUserCred()) + notifyclient.EventNotify(ctx, self.UserCred, notifyclient.SEventNotifyParam{ + Obj: cert, + Action: notifyclient.ActionDelete, + }) + self.SetStageComplete(ctx, nil) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 2b1cfb035d..1fb61bcaa6 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1852,7 +1852,7 @@ sigs.k8s.io/structured-merge-diff/v4/value # sigs.k8s.io/yaml v1.2.0 ## explicit; go 1.12 sigs.k8s.io/yaml -# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250714101351-0817913263fc +# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250716110021-9441f2355a22 ## explicit; go 1.21 yunion.io/x/cloudmux/pkg/apis yunion.io/x/cloudmux/pkg/apis/billing @@ -1949,7 +1949,7 @@ yunion.io/x/log/hooks yunion.io/x/ovsdb/cli_util yunion.io/x/ovsdb/schema/ovn_nb yunion.io/x/ovsdb/types -# yunion.io/x/pkg v1.10.4-0.20250715023532-99a31ea00303 +# yunion.io/x/pkg v1.10.4-0.20250715170922-d5b8a92716b6 ## explicit; go 1.18 yunion.io/x/pkg/appctx yunion.io/x/pkg/errors diff --git a/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/resources.go b/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/resources.go index d3347e1f9d..89e7335e2c 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/resources.go +++ b/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/resources.go @@ -1822,6 +1822,8 @@ type ICloudSSLCertificate interface { GetCert() string GetKey() string GetDnsZoneId() string + + Delete() error } type IAiGateway interface { diff --git a/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/ssl.go b/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/ssl.go index 35333e4613..29e52fef32 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/ssl.go +++ b/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/ssl.go @@ -20,6 +20,7 @@ const ( ) type SSLCertificateCreateOptions struct { + Name string DnsZoneId string Certificate string PrivateKey string diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/certificate_base.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/certificate_base.go index 943f6910c6..f1f41ad8e2 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/certificate_base.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/certificate_base.go @@ -14,6 +14,11 @@ package multicloud +import ( + "yunion.io/x/cloudmux/pkg/cloudprovider" + "yunion.io/x/pkg/errors" +) + type SCertificateBase struct { SVirtualResourceBase } @@ -21,3 +26,7 @@ type SCertificateBase struct { func (cert *SCertificateBase) GetDnsZoneId() string { return "" } + +func (cert *SCertificateBase) Delete() error { + return errors.Wrapf(cloudprovider.ErrNotImplemented, "Delete") +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/google/eip.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/google/eip.go index 0dfb6dc98a..51b4593d19 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/google/eip.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/google/eip.go @@ -129,7 +129,7 @@ func (addr *SAddress) GetAssociationType() string { return api.EIP_ASSOCIATE_TYPE_SERVER } for _, user := range addr.Users { - if strings.HasPrefix(user, "/instances/") { + if strings.Contains(user, "/instances/") { return api.EIP_ASSOCIATE_TYPE_SERVER } if strings.Contains(user, "/forwardingRules/") { diff --git a/vendor/yunion.io/x/pkg/util/stringutils/stringutils.go b/vendor/yunion.io/x/pkg/util/stringutils/stringutils.go index 460c656efa..c38f70fdce 100644 --- a/vendor/yunion.io/x/pkg/util/stringutils/stringutils.go +++ b/vendor/yunion.io/x/pkg/util/stringutils/stringutils.go @@ -95,3 +95,22 @@ func ContainsWord(str, w string) bool { reg := regexp.MustCompile(fmt.Sprintf("\\b%s\\b", w)) return reg.MatchString(str) } + +func byte2hex(b byte) byte { + if b >= 0 && b <= 9 { + return b + 0x30 + } + if b >= 10 && b <= 15 { + return b - 10 + 0x61 + } + return '?' +} + +func Bytes2Str(b []byte) string { + buf := strings.Builder{} + for i := range b { + buf.WriteByte(byte2hex((b[i] & 0xf0) >> 4)) + buf.WriteByte(byte2hex(b[i] & 0x0f)) + } + return buf.String() +}