-
Notifications
You must be signed in to change notification settings - Fork 0
Ability to apply licence #63
Changes from 12 commits
764119a
94e6c54
0178abd
7cabfd9
2d021e7
ee6277d
9aaa36a
9e530cf
3b73ddd
32d1fc3
a005858
9b3156c
29242ea
9663577
0fc1273
f803bc6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import ( | |
| "encoding/json" | ||
| "fmt" | ||
| "math" | ||
| "net/http" | ||
| "sync" | ||
| "time" | ||
|
|
||
|
|
@@ -53,7 +54,7 @@ func (e *PortalEndpoint) RegisterDevice(pubKeyPem []byte) error { | |
| headers := utils.NewHeaders(utils.ContentType) | ||
| headers["Authorization"] = fmt.Sprintf("Bearer %s", token.AccessToken) | ||
|
|
||
| _, err := utils.PostHttpContent(e.url+"/setup/register-cluster", req, headers) | ||
| _, _, err := utils.PostHttpContent(e.url+"/setup/register-cluster", req, headers) | ||
| if err != nil { | ||
| return errors.Wrap(err, "unable to send register request") | ||
| } | ||
|
|
@@ -118,26 +119,45 @@ func (e *PortalEndpoint) GetConfig() (*v1alpha1.IOTCoreConfig, error) { | |
| headers := utils.NewHeaders(utils.ContentType) | ||
| headers["Authorization"] = fmt.Sprintf("Bearer %s", e.token.AccessToken) | ||
|
|
||
| resp, err := utils.GetHttpContent(e.url+"/setup/configuration", headers) | ||
| resp, _, err := utils.GetHttpContent(e.url+"/setup/configuration", headers) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| iotConfig := &ConfigurationResponse{} | ||
| err = json.Unmarshal(resp, iotConfig) | ||
| configResp := &ConfigurationResponse{} | ||
| err = json.Unmarshal(resp, configResp) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| var pubPEM []byte | ||
|
|
||
| resp, code, err := utils.GetHttpContent(e.url+"/setup/signature-key?clusterId="+e.clusterID, headers) | ||
| if err != nil && code != http.StatusNotFound { | ||
| return nil, err | ||
| } else if code != http.StatusNotFound { | ||
| signResp := &SignatureResponse{} | ||
| err = json.Unmarshal(resp, signResp) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| pubPEM, err = base64.StdEncoding.DecodeString(signResp.PublicSignKey) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| } | ||
|
|
||
| iotConfig := v1alpha1.IOTCoreConfig{ | ||
| Project: configResp.ProjectId, | ||
| Registry: configResp.Registry, | ||
| Region: configResp.Region, | ||
| ServerURL: configResp.MttqURL, | ||
| SignatureKey: string(pubPEM), | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ugh, I am not sure about storing raw bytes in a string variable now that I think about it. I dooooont think it will cause bugs, but it looks strange. Not a blocker I think.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At some point, we have to convert it to string. So I did the conversion as early as possible (once). But lets talk about it. |
||
| } | ||
|
|
||
| e.logger.V(2).Info("Retrieved iotconfig", "iotconfig", iotConfig) | ||
|
|
||
| return &v1alpha1.IOTCoreConfig{ | ||
| Project: iotConfig.ProjectId, | ||
| Registry: iotConfig.Registry, | ||
| Region: iotConfig.Region, | ||
| ServerURL: iotConfig.MttqURL, | ||
| }, | ||
| nil | ||
| return &iotConfig, nil | ||
| } | ||
|
|
||
| // Stop close endpoint and resources. | ||
|
|
@@ -156,7 +176,7 @@ func (e *PortalEndpoint) refreshToken() (int, error) { | |
| Secret: e.password, | ||
| } | ||
|
|
||
| resp, err := utils.PostHttpContent(e.url+"/auth/token", req, utils.NewHeaders(utils.ContentType)) | ||
| resp, _, err := utils.PostHttpContent(e.url+"/auth/token", req, utils.NewHeaders(utils.ContentType)) | ||
| if err != nil { | ||
| return -1, errors.Wrap(err, "unable to send token request") | ||
| } | ||
|
|
@@ -178,8 +198,6 @@ func (e *PortalEndpoint) refreshToken() (int, error) { | |
|
|
||
| // NewPortalEndpoint contructs a new Portal endpoint. | ||
| func NewPortalEndpoint(clusterID, url string, clientID string, password string, logger logr.Logger) *PortalEndpoint { | ||
| logger = logger.WithName("portal_endpoint") | ||
|
|
||
| return &PortalEndpoint{ | ||
| clusterID: clusterID, | ||
| url: url, | ||
|
|
@@ -188,7 +206,7 @@ func NewPortalEndpoint(clusterID, url string, clientID string, password string, | |
| tokenLock: make(chan bool, 1), | ||
| refreshTokenDelay: refreshTokenDefaultDelay, | ||
| refreshStopchan: make(chan bool), | ||
| logger: logger, | ||
| logger: logger.WithName("portal_endpoint"), | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -225,3 +243,8 @@ type ConfigurationResponse struct { | |
| Registry string `json:"registry"` | ||
| Region string `json:"region"` | ||
| } | ||
|
|
||
| // SignatureResponse response of GET signture endpoint | ||
| type SignatureResponse struct { | ||
| PublicSignKey string `json:"publicSignKey"` | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,12 @@ | ||
| package endpoints | ||
|
|
||
| import ( | ||
| "context" | ||
| "time" | ||
|
|
||
| "github.com/go-logr/logr" | ||
| "github.com/pkg/errors" | ||
| stosapiv2 "github.com/storageos/go-api/v2" | ||
| "github.com/storageos/portal-manager/pkg/storageos" | ||
| ) | ||
|
|
||
|
|
@@ -13,40 +17,61 @@ type StorageOSEndpoint struct { | |
| username string | ||
| password string | ||
| logger logr.Logger | ||
| client *storageos.Client | ||
| } | ||
|
|
||
| // GetClusterID returns the cluster ID. | ||
| func (e *StorageOSEndpoint) GetClusterID() string { | ||
| return e.clusterID | ||
| } | ||
|
|
||
| // GetLicence returns the current licence. | ||
| func (e *StorageOSEndpoint) GetLicence() (*stosapiv2.Licence, error) { | ||
| return e.client.GetLicence() | ||
| } | ||
|
|
||
| // UpdateLicence applies given licence. | ||
| func (e *StorageOSEndpoint) UpdateLicence(key string) (*stosapiv2.Licence, error) { | ||
| return e.client.UpdateLicence(key) | ||
| } | ||
|
|
||
| // Start start endpoint service and token refresh. | ||
| func (e *StorageOSEndpoint) Start() error { | ||
| e.logger.V(3).Info("Start storageos endpoint...") | ||
|
|
||
| stosClient, err := storageos.NewClient(e.username, e.password, e.endpoint, e.logger) | ||
| var err error | ||
| e.client, err = storageos.NewClient(e.username, e.password, e.endpoint, e.logger) | ||
| if err != nil { | ||
| return errors.Wrap(err, "unable to init StorageOS client") | ||
| } | ||
|
|
||
| e.clusterID, err = stosClient.GetCluster() | ||
| e.clusterID, err = e.client.GetCluster() | ||
| if err != nil { | ||
| return errors.Wrap(err, "unable to retrieve cluster ID") | ||
| } | ||
|
|
||
| e.logger.V(3).Info("Storageos endpoint started", "ClusterID", e.clusterID) | ||
|
|
||
| // TODO would be nice to properly stop refresh. | ||
| go func() { | ||
| for { | ||
| if err := e.client.Refresh(context.Background(), time.Minute); err != nil { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think if you
Not sure if this has impact on other places, but IMVHO it's a good pattern, if a bit annyoing to code in the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At this point we have an active connection because the connection has been established to fetch cluster id, so here what we want is to refresh the token until program ends in every minute. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right. But inside the Refresh method you have already an infinite loop refreshing the token. so I assumed you've added an infinite loop here because that inner infinite loop might return an error and you want to retry?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. Our future plan is to watch storageos API credentials secret, and if changes restart the pod. So here until credentials are the same we would like to push refresh until the end. |
||
| e.logger.Error(err, "Failed to start refresh") | ||
| } | ||
|
|
||
| time.Sleep(time.Second) | ||
| } | ||
| }() | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| // NewStorageOSEndpoint contructs a new StorageOS endpoint. | ||
| func NewStorageOSEndpoint(username, password, endpoint string, logger logr.Logger) *StorageOSEndpoint { | ||
| logger = logger.WithName("storageos_endpoint") | ||
|
|
||
| return &StorageOSEndpoint{ | ||
| endpoint: endpoint, | ||
| username: username, | ||
| password: password, | ||
| logger: logger, | ||
| logger: logger.WithName("storageos_endpoint"), | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can there be any other error code?
Now if err == nil and code == 404 then we are on the happy path? Is that OK also?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The endpoint does not necessarily exist, so we have to set
pubPEMonly if it exists. On the other handerrshould benilonly if the status is2XX, so I think the code is correct.