Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(licenses): deprecate licenses v2 #6626

Merged
merged 6 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions ee/query-service/app/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ type APIHandlerOptions struct {
FluxInterval time.Duration
UseLogsNewSchema bool
UseTraceNewSchema bool
UseLicensesV3 bool
}

type APIHandler struct {
Expand All @@ -68,7 +67,6 @@ func NewAPIHandler(opts APIHandlerOptions) (*APIHandler, error) {
FluxInterval: opts.FluxInterval,
UseLogsNewSchema: opts.UseLogsNewSchema,
UseTraceNewSchema: opts.UseTraceNewSchema,
UseLicensesV3: opts.UseLicensesV3,
})

if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion ee/query-service/app/api/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (ah *APIHandler) applyLicense(w http.ResponseWriter, r *http.Request) {
RespondError(w, model.BadRequest(fmt.Errorf("license key is required")), nil)
return
}
license, apiError := ah.LM().Activate(r.Context(), l.Key)
vikrantgupta25 marked this conversation as resolved.
Show resolved Hide resolved
license, apiError := ah.LM().ActivateV3(r.Context(), l.Key)
if apiError != nil {
RespondError(w, apiError, nil)
return
Expand Down
3 changes: 1 addition & 2 deletions ee/query-service/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
}

// initiate license manager
lm, err := licensepkg.StartManager("sqlite", localDB, serverOptions.UseLicensesV3)
lm, err := licensepkg.StartManager("sqlite", localDB)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -274,7 +274,6 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
Gateway: gatewayProxy,
UseLogsNewSchema: serverOptions.UseLogsNewSchema,
UseTraceNewSchema: serverOptions.UseTraceNewSchema,
UseLicensesV3: serverOptions.UseLicensesV3,
}

