Skip to content

Commit

Permalink
rpk: show nag for free_trial about to expire
Browse files Browse the repository at this point in the history
Now the license nags will be shown for customers
with free_trial licenses that has less than 15
days left.
  • Loading branch information
r-vasquez committed Oct 29, 2024
1 parent 76dec5a commit 84a3ff0
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 14 deletions.
38 changes: 30 additions & 8 deletions src/go/rpk/pkg/adminapi/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"fmt"
"os"
"strconv"
"strings"
"time"

"go.uber.org/zap"
Expand Down Expand Up @@ -137,22 +138,31 @@ func licenseFeatureChecks(ctx context.Context, fs afero.Fs, cl *rpadmin.AdminAPI
// violation. (we only save successful responses).
// 2. LicenseStatus was last checked more than 1 hour ago.
if p.LicenseCheck == nil || p.LicenseCheck != nil && time.Unix(p.LicenseCheck.LastUpdate, 0).Add(1*time.Hour).Before(time.Now()) {
resp, err := cl.GetEnterpriseFeatures(ctx)
featResp, err := cl.GetEnterpriseFeatures(ctx)
if err != nil {
zap.L().Sugar().Warnf("unable to check licensed enterprise features in the cluster: %v", err)
return ""
}
info, err := cl.GetLicenseInfo(ctx)
if err != nil {
zap.L().Sugar().Warnf("unable to check license information: %v", err)
return ""
}
// We don't write a profile if the config doesn't exist.
y, exists := p.ActualConfig()
var licenseCheck *config.LicenseStatusCache
if resp.Violation {
var features []string
for _, f := range resp.Features {
if f.Enabled {
features = append(features, f.Name)
}
var enabledFeatures []string
for _, f := range featResp.Features {
if f.Enabled {
enabledFeatures = append(enabledFeatures, f.Name)
}
msg = fmt.Sprintf("\nWARNING: The following Enterprise features are being used in your Redpanda cluster: %v. These features require a license. To get a license, contact us at https://www.redpanda.com/contact. For more information, see https://docs.redpanda.com/current/get-started/licenses/#redpanda-enterprise-edition\n", features)
}
isTrialCheck := isTrialAboutToExpire(info, enabledFeatures)

if featResp.Violation {
msg = fmt.Sprintf("\nWARNING: The following Enterprise features are being used in your Redpanda cluster: %v. These features require a license. To get a license, contact us at https://www.redpanda.com/contact. For more information, see https://docs.redpanda.com/current/get-started/licenses/#redpanda-enterprise-edition\n", enabledFeatures)
} else if isTrialCheck {
msg = fmt.Sprintf("\nWARNING: your TRIAL license is about to expire. The following Enterprise features are being used in your Redpanda cluster: %v. These features require a license. To get a license, contact us at https://www.redpanda.com/contact. For more information, see https://docs.redpanda.com/current/get-started/licenses/#redpanda-enterprise-edition\n", enabledFeatures)
} else {
licenseCheck = &config.LicenseStatusCache{
LastUpdate: time.Now().Unix(),
Expand All @@ -170,3 +180,15 @@ func licenseFeatureChecks(ctx context.Context, fs afero.Fs, cl *rpadmin.AdminAPI
}
return msg
}

// isTrialAboutToExpire returns true if we have a loaded free_trial license that
// expires in less than 15 days, and we have enterprise features enabled.
func isTrialAboutToExpire(info rpadmin.License, enabledFeatures []string) bool {
if len(enabledFeatures) > 0 && info.Loaded && strings.EqualFold(info.Properties.Type, "free_trial") {
ut := time.Unix(info.Properties.Expires, 0)
daysLeft := int(time.Until(ut).Hours() / 24)

return daysLeft < 15 && !ut.Before(time.Now())
}
return false
}
42 changes: 36 additions & 6 deletions src/go/rpk/pkg/adminapi/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package adminapi

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"
Expand All @@ -16,7 +17,7 @@ func Test_licenseFeatureChecks(t *testing.T) {
tests := []struct {
name string
prof *config.RpkProfile
responseCase string // See the mapLicenseResponses below.
responseCase string // See the mapLicenseFeatureResponses below.
expContain string
withErr bool
checkCache func(t *testing.T, before int64, after int64)
Expand All @@ -27,6 +28,18 @@ func Test_licenseFeatureChecks(t *testing.T) {
responseCase: "ok",
expContain: "",
},
{
name: "free_trial about to expire, no features",
prof: &config.RpkProfile{},
responseCase: "ok-free",
expContain: "",
},
{
name: "free_trial about to expire, with features",
prof: &config.RpkProfile{},
responseCase: "ok-features",
expContain: "WARNING: your TRIAL license is about to expire",
},
{
name: "license ok, cache valid",
prof: &config.RpkProfile{LicenseCheck: &config.LicenseStatusCache{LastUpdate: time.Now().Add(20 * time.Minute).Unix()}},
Expand Down Expand Up @@ -144,16 +157,33 @@ type response struct {
body string
}

var mapLicenseResponses = map[string]response{
"ok": {http.StatusOK, `{"license_status": "valid", "violation": false}`},
var mapLicenseFeatureResponses = map[string]response{
"ok": {http.StatusOK, `{"license_status": "valid", "violation": false, "features": [{"name": "fips", "enabled": true},{"name": "partition_auto_balancing_continuous", "enabled": false}]}`},
"inViolation": {http.StatusOK, `{"license_status": "expired", "violation": true, "features": [{"name": "partition_auto_balancing_continuous", "enabled": true}]}`},
"failedRequest": {http.StatusBadRequest, ""},
"ok-free": {http.StatusOK, `{"license_status": "valid", "violation": false}`},
"ok-features": {http.StatusOK, `{"license_status": "valid", "violation": false, "features": [{"name": "partition_auto_balancing_continuous", "enabled": true}]}`},
}

var mapLicenseInfoResponses = map[string]response{
"ok": {http.StatusOK, fmt.Sprintf(`{"loaded": true, "license": {"type": "enterprise", "expires": %d}}`, time.Now().Add(60*24*time.Hour).Unix())},
"inViolation": {http.StatusOK, fmt.Sprintf(`{"loaded": true, "license": {"type": "enterprise", "expires": %d}}`, time.Now().Add(60*24*time.Hour).Unix())},
"failedRequest": {http.StatusBadRequest, ""},
"ok-free": {http.StatusOK, fmt.Sprintf(`{"loaded": true, "license": {"type": "free_trial", "expires": %d}}`, time.Now().Add(24*time.Hour).Unix())}, // expires in 1 day.
"ok-features": {http.StatusOK, fmt.Sprintf(`{"loaded": true, "license": {"type": "free_trial", "expires": %d}}`, time.Now().Add(24*time.Hour).Unix())},
}

func licenseHandler(respCase string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
resp := mapLicenseResponses[respCase]
w.WriteHeader(resp.status)
w.Write([]byte(resp.body))
fmt.Println(r.URL.Path)
if r.URL.Path == "/v1/features/enterprise" {
resp := mapLicenseFeatureResponses[respCase]
w.WriteHeader(resp.status)
w.Write([]byte(resp.body))
} else if r.URL.Path == "/v1/features/license" {
resp := mapLicenseInfoResponses[respCase]
w.WriteHeader(resp.status)
w.Write([]byte(resp.body))
}
}
}

0 comments on commit 84a3ff0

Please sign in to comment.