Skip to content

Commit

Permalink
Merge pull request #2600 from rchikatw/quotachanges
Browse files Browse the repository at this point in the history
Changes to the onboarding token api to include quota in the body
  • Loading branch information
openshift-merge-bot[bot] authored Jul 11, 2024
2 parents 2e3e6f9 + 0d14eac commit 2939ab0
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 9 deletions.
2 changes: 1 addition & 1 deletion controllers/storagecluster/storageclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (s *storageClient) ensureCreated(r *StorageClusterReconciler, storagecluste
storageClient.Name = storagecluster.Name
_, err := controllerutil.CreateOrUpdate(r.ctx, r.Client, storageClient, func() error {
if storageClient.Status.ConsumerID == "" {
token, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath)
token, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath, nil)
if err != nil {
return fmt.Errorf("unable to generate onboarding token: %v", err)
}
Expand Down
11 changes: 8 additions & 3 deletions controllers/util/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@ import (

// GenerateOnboardingToken generates a token valid for a duration of "tokenLifetimeInHours".
// The token content is predefined and signed by the private key which'll be read from supplied "privateKeyPath".
func GenerateOnboardingToken(tokenLifetimeInHours int, privateKeyPath string) (string, error) {
// The storageQuotaInGiB is optional, and it is used to limit the storage of PVC in the application cluster.
func GenerateOnboardingToken(tokenLifetimeInHours int, privateKeyPath string, storageQuotaInGiB *uint) (string, error) {
tokenExpirationDate := time.Now().
Add(time.Duration(tokenLifetimeInHours) * time.Hour).
Unix()

payload, err := json.Marshal(services.OnboardingTicket{
ticket := services.OnboardingTicket{
ID: uuid.New().String(),
ExpirationDate: tokenExpirationDate,
})
}
if storageQuotaInGiB != nil {
ticket.StorageQuotaInGiB = *storageQuotaInGiB
}
payload, err := json.Marshal(ticket)
if err != nil {
return "", fmt.Errorf("failed to marshal the payload: %v", err)
}
Expand Down
5 changes: 3 additions & 2 deletions services/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package services

type OnboardingTicket struct {
ID string `json:"id"`
ExpirationDate int64 `json:"expirationDate,string"`
ID string `json:"id"`
ExpirationDate int64 `json:"expirationDate,string"`
StorageQuotaInGiB uint `json:"storageQuotaInGiB,omitempty"`
}
39 changes: 36 additions & 3 deletions services/ux-backend/handlers/onboardingtokens/handler.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,62 @@
package onboardingtokens

import (
"encoding/json"
"fmt"
"net/http"

"github.com/red-hat-storage/ocs-operator/v4/controllers/util"
"github.com/red-hat-storage/ocs-operator/v4/services/ux-backend/handlers"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
)

const (
onboardingPrivateKeyFilePath = "/etc/private-key/key"
)

var unitToGib = map[string]uint{
"Gi": 1,
"Ti": 1024,
"Pi": 1024 * 1024,
}

func HandleMessage(w http.ResponseWriter, r *http.Request, tokenLifetimeInHours int) {
switch r.Method {
case "POST":
handlePost(w, tokenLifetimeInHours)
handlePost(w, r, tokenLifetimeInHours)
default:
handleUnsupportedMethod(w, r)
}
}

func handlePost(w http.ResponseWriter, tokenLifetimeInHours int) {
if onboardingToken, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath); err != nil {
func handlePost(w http.ResponseWriter, r *http.Request, tokenLifetimeInHours int) {
var storageQuotaInGiB *uint
// When ContentLength is 0 that means request body is empty and
// storage quota is unlimited
var err error
if r.ContentLength != 0 {
var quota = struct {
Value uint `json:"value"`
Unit string `json:"unit"`
}{}
if err = json.NewDecoder(r.Body).Decode(&quota); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

if quota.Value == 0 {
http.Error(w, fmt.Sprintf("invalid value sent in request body, value should be greater than 0: %v", quota.Value), http.StatusBadRequest)
return
}
unitAsGiB, ok := unitToGib[quota.Unit]
if !ok {
http.Error(w, fmt.Sprintf("invalid Unit type sent in request body, Valid types are [Gi,Ti,Pi]: %v", quota.Unit), http.StatusBadRequest)
return
}
storageQuotaInGiB = ptr.To(unitAsGiB * quota.Value)
}
if onboardingToken, err := util.GenerateOnboardingToken(tokenLifetimeInHours, onboardingPrivateKeyFilePath, storageQuotaInGiB); err != nil {
klog.Errorf("failed to get onboardig token: %v", err)
w.WriteHeader(http.StatusInternalServerError)
w.Header().Set("Content-Type", handlers.ContentTypeTextPlain)
Expand Down

0 comments on commit 2939ab0

Please sign in to comment.