apiHandler, err := api.NewAPIHandler(apiOpts)
Expand Down
32 changes: 10 additions & 22 deletions ee/query-service/license/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@ import (

// Repo is license repo. stores license keys in a secured DB
type Repo struct {
db *sqlx.DB
useLicensesV3 bool
db *sqlx.DB
}

// NewLicenseRepo initiates a new license repo
func NewLicenseRepo(db *sqlx.DB, useLicensesV3 bool) Repo {
func NewLicenseRepo(db *sqlx.DB) Repo {
return Repo{
db: db,
useLicensesV3: useLicensesV3,
db: db,
}
}

Expand Down Expand Up @@ -112,26 +110,16 @@ func (r *Repo) GetActiveLicenseV2(ctx context.Context) (*model.License, *basemod
// GetActiveLicense fetches the latest active license from DB.
// If the license is not present, expect a nil license and a nil error in the output.
func (r *Repo) GetActiveLicense(ctx context.Context) (*model.License, *basemodel.ApiError) {
if r.useLicensesV3 {
zap.L().Info("Using licenses v3 for GetActiveLicense")
activeLicenseV3, err := r.GetActiveLicenseV3(ctx)
if err != nil {
return nil, basemodel.InternalError(fmt.Errorf("failed to get active licenses from db: %v", err))
}

if activeLicenseV3 == nil {
return nil, nil
}
activeLicenseV2 := model.ConvertLicenseV3ToLicenseV2(activeLicenseV3)
return activeLicenseV2, nil

activeLicenseV3, err := r.GetActiveLicenseV3(ctx)
if err != nil {
return nil, basemodel.InternalError(fmt.Errorf("failed to get active licenses from db: %v", err))
}

active, err := r.GetActiveLicenseV2(ctx)
if err != nil {
return nil, err
if activeLicenseV3 == nil {
return nil, nil
}
return active, nil
activeLicenseV2 := model.ConvertLicenseV3ToLicenseV2(activeLicenseV3)
return activeLicenseV2, nil
}

func (r *Repo) GetActiveLicenseV3(ctx context.Context) (*model.LicenseV3, error) {
Expand Down
227 changes: 5 additions & 222 deletions ee/query-service/license/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ type Manager struct {
activeFeatures basemodel.FeatureSet
}

func StartManager(dbType string, db *sqlx.DB, useLicensesV3 bool, features ...basemodel.Feature) (*Manager, error) {
func StartManager(dbType string, db *sqlx.DB, features ...basemodel.Feature) (*Manager, error) {
if LM != nil {
return LM, nil
}

repo := NewLicenseRepo(db, useLicensesV3)
repo := NewLicenseRepo(db)
err := repo.InitDB(dbType)

if err != nil {
Expand All @@ -67,81 +67,23 @@ func StartManager(dbType string, db *sqlx.DB, useLicensesV3 bool, features ...ba
repo: &repo,
}

if useLicensesV3 {
// get active license from the db
active, err := m.repo.GetActiveLicenseV2(context.Background())
if err != nil {
return m, err
}

// if we have an active license then need to fetch the complete details
if active != nil {
// fetch the new license structure from control plane
licenseV3, apiError := validate.ValidateLicenseV3(active.Key)
if apiError != nil {
return m, apiError
}

// insert the licenseV3 in sqlite db
apiError = m.repo.InsertLicenseV3(context.Background(), licenseV3)
// if the license already exists move ahead.
if apiError != nil && apiError.Typ != model.ErrorConflict {
return m, apiError
}
zap.L().Info("Successfully inserted license from v2 to v3 table")
}
}

if err := m.start(useLicensesV3, features...); err != nil {
if err := m.start(features...); err != nil {
return m, err
}
LM = m
return m, nil
}

// start loads active license in memory and initiates validator
func (lm *Manager) start(useLicensesV3 bool, features ...basemodel.Feature) error {

var err error
if useLicensesV3 {
err = lm.LoadActiveLicenseV3(features...)
} else {
err = lm.LoadActiveLicense(features...)
}

return err
func (lm *Manager) start(features ...basemodel.Feature) error {
return lm.LoadActiveLicenseV3(features...)
}

func (lm *Manager) Stop() {
close(lm.done)
<-lm.terminated
}

func (lm *Manager) SetActive(l *model.License, features ...basemodel.Feature) {
lm.mutex.Lock()
defer lm.mutex.Unlock()

if l == nil {
return
}

lm.activeLicense = l
lm.activeFeatures = append(l.FeatureSet, features...)
// set default features
setDefaultFeatures(lm)

err := lm.InitFeatures(lm.activeFeatures)
if err != nil {
zap.L().Panic("Couldn't activate features", zap.Error(err))
}
if !lm.validatorRunning {
// we want to make sure only one validator runs,
// we already have lock() so good to go
lm.validatorRunning = true
go lm.Validator(context.Background())
}

}
func (lm *Manager) SetActiveV3(l *model.LicenseV3, features ...basemodel.Feature) {
lm.mutex.Lock()
defer lm.mutex.Unlock()
Expand Down Expand Up @@ -172,29 +114,6 @@ func setDefaultFeatures(lm *Manager) {
lm.activeFeatures = append(lm.activeFeatures, baseconstants.DEFAULT_FEATURE_SET...)
}

// LoadActiveLicense loads the most recent active license
func (lm *Manager) LoadActiveLicense(features ...basemodel.Feature) error {
active, err := lm.repo.GetActiveLicense(context.Background())
if err != nil {
return err
}
if active != nil {
lm.SetActive(active, features...)
} else {
zap.L().Info("No active license found, defaulting to basic plan")
// if no active license is found, we default to basic(free) plan with all default features
lm.activeFeatures = model.BasicPlan
setDefaultFeatures(lm)
err := lm.InitFeatures(lm.activeFeatures)
if err != nil {
zap.L().Error("Couldn't initialize features", zap.Error(err))
return err
}
}

return nil
}

func (lm *Manager) LoadActiveLicenseV3(features ...basemodel.Feature) error {
active, err := lm.repo.GetActiveLicenseV3(context.Background())
if err != nil {
Expand Down Expand Up @@ -265,31 +184,6 @@ func (lm *Manager) GetLicensesV3(ctx context.Context) (response []*model.License
return response, nil
}

// Validator validates license after an epoch of time
func (lm *Manager) Validator(ctx context.Context) {
zap.L().Info("Validator started!")
defer close(lm.terminated)
tick := time.NewTicker(validationFrequency)
defer tick.Stop()

lm.Validate(ctx)

for {
select {
case <-lm.done:
return
default:
select {
case <-lm.done:
return
case <-tick.C:
lm.Validate(ctx)
}
}

}
}

// Validator validates license after an epoch of time
func (lm *Manager) ValidatorV3(ctx context.Context) {
zap.L().Info("ValidatorV3 started!")
Expand All @@ -315,73 +209,6 @@ func (lm *Manager) ValidatorV3(ctx context.Context) {
}
}

// Validate validates the current active license
func (lm *Manager) Validate(ctx context.Context) (reterr error) {
zap.L().Info("License validation started")
if lm.activeLicense == nil {
return nil
}

defer func() {
lm.mutex.Lock()

lm.lastValidated = time.Now().Unix()
if reterr != nil {
zap.L().Error("License validation completed with error", zap.Error(reterr))
atomic.AddUint64(&lm.failedAttempts, 1)
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_LICENSE_CHECK_FAILED,
map[string]interface{}{"err": reterr.Error()}, "", true, false)
} else {
zap.L().Info("License validation completed with no errors")
}

lm.mutex.Unlock()
}()

response, apiError := validate.ValidateLicense(lm.activeLicense.ActivationId)
if apiError != nil {
zap.L().Error("failed to validate license", zap.Error(apiError.Err))
return apiError.Err
}

if response.PlanDetails == lm.activeLicense.PlanDetails {
// license plan hasnt changed, nothing to do
return nil
}

if response.PlanDetails != "" {

// copy and replace the active license record
l := model.License{
Key: lm.activeLicense.Key,
CreatedAt: lm.activeLicense.CreatedAt,
PlanDetails: response.PlanDetails,
ValidationMessage: lm.activeLicense.ValidationMessage,
ActivationId: lm.activeLicense.ActivationId,
}

if err := l.ParsePlan(); err != nil {
zap.L().Error("failed to parse updated license", zap.Error(err))
return err
}

// updated plan is parsable, check if plan has changed
if lm.activeLicense.PlanDetails != response.PlanDetails {
err := lm.repo.UpdatePlanDetails(ctx, lm.activeLicense.Key, response.PlanDetails)
if err != nil {
// unexpected db write issue but we can let the user continue
// and wait for update to work in next cycle.
zap.L().Error("failed to validate license", zap.Error(err))
}
}

// activate the update license plan
lm.SetActive(&l)
}

return nil
}

func (lm *Manager) RefreshLicense(ctx context.Context) *model.ApiError {

license, apiError := validate.ValidateLicenseV3(lm.activeLicenseV3.Key)
Expand Down Expand Up @@ -429,50 +256,6 @@ func (lm *Manager) ValidateV3(ctx context.Context) (reterr error) {
return nil
}

// Activate activates a license key with signoz server
func (lm *Manager) Activate(ctx context.Context, key string) (licenseResponse *model.License, errResponse *model.ApiError) {
defer func() {
if errResponse != nil {
userEmail, err := auth.GetEmailFromJwt(ctx)
if err == nil {
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_LICENSE_ACT_FAILED,
map[string]interface{}{"err": errResponse.Err.Error()}, userEmail, true, false)
}
}
}()

response, apiError := validate.ActivateLicense(key, "")
if apiError != nil {
zap.L().Error("failed to activate license", zap.Error(apiError.Err))
return nil, apiError
}

l := &model.License{
Key: key,
ActivationId: response.ActivationId,
PlanDetails: response.PlanDetails,
}

// parse validity and features from the plan details
err := l.ParsePlan()

if err != nil {
zap.L().Error("failed to activate license", zap.Error(err))
return nil, model.InternalError(err)
}

// store the license before activating it
err = lm.repo.InsertLicense(ctx, l)
if err != nil {
zap.L().Error("failed to activate license", zap.Error(err))
return nil, model.InternalError(err)
}

// license is valid, activate it
lm.SetActive(l)
return l, nil
}

func (lm *Manager) ActivateV3(ctx context.Context, licenseKey string) (licenseResponse *model.LicenseV3, errResponse *model.ApiError) {
defer func() {
if errResponse != nil {
Expand Down
Loading
Loading