mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-06-25 14:17:12 +08:00
365 lines
12 KiB
Go
365 lines
12 KiB
Go
// 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 models
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/pkg/tristate"
|
|
"yunion.io/x/sqlchemy"
|
|
|
|
api "yunion.io/x/onecloud/pkg/apis/identity"
|
|
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
|
"yunion.io/x/onecloud/pkg/httperrors"
|
|
"yunion.io/x/onecloud/pkg/mcclient"
|
|
"yunion.io/x/onecloud/pkg/util/logclient"
|
|
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
|
)
|
|
|
|
type SEndpointManager struct {
|
|
db.SStandaloneResourceBaseManager
|
|
}
|
|
|
|
var EndpointManager *SEndpointManager
|
|
|
|
func init() {
|
|
EndpointManager = &SEndpointManager{
|
|
SStandaloneResourceBaseManager: db.NewStandaloneResourceBaseManager(
|
|
SEndpoint{},
|
|
"endpoint",
|
|
"endpoint",
|
|
"endpoints",
|
|
),
|
|
}
|
|
EndpointManager.SetVirtualObject(EndpointManager)
|
|
}
|
|
|
|
/*
|
|
+--------------------+--------------+------+-----+---------+-------+
|
|
| Field | Type | Null | Key | Default | Extra |
|
|
+--------------------+--------------+------+-----+---------+-------+
|
|
| id | varchar(64) | NO | PRI | NULL | |
|
|
| legacy_endpoint_id | varchar(64) | YES | | NULL | |
|
|
| interface | varchar(8) | NO | | NULL | |
|
|
| service_id | varchar(64) | NO | MUL | NULL | |
|
|
| url | text | NO | | NULL | |
|
|
| extra | text | YES | | NULL | |
|
|
| enabled | tinyint(1) | NO | | 1 | |
|
|
| region_id | varchar(255) | YES | MUL | NULL | |
|
|
| created_at | datetime | YES | | NULL | |
|
|
+--------------------+--------------+------+-----+---------+-------+
|
|
*/
|
|
|
|
type SEndpoint struct {
|
|
db.SStandaloneResourceBase
|
|
|
|
LegacyEndpointId string `width:"64" charset:"ascii" nullable:"true"`
|
|
Interface string `width:"8" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"`
|
|
ServiceId string `width:"64" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"`
|
|
Url string `charset:"utf8" nullable:"false" list:"admin" update:"admin" create:"admin_required"`
|
|
Extra *jsonutils.JSONDict `nullable:"true"`
|
|
Enabled tristate.TriState `nullable:"false" default:"true" list:"admin" update:"admin" create:"admin_optional"`
|
|
RegionId string `width:"255" charset:"utf8" nullable:"true" list:"admin" create:"admin_required"`
|
|
}
|
|
|
|
func (manager *SEndpointManager) InitializeData() error {
|
|
q := manager.Query()
|
|
q = q.IsNullOrEmpty("name")
|
|
eps := make([]SEndpoint, 0)
|
|
err := db.FetchModelObjects(manager, q, &eps)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for i := range eps {
|
|
name, _ := eps[i].Extra.GetString("name")
|
|
desc, _ := eps[i].Extra.GetString("description")
|
|
if len(name) == 0 {
|
|
serv := eps[i].getService()
|
|
if serv != nil {
|
|
name = fmt.Sprintf("%s-%s", serv.Type, eps[i].Interface)
|
|
}
|
|
}
|
|
if len(name) > 0 {
|
|
db.Update(&eps[i], func() error {
|
|
eps[i].Name = name
|
|
eps[i].Description = desc
|
|
return nil
|
|
})
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ep *SEndpoint) getService() *SService {
|
|
srvObj, err := ServiceManager.FetchById(ep.ServiceId)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return srvObj.(*SService)
|
|
}
|
|
|
|
type SEndpointExtended struct {
|
|
Id string
|
|
Name string
|
|
Interface string
|
|
Url string
|
|
Region string
|
|
RegionId string
|
|
ServiceId string
|
|
ServiceType string
|
|
ServiceName string
|
|
}
|
|
|
|
type SServiceCatalog []SEndpointExtended
|
|
|
|
func (manager *SEndpointManager) FetchAll() (SServiceCatalog, error) {
|
|
endpoints := manager.Query().SubQuery()
|
|
services := ServiceManager.Query().SubQuery()
|
|
regions := RegionManager.Query().SubQuery()
|
|
|
|
q := endpoints.Query(
|
|
endpoints.Field("id"),
|
|
endpoints.Field("name"),
|
|
endpoints.Field("interface"),
|
|
endpoints.Field("url"),
|
|
endpoints.Field("region_id"),
|
|
regions.Field("name", "region"),
|
|
endpoints.Field("service_id"),
|
|
services.Field("type", "service_type"),
|
|
services.Field("name", "service_name"),
|
|
)
|
|
q = q.Join(regions, sqlchemy.Equals(endpoints.Field("region_id"), regions.Field("id")))
|
|
q = q.Join(services, sqlchemy.Equals(endpoints.Field("service_id"), services.Field("id")))
|
|
q = q.Filter(sqlchemy.IsTrue(endpoints.Field("enabled")))
|
|
q = q.Filter(sqlchemy.IsTrue(services.Field("enabled")))
|
|
|
|
eps := make([]SEndpointExtended, 0)
|
|
err := q.All(&eps)
|
|
if err != nil && err != sql.ErrNoRows {
|
|
return nil, err
|
|
}
|
|
return eps, nil
|
|
}
|
|
|
|
func (cata SServiceCatalog) GetKeystoneCatalogV3() mcclient.KeystoneServiceCatalogV3 {
|
|
ksCata := make(map[string]mcclient.KeystoneServiceV3)
|
|
|
|
for i := range cata {
|
|
srvId := cata[i].ServiceId
|
|
srv, ok := ksCata[srvId]
|
|
if !ok {
|
|
srv = mcclient.KeystoneServiceV3{
|
|
Id: srvId,
|
|
Name: cata[i].ServiceName,
|
|
Type: cata[i].ServiceType,
|
|
Endpoints: make([]mcclient.KeystoneEndpointV3, 0),
|
|
}
|
|
}
|
|
ep := mcclient.KeystoneEndpointV3{
|
|
Id: cata[i].Id,
|
|
Name: cata[i].Name,
|
|
Interface: cata[i].Interface,
|
|
Region: cata[i].Region,
|
|
RegionId: cata[i].RegionId,
|
|
Url: cata[i].Url,
|
|
}
|
|
srv.Endpoints = append(srv.Endpoints, ep)
|
|
ksCata[cata[i].ServiceId] = srv
|
|
}
|
|
|
|
results := make([]mcclient.KeystoneServiceV3, 0)
|
|
for k := range ksCata {
|
|
results = append(results, ksCata[k])
|
|
}
|
|
return results
|
|
}
|
|
|
|
func (cata SServiceCatalog) GetKeystoneCatalogV2() mcclient.KeystoneServiceCatalogV2 {
|
|
ksCata := make(map[string]mcclient.KeystoneServiceV2)
|
|
|
|
for i := range cata {
|
|
srvId := cata[i].ServiceId
|
|
srv, ok := ksCata[srvId]
|
|
if !ok {
|
|
srv = mcclient.KeystoneServiceV2{
|
|
Name: cata[i].ServiceName,
|
|
Type: cata[i].ServiceType,
|
|
Endpoints: make([]mcclient.KeystoneEndpointV2, 0),
|
|
}
|
|
}
|
|
findIdx := -1
|
|
for j := range srv.Endpoints {
|
|
if srv.Endpoints[j].Region == cata[i].RegionId {
|
|
findIdx = j
|
|
}
|
|
}
|
|
if findIdx < 0 {
|
|
ep := mcclient.KeystoneEndpointV2{
|
|
Id: cata[i].Id,
|
|
Region: cata[i].RegionId,
|
|
}
|
|
srv.Endpoints = append(srv.Endpoints, ep)
|
|
findIdx = len(srv.Endpoints) - 1
|
|
}
|
|
switch cata[i].Interface {
|
|
case api.EndpointInterfacePublic:
|
|
srv.Endpoints[findIdx].PublicURL = cata[i].Url
|
|
case api.EndpointInterfaceInternal:
|
|
srv.Endpoints[findIdx].InternalURL = cata[i].Url
|
|
case api.EndpointInterfaceAdmin:
|
|
srv.Endpoints[findIdx].AdminURL = cata[i].Url
|
|
}
|
|
ksCata[cata[i].ServiceId] = srv
|
|
}
|
|
|
|
results := make([]mcclient.KeystoneServiceV2, 0)
|
|
for k := range ksCata {
|
|
results = append(results, ksCata[k])
|
|
}
|
|
return results
|
|
}
|
|
|
|
func (manager *SEndpointManager) FetchCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, objs []db.IModel, fields stringutils2.SSortedStrings) []*jsonutils.JSONDict {
|
|
rows := manager.SStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields)
|
|
serviceIds := stringutils2.SSortedStrings{}
|
|
for i := range objs {
|
|
ep := objs[i].(*SEndpoint)
|
|
serviceIds = stringutils2.Append(serviceIds, ep.ServiceId)
|
|
}
|
|
if len(fields) == 0 || fields.Contains("service_name") || fields.Contains("service_type") {
|
|
svs := fetchServices(serviceIds)
|
|
if svs != nil {
|
|
for i := range rows {
|
|
ep := objs[i].(*SEndpoint)
|
|
if srv, ok := svs[ep.ServiceId]; ok {
|
|
if len(fields) == 0 || fields.Contains("service_name") {
|
|
rows[i].Add(jsonutils.NewString(srv.Name), "service_name")
|
|
}
|
|
if len(fields) == 0 || fields.Contains("service_type") {
|
|
rows[i].Add(jsonutils.NewString(srv.Type), "service_type")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return rows
|
|
}
|
|
|
|
func fetchServices(srvIds []string) map[string]SService {
|
|
q := ServiceManager.Query().In("id", srvIds)
|
|
srvs := make([]SService, 0)
|
|
err := db.FetchModelObjects(ServiceManager, q, &srvs)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
ret := make(map[string]SService)
|
|
for i := range srvs {
|
|
ret[srvs[i].Id] = srvs[i]
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (endpoint *SEndpoint) ValidateDeleteCondition(ctx context.Context) error {
|
|
if endpoint.Enabled.IsTrue() {
|
|
return httperrors.NewInvalidStatusError("endpoint is enabled")
|
|
}
|
|
return endpoint.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
|
|
}
|
|
|
|
func (endpoint *SEndpoint) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
|
|
extra := endpoint.SStandaloneResourceBase.GetCustomizeColumns(ctx, userCred, query)
|
|
return endpointExtra(endpoint, extra)
|
|
}
|
|
|
|
func (endpoint *SEndpoint) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
|
extra, err := endpoint.SStandaloneResourceBase.GetExtraDetails(ctx, userCred, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return endpointExtra(endpoint, extra), nil
|
|
}
|
|
|
|
func endpointExtra(endpoint *SEndpoint, extra *jsonutils.JSONDict) *jsonutils.JSONDict {
|
|
return extra
|
|
}
|
|
|
|
func (manager *SEndpointManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
|
infname, _ := data.GetString("interface")
|
|
if len(infname) == 0 {
|
|
return nil, httperrors.NewInputParameterError("missing input field interface")
|
|
}
|
|
serviceStr := jsonutils.GetAnyString(data, []string{"service_id", "service"})
|
|
if len(serviceStr) > 0 {
|
|
servObj, err := ServiceManager.FetchByIdOrName(userCred, serviceStr)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, httperrors.NewResourceNotFoundError2(ServiceManager.Keyword(), serviceStr)
|
|
} else {
|
|
return nil, httperrors.NewGeneralError(err)
|
|
}
|
|
}
|
|
service := servObj.(*SService)
|
|
if !data.Contains("name") {
|
|
data.Set("name", jsonutils.NewString(fmt.Sprintf("%s-%s", service.Type, infname)))
|
|
}
|
|
data.Set("service_id", jsonutils.NewString(service.Id))
|
|
} else {
|
|
return nil, httperrors.NewInputParameterError("missing input field service/service_id")
|
|
}
|
|
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
|
|
}
|
|
|
|
func (manager *SEndpointManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
|
q, err := manager.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
svcStr := jsonutils.GetAnyString(query, []string{"service", "service_id"})
|
|
if len(svcStr) > 0 {
|
|
svcObj, err := ServiceManager.FetchByIdOrName(userCred, svcStr)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, httperrors.NewResourceNotFoundError2(ServiceManager.Keyword(), svcStr)
|
|
} else {
|
|
return nil, httperrors.NewGeneralError(err)
|
|
}
|
|
}
|
|
subq := ServiceManager.Query("id").Equals("id", svcObj.GetId())
|
|
q = q.Equals("service_id", subq.SubQuery())
|
|
}
|
|
return q, nil
|
|
}
|
|
|
|
func (endpoint *SEndpoint) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
|
endpoint.SStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
|
|
logclient.AddActionLogWithContext(ctx, endpoint, logclient.ACT_CREATE, data, userCred, true)
|
|
refreshDefaultClientServiceCatalog()
|
|
}
|
|
|
|
func (endpoint *SEndpoint) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
|
endpoint.SStandaloneResourceBase.PostUpdate(ctx, userCred, query, data)
|
|
logclient.AddActionLogWithContext(ctx, endpoint, logclient.ACT_UPDATE, data, userCred, true)
|
|
refreshDefaultClientServiceCatalog()
|
|
}
|
|
|
|
func (endpoint *SEndpoint) PostDelete(ctx context.Context, userCred mcclient.TokenCredential) {
|
|
endpoint.SStandaloneResourceBase.PostDelete(ctx, userCred)
|
|
logclient.AddActionLogWithContext(ctx, endpoint, logclient.ACT_DELETE, nil, userCred, true)
|
|
refreshDefaultClientServiceCatalog()
|
|
}
|