Skip to content

Calculate and return days remaining in get signup response #432

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

Merged
merged 37 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2a34b8b
initial implementation
sbryzak Mar 11, 2024
47b4322
updated existing tests
sbryzak Mar 11, 2024
0f7a3ef
fixed
sbryzak Mar 11, 2024
5100873
add get/list/watch permissions for UserTiers
sbryzak Mar 11, 2024
d1eef45
review comments
sbryzak Mar 11, 2024
d2eaf1b
stashing changes
sbryzak Mar 12, 2024
d726b50
revert
sbryzak Mar 15, 2024
f74ea78
Merge remote-tracking branch 'origin/master' into SANDBOX-554
sbryzak Mar 15, 2024
fc80365
updated api
sbryzak Mar 16, 2024
2be3b46
fix lint error
sbryzak Mar 16, 2024
860faf9
return days remaining in get signup response
sbryzak May 15, 2024
307899d
Merge remote-tracking branch 'origin/master' into SANDBOX-554-reg-ser…
sbryzak May 15, 2024
abca95a
Merge remote-tracking branch 'origin/master' into SANDBOX-554-reg-ser…
sbryzak May 28, 2024
43d1dfa
linter
sbryzak May 28, 2024
a0d8e0e
added unit test
sbryzak Jun 3, 2024
8110a48
Merge remote-tracking branch 'origin/master' into SANDBOX-554-reg-ser…
sbryzak Jun 3, 2024
817e023
fixed undo text
sbryzak Jun 3, 2024
329a8b0
review comments
sbryzak Jun 4, 2024
b8ea212
minor
sbryzak Jun 4, 2024
bfb2f6e
cleanup
sbryzak Jun 4, 2024
b5500c8
Merge remote-tracking branch 'origin/master' into SANDBOX-554-reg-ser…
sbryzak Jun 15, 2024
44bb712
fix comment
sbryzak Jun 15, 2024
41085ca
coverage
sbryzak Jun 17, 2024
eeae459
lint
sbryzak Jun 17, 2024
aafc0d3
fix
sbryzak Jun 17, 2024
afa7c16
Merge remote-tracking branch 'origin/master' into SANDBOX-554-reg-ser…
sbryzak Jun 18, 2024
b3516e0
review comments
sbryzak Jun 20, 2024
9912c3d
Merge remote-tracking branch 'origin/master' into SANDBOX-554-reg-ser…
sbryzak Jun 27, 2024
3eed976
removed daysRemaining
sbryzak Jun 27, 2024
6db97b0
Merge remote-tracking branch 'origin/master' into SANDBOX-554-reg-ser…
sbryzak Jun 27, 2024
eeb80a6
minor
sbryzak Jul 1, 2024
1ecb546
Merge remote-tracking branch 'origin/master' into SANDBOX-554-reg-ser…
sbryzak Jul 1, 2024
6edebf0
refine
sbryzak Jul 2, 2024
1a0d786
parse as local
sbryzak Jul 2, 2024
0384c85
do it all in UTC
sbryzak Jul 2, 2024
d9c6673
review comments
sbryzak Jul 2, 2024
ab70570
Merge remote-tracking branch 'origin/master' into SANDBOX-554-reg-ser…
sbryzak Jul 3, 2024
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
19 changes: 19 additions & 0 deletions pkg/signup/service/signup_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package service

