Skip to content

Commit 17ad797

Browse files
author
Simon Emms
committed
[licensor]: refactor evaluators into a single evaluator
The previous Gitpod and Replicated evaluators were functionally identical anyway as all the logic happens in the constructors
1 parent c6ab2d3 commit 17ad797

File tree

6 files changed

+62
-69
lines changed

6 files changed

+62
-69
lines changed

components/licensor/ee/cmd/validate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ var validateCmd = &cobra.Command{
2525
domain, _ := cmd.Flags().GetString("domain")
2626
licensorType, _ := cmd.Flags().GetString("licensor")
2727

28-
var e licensor.Evaluator
28+
var e *licensor.Evaluator
2929
switch licensorType {
3030
case string(licensor.LicenseTypeReplicated):
3131
e = licensor.NewReplicatedEvaluator(domain)

components/licensor/ee/pkg/licensor/gitpod.go

Lines changed: 9 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -14,73 +14,31 @@ import (
1414
"time"
1515
)
1616

17-
// GitpodEvaluator determines what a license allows for
18-
type GitpodEvaluator struct {
19-
invalid string
20-
lic LicensePayload
21-
}
22-
23-
// Validate returns false if the license isn't valid and a message explaining why that is.
24-
func (e *GitpodEvaluator) Validate() (msg string, valid bool) {
25-
if e.invalid == "" {
26-
return "", true
27-
}
28-
29-
return e.invalid, false
30-
}
31-
32-
// Enabled determines if a feature is enabled by the license
33-
func (e *GitpodEvaluator) Enabled(feature Feature) bool {
34-
if e.invalid != "" {
35-
return false
36-
}
37-
38-
_, ok := e.lic.Level.allowance().Features[feature]
39-
return ok
40-
}
41-
42-
// HasEnoughSeats returns true if the license supports at least the give amount of seats
43-
func (e *GitpodEvaluator) HasEnoughSeats(seats int) bool {
44-
if e.invalid != "" {
45-
return false
46-
}
47-
48-
return e.lic.Seats == 0 || seats <= e.lic.Seats
49-
}
50-
51-
// Inspect returns the license information this evaluator holds.
52-
// This function is intended for transparency/debugging purposes only and must
53-
// never be used to determine feature eligibility under a license. All code making
54-
// those kinds of decisions must be part of the Evaluator.
55-
func (e *GitpodEvaluator) Inspect() LicensePayload {
56-
return e.lic
57-
}
58-
5917
// NewGitpodEvaluator produces a new license evaluator from a license key
60-
func NewGitpodEvaluator(key []byte, domain string) (res *GitpodEvaluator) {
18+
func NewGitpodEvaluator(key []byte, domain string) (res *Evaluator) {
6119
if len(key) == 0 {
6220
// fallback to the default license
63-
return &GitpodEvaluator{
21+
return &Evaluator{
6422
lic: defaultLicense,
6523
}
6624
}
6725

6826
deckey := make([]byte, base64.StdEncoding.DecodedLen(len(key)))
6927
n, err := base64.StdEncoding.Decode(deckey, key)
7028
if err != nil {
71-
return &GitpodEvaluator{invalid: fmt.Sprintf("cannot decode key: %q", err)}
29+
return &Evaluator{invalid: fmt.Sprintf("cannot decode key: %q", err)}
7230
}
7331
deckey = deckey[:n]
7432

7533
var lic licensePayload
7634
err = json.Unmarshal(deckey, &lic)
7735
if err != nil {
78-
return &GitpodEvaluator{invalid: fmt.Sprintf("cannot unmarshal key: %q", err)}
36+
return &Evaluator{invalid: fmt.Sprintf("cannot unmarshal key: %q", err)}
7937
}
8038

8139
keyWoSig, err := json.Marshal(lic.LicensePayload)
8240
if err != nil {
83-
return &GitpodEvaluator{invalid: fmt.Sprintf("cannot remarshal key: %q", err)}
41+
return &Evaluator{invalid: fmt.Sprintf("cannot remarshal key: %q", err)}
8442
}
8543
hashed := sha256.Sum256(keyWoSig)
8644

@@ -91,18 +49,18 @@ func NewGitpodEvaluator(key []byte, domain string) (res *GitpodEvaluator) {
9149
}
9250
}
9351
if err != nil {
94-
return &GitpodEvaluator{invalid: fmt.Sprintf("cannot verify key: %q", err)}
52+
return &Evaluator{invalid: fmt.Sprintf("cannot verify key: %q", err)}
9553
}
9654

9755
if !matchesDomain(lic.Domain, domain) {
98-
return &GitpodEvaluator{invalid: "wrong domain"}
56+
return &Evaluator{invalid: "wrong domain"}
9957
}
10058

10159
if lic.ValidUntil.Before(time.Now()) {
102-
return &GitpodEvaluator{invalid: "not valid anymore"}
60+
return &Evaluator{invalid: "not valid anymore"}
10361
}
10462

105-
return &GitpodEvaluator{
63+
return &Evaluator{
10664
lic: lic.LicensePayload,
10765
}
10866
}

components/licensor/ee/pkg/licensor/licensor.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,46 @@ func matchesDomain(pattern, domain string) bool {
140140
return false
141141
}
142142

143-
type Evaluator interface {
144-
Enabled(feature Feature) bool
145-
HasEnoughSeats(seats int) bool
146-
Inspect() LicensePayload
147-
Validate() (msg string, valid bool)
143+
// Evaluator determines what a license allows for
144+
type Evaluator struct {
145+
invalid string
146+
lic LicensePayload
147+
}
148+
149+
// Validate returns false if the license isn't valid and a message explaining why that is.
150+
func (e *Evaluator) Validate() (msg string, valid bool) {
151+
if e.invalid == "" {
152+
return "", true
153+
}
154+
155+
return e.invalid, false
156+
}
157+
158+
// Enabled determines if a feature is enabled by the license
159+
func (e *Evaluator) Enabled(feature Feature) bool {
160+
if e.invalid != "" {
161+
return false
162+
}
163+
164+
_, ok := e.lic.Level.allowance().Features[feature]
165+
return ok
166+
}
167+
168+
// HasEnoughSeats returns true if the license supports at least the give amount of seats
169+
func (e *Evaluator) HasEnoughSeats(seats int) bool {
170+
if e.invalid != "" {
171+
return false
172+
}
173+
174+
return e.lic.Seats == 0 || seats <= e.lic.Seats
175+
}
176+
177+
// Inspect returns the license information this evaluator holds.
178+
// This function is intended for transparency/debugging purposes only and must
179+
// never be used to determine feature eligibility under a license. All code making
180+
// those kinds of decisions must be part of the Evaluator.
181+
func (e *Evaluator) Inspect() LicensePayload {
182+
return e.lic
148183
}
149184

150185
// Sign signs a license so that it can be used with the evaluator

components/licensor/ee/pkg/licensor/licensor_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const (
2525
type licenseTest struct {
2626
Name string
2727
License *LicensePayload
28-
Validate func(t *testing.T, eval Evaluator)
28+
Validate func(t *testing.T, eval *Evaluator)
2929
Type LicenseType
3030
NeverExpires bool
3131
}
@@ -47,7 +47,7 @@ func newTestClient(fn roundTripFunc) *http.Client {
4747

4848
func (test *licenseTest) Run(t *testing.T) {
4949
t.Run(test.Name, func(t *testing.T) {
50-
var eval Evaluator
50+
var eval *Evaluator
5151
if test.Type == LicenseTypeGitpod {
5252
if test.NeverExpires {
5353
t.Fatal("gitpod licenses must have an expiry date")
@@ -195,7 +195,7 @@ func TestSeats(t *testing.T) {
195195
Seats: test.Licensed,
196196
ValidUntil: validUntil,
197197
},
198-
Validate: func(t *testing.T, eval Evaluator) {
198+
Validate: func(t *testing.T, eval *Evaluator) {
199199
withinLimits := eval.HasEnoughSeats(test.Probe)
200200
if withinLimits != test.WithinLimits {
201201
t.Errorf("HasEnoughSeats did not behave as expected: lic=%d probe=%d expected=%v actual=%v", test.Licensed, test.Probe, test.WithinLimits, withinLimits)
@@ -253,7 +253,7 @@ func TestFeatures(t *testing.T) {
253253
lt := licenseTest{
254254
Name: test.Name,
255255
License: lic,
256-
Validate: func(t *testing.T, eval Evaluator) {
256+
Validate: func(t *testing.T, eval *Evaluator) {
257257
unavailableFeatures := featureSet{}
258258
for f := range allowanceMap[LevelEnterprise].Features {
259259
unavailableFeatures[f] = struct{}{}

components/licensor/ee/pkg/licensor/replicated.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,24 @@ func (e *ReplicatedEvaluator) Validate() (msg string, valid bool) {
6969
}
7070

7171
// defaultReplicatedLicense this is the default license if call fails
72-
func defaultReplicatedLicense() *ReplicatedEvaluator {
73-
return &ReplicatedEvaluator{
72+
func defaultReplicatedLicense() *Evaluator {
73+
return &Evaluator{
7474
lic: defaultLicense,
7575
}
7676
}
7777

7878
// newReplicatedEvaluator exists to allow mocking of client
79-
func newReplicatedEvaluator(client *http.Client, domain string) (res *ReplicatedEvaluator) {
79+
func newReplicatedEvaluator(client *http.Client, domain string) (res *Evaluator) {
8080
resp, err := client.Get(replicatedLicenseApiEndpoint)
8181
if err != nil {
82-
return &ReplicatedEvaluator{invalid: fmt.Sprintf("cannot query kots admin, %q", err)}
82+
return &Evaluator{invalid: fmt.Sprintf("cannot query kots admin, %q", err)}
8383
}
8484
defer resp.Body.Close()
8585

8686
var replicatedPayload replicatedLicensePayload
8787
err = json.NewDecoder(resp.Body).Decode(&replicatedPayload)
8888
if err != nil {
89-
return &ReplicatedEvaluator{invalid: fmt.Sprintf("cannot decode json data, %q", err)}
89+
return &Evaluator{invalid: fmt.Sprintf("cannot decode json data, %q", err)}
9090
}
9191

9292
lic := LicensePayload{
@@ -119,12 +119,12 @@ func newReplicatedEvaluator(client *http.Client, domain string) (res *Replicated
119119
}
120120
}
121121

122-
return &ReplicatedEvaluator{
122+
return &Evaluator{
123123
lic: lic,
124124
}
125125
}
126126

127127
// NewReplicatedEvaluator gets the license data from the kots admin panel
128-
func NewReplicatedEvaluator(domain string) (res *ReplicatedEvaluator) {
128+
func NewReplicatedEvaluator(domain string) (res *Evaluator) {
129129
return newReplicatedEvaluator(&http.Client{Timeout: replicatedLicenseApiTimeout}, domain)
130130
}

components/licensor/typescript/ee/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
)
1616

1717
var (
18-
instances map[int]licensor.Evaluator = make(map[int]licensor.Evaluator)
18+
instances map[int]*licensor.Evaluator = make(map[int]*licensor.Evaluator)
1919
nextID int = 1
2020
)
2121

0 commit comments

Comments
 (0)