Skip to content

Commit 4e235ae

Browse files
committed
feat: adds license check
1 parent b067070 commit 4e235ae

File tree

8 files changed

+148
-60
lines changed

8 files changed

+148
-60
lines changed

server/controller/config/common/config.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ type Swagger struct {
2020
Enabled bool `default:"true" yaml:"enabled"`
2121
}
2222

23+
type Warrant struct {
24+
Enabled bool `default:"false" yaml:"enabled"`
25+
Host string `default:"warrant" yaml:"host"`
26+
Port int `default:"20413" yaml:"port"`
27+
Timeout int `default:"30" yaml:"timeout"`
28+
}
29+
2330
// TODO use this
2431
type FPermit struct {
2532
Enabled bool `default:"false" yaml:"enabled"`

server/controller/http/common/const.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const (
4949

5050
// map to http.StatusForbidden
5151
NO_PERMISSIONS = "NO_PERMISSIONS"
52+
NO_LICENSE = "NO_LICENSE"
5253

5354
// map to http.StatusPartialContent
5455
PARTIAL_CONTENT = "PARTIAL_RESULT"

server/controller/http/router/agent/agent_cmd.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"net/http/httputil"
2626
"net/url"
2727
"strconv"
28+
"strings"
2829

2930
"github.com/gin-gonic/gin"
3031
"github.com/gin-gonic/gin/binding"
@@ -88,6 +89,16 @@ func (a *AgentCMD) RegisterTo(e *gin.Engine) {
8889
agentRoutes.POST("/cmd/run", forwardToServerConnectedByAgent(), a.cmdRunHandler())
8990
}
9091

92+
func checkAgentLicense(agent *metadbmodel.VTap) error {
93+
parts := strings.Split(agent.LicenseFunctions, ",")
94+
for _, part := range parts {
95+
if strings.TrimSpace(part) == fmt.Sprintf("%s", common.AGENT_LICENSE_FUNCTION_LEGACY_PROBE) {
96+
return nil
97+
}
98+
}
99+
return fmt.Errorf("agent(%s) license not support probe command", agent.Name)
100+
}
101+
91102
func forwardToServerConnectedByAgent() gin.HandlerFunc {
92103
return func(c *gin.Context) {
93104
orgID, _ := c.Get(common.HEADER_KEY_X_ORG_ID)
@@ -112,6 +123,13 @@ func forwardToServerConnectedByAgent() gin.HandlerFunc {
112123
c.Abort()
113124
return
114125
}
126+
if err := checkAgentLicense(agent); err != nil {
127+
log.Error(err, db.LogPrefixORGID)
128+
response.JSON(c, response.SetOptStatus(httpcommon.NO_PERMISSIONS), response.SetError(err))
129+
c.Abort()
130+
return
131+
}
132+
115133
key := agent.CtrlIP + "-" + agent.CtrlMac
116134
// handle forward times
117135
var forwardTimes int

server/controller/http/router/resource/domain.go

Lines changed: 96 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"encoding/json"
2121
"fmt"
2222
"io"
23+
"net/http"
2324
"net/url"
2425
"strconv"
2526
"strings"
@@ -29,7 +30,9 @@ import (
2930
"github.com/op/go-logging"
3031
"gopkg.in/yaml.v2"
3132

33+
ctrlCommon "github.com/deepflowio/deepflow/server/controller/common"
3234
"github.com/deepflowio/deepflow/server/controller/config"
35+
configs "github.com/deepflowio/deepflow/server/controller/config/common"
3336
metadbcommon "github.com/deepflowio/deepflow/server/controller/db/metadb/common"
3437
httpcommon "github.com/deepflowio/deepflow/server/controller/http/common"
3538
"github.com/deepflowio/deepflow/server/controller/http/common/response"
@@ -64,11 +67,11 @@ func (d *Domain) RegisterTo(e *gin.Engine) {
6467
e.PATCH("/v2/sub-domains/:lcuuid/", updateSubDomain(d.cfg))
6568
e.DELETE("/v2/sub-domains/:lcuuid/", deleteSubDomain(d.cfg))
6669

67-
e.PUT("/v1/domain-additional-resources/", applyDomainAddtionalResource)
68-
e.GET("/v1/domain-additional-resources/", listDomainAddtionalResource)
70+
e.PUT("/v1/domain-additional-resources/", applyDomainAdditionalResource(d.cfg.MonitorCfg.Warrant))
71+
e.GET("/v1/domain-additional-resources/", listDomainAdditionalResource)
6972
e.GET("/v1/domain-additional-resources/example/", GetDomainAdditionalResourceExample)
70-
e.PATCH("/v1/domain-additional-resources/advanced/", updateDomainAddtionalResourceAdvanced)
71-
e.GET("/v1/domain-additional-resources/advanced/", getDomainAddtionalResourceAdvanced)
73+
e.PATCH("/v1/domain-additional-resources/advanced/", updateDomainAdditionalResourceAdvanced(d.cfg.MonitorCfg.Warrant))
74+
e.GET("/v1/domain-additional-resources/advanced/", getDomainAdditionalResourceAdvanced)
7275
}
7376

7477
func getDomain(cfg *config.ControllerConfig) gin.HandlerFunc {
@@ -397,37 +400,44 @@ func updateSubDomain(cfg *config.ControllerConfig) gin.HandlerFunc {
397400
})
398401
}
399402

400-
func applyDomainAddtionalResource(c *gin.Context) {
401-
b, err := io.ReadAll(c.Request.Body)
402-
if err != nil {
403-
response.JSON(c, response.SetOptStatus(httpcommon.SERVER_ERROR), response.SetError(err))
404-
return
405-
}
406-
err = common.CheckJSONParam(string(b), model.AdditionalResource{})
407-
if err != nil {
408-
response.JSON(c, response.SetOptStatus(httpcommon.INVALID_PARAMETERS), response.SetError(err))
409-
return
410-
}
403+
func applyDomainAdditionalResource(warrantCfg configs.Warrant) gin.HandlerFunc {
404+
return gin.HandlerFunc(func(c *gin.Context) {
405+
if err := checkCMDBLicense(warrantCfg); err != nil {
406+
response.JSON(c, response.SetOptStatus(httpcommon.NO_LICENSE), response.SetError(err))
407+
return
408+
}
411409

412-
var data model.AdditionalResource
413-
err = json.Unmarshal(b, &data)
414-
// invalidate request body
415-
if err != nil {
416-
response.JSON(c, response.SetOptStatus(httpcommon.INVALID_PARAMETERS), response.SetError(err))
417-
return
418-
}
410+
b, err := io.ReadAll(c.Request.Body)
411+
if err != nil {
412+
response.JSON(c, response.SetOptStatus(httpcommon.SERVER_ERROR), response.SetError(err))
413+
return
414+
}
415+
err = common.CheckJSONParam(string(b), model.AdditionalResource{})
416+
if err != nil {
417+
response.JSON(c, response.SetOptStatus(httpcommon.INVALID_PARAMETERS), response.SetError(err))
418+
return
419+
}
419420

420-
db, err := common.GetContextOrgDB(c)
421-
if err != nil {
422-
response.JSON(c, response.SetOptStatus(httpcommon.GET_ORG_DB_FAIL), response.SetError(err))
423-
return
424-
}
421+
var data model.AdditionalResource
422+
err = json.Unmarshal(b, &data)
423+
// invalidate request body
424+
if err != nil {
425+
response.JSON(c, response.SetOptStatus(httpcommon.INVALID_PARAMETERS), response.SetError(err))
426+
return
427+
}
428+
429+
db, err := common.GetContextOrgDB(c)
430+
if err != nil {
431+
response.JSON(c, response.SetOptStatus(httpcommon.GET_ORG_DB_FAIL), response.SetError(err))
432+
return
433+
}
425434

426-
err = resource.ApplyDomainAddtionalResource(data, db)
427-
response.JSON(c, response.SetError(err))
435+
err = resource.ApplyDomainAdditionalResource(data, db)
436+
response.JSON(c, response.SetError(err))
437+
})
428438
}
429439

430-
func listDomainAddtionalResource(c *gin.Context) {
440+
func listDomainAdditionalResource(c *gin.Context) {
431441
var resourceType, resourceName string
432442
t, ok := c.GetQuery("type")
433443
if ok {
@@ -457,38 +467,45 @@ func GetDomainAdditionalResourceExample(c *gin.Context) {
457467
response.JSON(c, response.SetData(data), response.SetError(err))
458468
}
459469

460-
func updateDomainAddtionalResourceAdvanced(c *gin.Context) {
461-
db, err := common.GetContextOrgDB(c)
462-
if err != nil {
463-
response.JSON(c, response.SetOptStatus(httpcommon.GET_ORG_DB_FAIL), response.SetError(err))
464-
return
465-
}
466-
467-
data := &model.AdditionalResource{}
468-
err = c.ShouldBindBodyWith(&data, binding.YAML)
469-
if err == nil || err == io.EOF {
470-
if err = resource.ApplyDomainAddtionalResource(*data, db); err != nil {
471-
response.JSON(c, response.SetError(err))
470+
func updateDomainAdditionalResourceAdvanced(warrantCfg configs.Warrant) gin.HandlerFunc {
471+
return gin.HandlerFunc(func(c *gin.Context) {
472+
if err := checkCMDBLicense(warrantCfg); err != nil {
473+
response.JSON(c, response.SetOptStatus(httpcommon.NO_LICENSE), response.SetError(err))
472474
return
473475
}
474-
d, err := resource.GetDomainAdditionalResource("", "", db)
476+
477+
db, err := common.GetContextOrgDB(c)
475478
if err != nil {
476-
response.JSON(c, response.SetError(err))
479+
response.JSON(c, response.SetOptStatus(httpcommon.GET_ORG_DB_FAIL), response.SetError(err))
477480
return
478481
}
479-
b, err := yaml.Marshal(d)
480-
if err != nil {
481-
response.JSON(c, response.SetError(err))
482+
483+
data := &model.AdditionalResource{}
484+
err = c.ShouldBindBodyWith(&data, binding.YAML)
485+
if err == nil || err == io.EOF {
486+
if err = resource.ApplyDomainAdditionalResource(*data, db); err != nil {
487+
response.JSON(c, response.SetError(err))
488+
return
489+
}
490+
d, err := resource.GetDomainAdditionalResource("", "", db)
491+
if err != nil {
492+
response.JSON(c, response.SetError(err))
493+
return
494+
}
495+
b, err := yaml.Marshal(d)
496+
if err != nil {
497+
response.JSON(c, response.SetError(err))
498+
return
499+
}
500+
response.JSON(c, response.SetData(string(b))) // TODO 不需要转换类型
501+
} else {
502+
response.JSON(c, response.SetOptStatus(httpcommon.INVALID_PARAMETERS), response.SetError(err))
482503
return
483504
}
484-
response.JSON(c, response.SetData(string(b))) // TODO 不需要转换类型
485-
} else {
486-
response.JSON(c, response.SetOptStatus(httpcommon.INVALID_PARAMETERS), response.SetError(err))
487-
return
488-
}
505+
})
489506
}
490507

491-
func getDomainAddtionalResourceAdvanced(c *gin.Context) {
508+
func getDomainAdditionalResourceAdvanced(c *gin.Context) {
492509
db, err := common.GetContextOrgDB(c)
493510
if err != nil {
494511
response.JSON(c, response.SetOptStatus(httpcommon.GET_ORG_DB_FAIL), response.SetError(err))
@@ -507,3 +524,29 @@ func getDomainAddtionalResourceAdvanced(c *gin.Context) {
507524
}
508525
response.JSON(c, response.SetData(string(b))) // TODO 不需要转换类型
509526
}
527+
528+
func checkCMDBLicense(warrantCfg configs.Warrant) error {
529+
if !warrantCfg.Enabled {
530+
return nil
531+
}
532+
body := make(map[string]interface{})
533+
response, err := ctrlCommon.CURLPerform(
534+
http.MethodGet,
535+
fmt.Sprintf(
536+
"http://%s:%d/licensedata",
537+
warrantCfg.Host, warrantCfg.Port,
538+
),
539+
body,
540+
)
541+
if err != nil {
542+
return err
543+
}
544+
for k, v := range response.Get("DATA").Get("LICENSE").MustMap() {
545+
if k == "ASSET_CMDB_COUNT" {
546+
if v.(int) != 0 {
547+
return nil
548+
}
549+
}
550+
}
551+
return fmt.Errorf("no license for cmdb")
552+
}

server/controller/http/service/resource/domain_additional_resource.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func newAddtionalResourceToolDataSet(regionUUID string) *addtionalResourceToolDa
7474
}
7575
}
7676

77-
func ApplyDomainAddtionalResource(reqData model.AdditionalResource, orgDB *metadb.DB) error {
77+
func ApplyDomainAdditionalResource(reqData model.AdditionalResource, orgDB *metadb.DB) error {
7878
log.Infof("apply domain additional resource: %#v", reqData, orgDB.LogPrefixORGID)
7979
domainUUIDToToolDataSet, err := generateToolDataSet(reqData, orgDB)
8080
if err != nil {

server/controller/monitor/config/config.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@
1616

1717
package config
1818

19-
type Warrant struct {
20-
Host string `default:"warrant" yaml:"warrant"`
21-
Port int `default:"20413" yaml:"port"`
22-
Timeout int `default:"30" yaml:"timeout"`
23-
}
19+
import (
20+
configs "github.com/deepflowio/deepflow/server/controller/config/common"
21+
)
2422

2523
type MonitorConfig struct {
2624
HealthCheckInterval int `default:"60" yaml:"health_check_interval"`
@@ -32,7 +30,7 @@ type MonitorConfig struct {
3230
AutoRebalanceVTap bool `default:"true" yaml:"auto_rebalance_vtap"`
3331
RebalanceCheckInterval int `default:"300" yaml:"rebalance_check_interval"` // unit: second
3432
VTapAutoDelete VTapAutoDelete `yaml:"vtap_auto_delete"`
35-
Warrant Warrant `yaml:"warrant"`
33+
Warrant configs.Warrant `yaml:"warrant"`
3634
IngesterLoadBalancingConfig IngesterLoadBalancingStrategy `yaml:"ingester-load-balancing-strategy"`
3735
SyncDefaultORGDataInterval int `default:"10" yaml:"sync_default_org_data_interval"`
3836
}

server/controller/recorder/domain.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,20 @@ func (d *domain) refreshDomainExcludeSubDomain(cloudData cloudmodel.Resource) er
102102
return d.tryRefresh(cloudData)
103103
}
104104

105+
func (d *domain) checkLicense() error {
106+
var domain *metadbmodel.Domain
107+
err := d.metadata.DB.Select("state").Where("lcuuid = ?", d.metadata.Domain.Lcuuid).First(&domain).Error
108+
if err != nil {
109+
log.Errorf("failed to get domain from db: %s", err, d.metadata.LogPrefixes)
110+
return err
111+
}
112+
if domain.State == common.RESOURCE_STATE_CODE_NO_LICENSE {
113+
log.Errorf("domain %s has no license", d.metadata.Domain.Lcuuid, d.metadata.LogPrefixes)
114+
return errors.New("domain has no license")
115+
}
116+
return nil
117+
}
118+
105119
func (d *domain) tryRefresh(cloudData cloudmodel.Resource) error {
106120
// 无论是否会更新资源,需先更新domain及subdomain状态
107121
d.updateStateInfo(cloudData)

server/server.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ controller:
100100
port: 20823
101101
timeout: 30
102102

103+
warrant:
104+
enabled: false
105+
host: warrant
106+
port: 20413
107+
timeout: 30
108+
103109
# mysql相关配置
104110
mysql:
105111
enabled: true
@@ -217,6 +223,7 @@ controller:
217223
# lost_time_max: 3600
218224
# warrant
219225
warrant:
226+
enabled: false
220227
host: warrant
221228
port: 20413
222229
timeout: 30

0 commit comments

Comments
 (0)