import (
"fmt"
"github.com/codeready-toolchain/registration-service/pkg/util"
"hash/crc32"
"math"
"regexp"
"strings"
"time"

toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
"github.com/codeready-toolchain/registration-service/pkg/application/service"
Expand Down Expand Up @@ -457,6 +460,17 @@ func (s *ServiceImpl) DoGetSignup(ctx *gin.Context, provider ResourceProvider, u
return signupResponse, nil
}

if !userSignup.Status.ScheduledDeactivationTimestamp.IsZero() {
signupResponse.EndDate = userSignup.Status.ScheduledDeactivationTimestamp.Format(time.RFC3339)
remaining := time.Until(userSignup.Status.ScheduledDeactivationTimestamp.Time)
// Round the days remaining to 2 decimal points
signupResponse.DaysRemaining = util.Ptr(math.Round(remaining.Hours()/24*100) / 100)
// If for whatever reason the days remaining is negative, set it to zero
if *signupResponse.DaysRemaining < float64(0) {
signupResponse.DaysRemaining = util.Ptr(float64(0))
}
}

// If UserSignup status is complete as active
// Retrieve MasterUserRecord resource from the host cluster and use its status
mur, err := provider.GetMasterUserRecord(userSignup.Status.CompliantUsername)
Expand All @@ -474,6 +488,11 @@ func (s *ServiceImpl) DoGetSignup(ctx *gin.Context, provider ResourceProvider, u
Message: murCondition.Message,
VerificationRequired: states.VerificationRequired(userSignup),
}

if mur.Status.ProvisionedTime != nil {
signupResponse.StartDate = mur.Status.ProvisionedTime.Format(time.RFC3339)
}

if mur.Status.UserAccounts != nil && len(mur.Status.UserAccounts) > 0 {
// Retrieve cluster-specific URLs from the status of the corresponding member cluster
status, err := provider.GetToolchainStatus()
Expand Down
34 changes: 33 additions & 1 deletion pkg/signup/service/signup_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import (
"bytes"
"errors"
"fmt"
"github.com/codeready-toolchain/registration-service/pkg/util"
"hash/crc32"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"

"github.com/codeready-toolchain/registration-service/pkg/application/service/factory"
"github.com/codeready-toolchain/registration-service/pkg/configuration"
Expand Down Expand Up @@ -1159,6 +1161,10 @@ func (s *TestSignupServiceSuite) TestGetSignupStatusOK() {
require.Equal(t, us.Name, response.Name)
require.Equal(t, "jsmith", response.Username)
require.Equal(t, "ted", response.CompliantUsername)
require.NotNil(t, response.DaysRemaining)
require.InEpsilon(t, float64(30), *response.DaysRemaining, 0.1)
require.Equal(t, mur.Status.ProvisionedTime.Format(time.RFC3339), response.StartDate)
require.Equal(t, us.Status.ScheduledDeactivationTimestamp.Format(time.RFC3339), response.EndDate)
assert.True(t, response.Status.Ready)
assert.Equal(t, "mur_ready_reason", response.Status.Reason)
assert.Equal(t, "mur_ready_message", response.Status.Message)
Expand Down Expand Up @@ -1235,13 +1241,25 @@ func (s *TestSignupServiceSuite) TestGetSignupByUsernameOK() {

us := s.newUserSignupComplete()
us.Name = service.EncodeUserIdentifier(us.Spec.IdentityClaims.PreferredUsername)
// Set the scheduled deactivation timestamp 1 day ago
us.Status.ScheduledDeactivationTimestamp = util.Ptr(v1.NewTime(time.Now().Add(-time.Hour * 24)))
err := s.FakeUserSignupClient.Tracker.Add(us)
require.NoError(s.T(), err)

mur := s.newProvisionedMUR("ted")
// Set the provisioned time 31 days in the past
provisionedTime := time.Now().Add(-time.Hour * 24 * 31).Round(time.Second)
mur.Status.ProvisionedTime = util.Ptr(v1.NewTime(provisionedTime))
err = s.FakeMasterUserRecordClient.Tracker.Add(mur)
require.NoError(s.T(), err)

svc := service.NewSignupService(
fake.MemberClusterServiceContext{
Client: s,
Svcs: s.Application,
},
)

c, _ := gin.CreateTestContext(httptest.NewRecorder())

space := s.newSpaceForMUR(mur.Name, us.Name)
Expand All @@ -1257,12 +1275,24 @@ func (s *TestSignupServiceSuite) TestGetSignupByUsernameOK() {
require.NoError(s.T(), err)

// when
response, err := s.Application.SignupService().GetSignup(c, "foo", us.Spec.IdentityClaims.PreferredUsername)
response, err := svc.GetSignup(c, "foo", us.Spec.IdentityClaims.PreferredUsername)

// then
require.NoError(s.T(), err)
require.NotNil(s.T(), response)

// Confirm the StartDate is the same as the provisionedTime
require.Equal(s.T(), provisionedTime.Format(time.RFC3339), response.StartDate)

// Confirm the end date is about 1 day ago
responseEndDate, err := time.Parse(time.RFC3339, response.EndDate)
require.NoError(s.T(), err)
expectedEndDate := time.Now().Add(-time.Hour * 24)
require.WithinDuration(s.T(), expectedEndDate, responseEndDate, time.Minute*5,
"endDate in response [%s] not in expected range [%s]", responseEndDate, expectedEndDate.Format(time.RFC3339))

// DaysRemaining should be zero
require.InDelta(s.T(), float64(0), *response.DaysRemaining, 0)
require.Equal(s.T(), us.Name, response.Name)
require.Equal(s.T(), "jsmith", response.Username)
require.Equal(s.T(), "ted", response.CompliantUsername)
Expand Down Expand Up @@ -2240,6 +2270,7 @@ func (s *TestSignupServiceSuite) newUserSignupCompleteWithReason(reason string)
},
},
Status: toolchainv1alpha1.UserSignupStatus{
ScheduledDeactivationTimestamp: util.Ptr(v1.NewTime(time.Now().Add(30 * time.Hour * 24))),
Conditions: []toolchainv1alpha1.Condition{
{
Type: toolchainv1alpha1.UserSignupComplete,
Expand Down Expand Up @@ -2313,6 +2344,7 @@ func (s *TestSignupServiceSuite) newProvisionedMUR(name string) *toolchainv1alph
UserAccounts: []toolchainv1alpha1.UserAccountEmbedded{{TargetCluster: "member-123"}},
},
Status: toolchainv1alpha1.MasterUserRecordStatus{
ProvisionedTime: util.Ptr(v1.NewTime(time.Now())),
Conditions: []toolchainv1alpha1.Condition{
{
Type: toolchainv1alpha1.MasterUserRecordReady,
Expand Down
8 changes: 8 additions & 0 deletions pkg/signup/signup.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ type Signup struct {
// Company from the Identity Provider
Company string `json:"company"`
Status Status `json:"status,omitempty"`
// StartDate is the date that the user's current subscription started, in RFC3339 format
StartDate string `json:"startDate,omitempty"`
// End Date is the date that the user's current subscription will end, in RFC3339 format
EndDate string `json:"endDate,omitempty"`
// DaysRemaining is a float pointer representing the number of days remaining in the user's subscription
// If the subscription is not currently active then this property should be nil and therefore shouldn't be returned
// in the response
DaysRemaining *float64 `json:"daysRemaining,omitempty"`
}

// Status represents UserSignup resource status
Expand Down
6 changes: 6 additions & 0 deletions pkg/util/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package util

// Ptr is a generic function that returns a pointer to whatever value is passed in
func Ptr[T any](v T) *T {
return &v
}
Loading