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: consume the new licenses v3 structure. #6341

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
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
15 changes: 15 additions & 0 deletions ee/query-service/app/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,25 @@ func (ah *APIHandler) RegisterRoutes(router *mux.Router, am *baseapp.AuthMiddlew
router.HandleFunc("/api/v1/dashboards/{uuid}/lock", am.EditAccess(ah.lockDashboard)).Methods(http.MethodPut)
router.HandleFunc("/api/v1/dashboards/{uuid}/unlock", am.EditAccess(ah.unlockDashboard)).Methods(http.MethodPut)

// v2
router.HandleFunc("/api/v2/licenses",
am.ViewAccess(ah.listLicensesV2)).
Methods(http.MethodGet)

// v3
router.HandleFunc("/api/v3/licenses",
am.AdminAccess(ah.listLicensesV3)).
Methods(http.MethodGet)
Comment on lines +182 to +184
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All folks need access to this endpoint (not just admin).


router.HandleFunc("/api/v3/licenses",
am.AdminAccess(ah.applyLicenseV3)).
Methods(http.MethodPost)

router.HandleFunc("/api/v3/licenses/refresh",
am.AdminAccess(ah.refreshLicensesV3)).
Methods(http.MethodPut)

// v4
router.HandleFunc("/api/v4/query_range", am.ViewAccess(ah.queryRangeV4)).Methods(http.MethodPost)

// Gateway
Expand Down
56 changes: 56 additions & 0 deletions ee/query-service/app/api/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,62 @@ func (ah *APIHandler) applyLicense(w http.ResponseWriter, r *http.Request) {
ah.Respond(w, license)
}

func (ah *APIHandler) listLicensesV3(w http.ResponseWriter, r *http.Request) {
licenses, apiError := ah.LM().GetLicensesV3(r.Context())

if apiError != nil {
RespondError(w, apiError, nil)
return
}

ah.Respond(w, licenses)
}

// this function is called by zeus when inserting licenses in the query-service
func (ah *APIHandler) applyLicenseV3(w http.ResponseWriter, r *http.Request) {
var license model.LicenseV3

if err := json.NewDecoder(r.Body).Decode(&license); err != nil {
RespondError(w, model.BadRequest(err), nil)
return
}
vikrantgupta25 marked this conversation as resolved.
Show resolved Hide resolved

if license.Key == "" {
RespondError(w, model.BadRequest(fmt.Errorf("license key is required")), nil)
return
}

l, apiError := ah.LM().ActivateV3(r.Context(), &license)
if apiError != nil {
RespondError(w, apiError, nil)
return
}

ah.Respond(w, l)
}

func (ah *APIHandler) refreshLicensesV3(w http.ResponseWriter, r *http.Request) {
vikrantgupta25 marked this conversation as resolved.
Show resolved Hide resolved
var license model.LicenseV3

if err := json.NewDecoder(r.Body).Decode(&license); err != nil {
RespondError(w, model.BadRequest(err), nil)
return
}

if license.Key == "" {
RespondError(w, model.BadRequest(fmt.Errorf("license key is required")), nil)
return
}

l, apiError := ah.LM().RefreshLicense(r.Context(), &license)
if apiError != nil {
RespondError(w, apiError, nil)
return
}

ah.Respond(w, l)
}

func (ah *APIHandler) checkout(w http.ResponseWriter, r *http.Request) {

type checkoutResponse struct {
Expand Down
3 changes: 2 additions & 1 deletion ee/query-service/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type ServerOptions struct {
Cluster string
GatewayUrl string
UseLogsNewSchema bool
UseLicensesV3 bool
}

// Server runs HTTP api service
Expand Down Expand Up @@ -134,7 +135,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
}

// initiate license manager
lm, err := licensepkg.StartManager("sqlite", localDB)
lm, err := licensepkg.StartManager("sqlite", localDB, serverOptions.UseLicensesV3)
if err != nil {
return nil, err
}
Expand Down
39 changes: 37 additions & 2 deletions ee/query-service/integrations/signozio/signozio.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ const (
)

type Client struct {
Prefix string
Prefix string
GatewayUrl string
}

func New() *Client {
return &Client{
Prefix: constants.LicenseSignozIo,
Prefix: constants.LicenseSignozIo,
GatewayUrl: constants.ZeusFeaturesURL,
}
}

Expand Down Expand Up @@ -116,6 +118,39 @@ func ValidateLicense(activationId string) (*ActivationResponse, *model.ApiError)

}

func ValidateLicenseV3() (*model.LicenseV3, *model.ApiError) {

response, err := http.Get(C.GatewayUrl + "/licenses/me")

if err != nil {
return nil, model.BadRequest(errors.Wrap(err, fmt.Sprintf("unable to connect with %v, please check your network connection", C.GatewayUrl)))
}

body, err := io.ReadAll(response.Body)
if err != nil {
return nil, model.BadRequest(errors.Wrap(err, fmt.Sprintf("failed to read validation response from %v", C.GatewayUrl)))
}

defer response.Body.Close()

switch response.StatusCode {
case 200, 201:
a := model.LicenseV3{}
err = json.Unmarshal(body, &a)
if err != nil {
return nil, model.BadRequest(errors.Wrap(err, "failed to marshal license validation response"))
}
return &a, nil
case 400, 401:
return nil, model.BadRequest(errors.Wrap(fmt.Errorf(string(body)),
"bad request error received from license.signoz.io"))
default:
return nil, model.InternalError(errors.Wrap(fmt.Errorf(string(body)),
"internal error received from license.signoz.io"))
}

}

func NewPostRequestWithCtx(ctx context.Context, url string, contentType string, body io.Reader) (*http.Request, error) {
req, err := http.NewRequestWithContext(ctx, POST, url, body)
if err != nil {
Expand Down
123 changes: 123 additions & 0 deletions ee/query-service/license/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package license
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"time"

Expand Down Expand Up @@ -48,6 +49,32 @@ func (r *Repo) GetLicenses(ctx context.Context) ([]model.License, error) {
return licenses, nil
}

func (r *Repo) GetLicensesV3(ctx context.Context) ([]model.LicenseV3, error) {
licensesData := []string{}

query := "SELECT data FROM licenses_v3"

err := r.db.Select(&licensesData, query)
if err != nil {
return nil, fmt.Errorf("failed to get licenses from db: %v", err)
}

licenses := []model.LicenseV3{}

for _, l := range licensesData {
var license model.LicenseV3

err = json.Unmarshal([]byte(l), &license)
if err != nil {
return nil, basemodel.InternalError(fmt.Errorf("failed to unmarshal licenses from db: %v", err))
}

licenses = append(licenses, license)
}

return licenses, nil
}

// 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) {
Expand Down Expand Up @@ -79,6 +106,44 @@ func (r *Repo) GetActiveLicense(ctx context.Context) (*model.License, *basemodel
return active, nil
}

func (r *Repo) GetActiveLicenseV3(ctx context.Context) (*model.LicenseV3, *basemodel.ApiError) {
var err error
licensesString := []string{}

query := "SELECT data FROM licenses_v3"

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

var active *model.LicenseV3
for _, l := range licensesString {
license := model.LicenseV3{}

err = json.Unmarshal([]byte(l), &license)
if err != nil {
return nil, basemodel.InternalError(fmt.Errorf("failed to unmarshal licenses from db: %v", err))
}

// insert all the features to the license based on the plan!
license.ParseFeaturesV3()

if active == nil &&
(license.ValidFrom != 0) &&
(license.ValidUntil == -1 || license.ValidUntil > time.Now().Unix()) {
active = &license
}
if active != nil &&
license.ValidFrom > active.ValidFrom &&
(license.ValidUntil == -1 || license.ValidUntil > time.Now().Unix()) {
active = &license
}
}

return active, nil
}

// InsertLicense inserts a new license in db
func (r *Repo) InsertLicense(ctx context.Context, l *model.License) error {

Expand Down Expand Up @@ -204,3 +269,61 @@ func (r *Repo) InitFeatures(req basemodel.FeatureSet) error {
}
return nil
}

// InsertLicenseV3 inserts a new license v3 in db
func (r *Repo) InsertLicenseV3(ctx context.Context, l *model.LicenseV3) error {

if l.Key == "" {
return fmt.Errorf("insert license failed: license key is required")
}
query := `INSERT INTO licenses_v3
(id, key, data)
VALUES ($1, $2, $3)`

// licsense is the entity of zeus so putting the entire license here without defining schema
license, err := json.Marshal(l)
if err != nil {
return fmt.Errorf("insert license failed: license marshal error")
}
_, err = r.db.ExecContext(ctx,
query,
l.ID,
l.Key,
string(license),
)

if err != nil {
zap.L().Error("error in inserting license data: ", zap.Error(err))
return fmt.Errorf("failed to insert license in db: %v", err)
}

return nil
}

// UpdateLicenseV3 updates a new license v3 in db
func (r *Repo) UpdateLicenseV3(ctx context.Context, l *model.LicenseV3) error {

if l.Key == "" {
return fmt.Errorf("update license failed: license key is required")
}

// the key and id for the license can't change so only update the data here!
query := `UPDATE licenses_v3 SET data=$1 WHERE id=$2;`

license, err := json.Marshal(l)
if err != nil {
return fmt.Errorf("insert license failed: license marshal error")
}
_, err = r.db.ExecContext(ctx,
query,
license,
l.ID,
)

if err != nil {
zap.L().Error("error in updating license data: ", zap.Error(err))
return fmt.Errorf("failed to update license in db: %v", err)
}

return nil
}
Loading
Loading