Skip to content

Commit

Permalink
make initial acp version check async
Browse files Browse the repository at this point in the history
  • Loading branch information
jwebster7 authored Oct 16, 2023
1 parent 1e36762 commit 33fd0cf
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 28 deletions.
9 changes: 7 additions & 2 deletions acp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (c *client) GetVersion(ctx context.Context) (*version.Version, error) {
Logc(ctx).Debug("Getting Trident-ACP version.")

if !c.acpEnabled {
Logc(ctx).Warning("ACP not enabled.")
Logc(ctx).Warning("ACP is not enabled.")
return nil, nil
}

Expand All @@ -79,10 +79,15 @@ func (c *client) GetVersion(ctx context.Context) (*version.Version, error) {
}

func (c *client) GetVersionWithBackoff(ctx context.Context) (*version.Version, error) {
Logc(ctx).Debug("Checking if Trident-ACP REST API is responsive.")
Logc(ctx).Debug("Checking if Trident-ACP REST API is available.")
var v *version.Version
var err error

if !c.acpEnabled {
Logc(ctx).Warning("ACP is not enabled.")
return nil, nil
}

getVersion := func() error {
v, err = c.restClient.GetVersion(ctx)
return err
Expand Down
12 changes: 11 additions & 1 deletion acp/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,21 @@ func TestTridentACP_GetVersionWithBackoff(t *testing.T) {

client := newClient(mockRest, true)
v, err := client.GetVersionWithBackoff(ctx)
// For now expect no error even though one occurs.
assert.Error(t, err, "expected error")
assert.Nil(t, v, "expected nil version")
})

t.Run("WithACPNotEnabled", func(t *testing.T) {
// Reset the backoff to the initial values after the test exits.
defer setupBackoff(initialInterval, maxInterval, maxElapsedTime, multiplier, randomFactor)
setupBackoff(50*time.Millisecond, 100*time.Millisecond, 250*time.Millisecond, 1.414, 1.0)

client := newClient(nil, false)
v, err := client.GetVersionWithBackoff(ctx)
assert.Nil(t, err, "unexpected error")
assert.Nil(t, v, "expected nil version")
})

t.Run("WithCorrectResponseTypeAsync", func(t *testing.T) {
// Reset the backoff to the initial values after the test exits.
defer setupBackoff(initialInterval, maxInterval, maxElapsedTime, multiplier, randomFactor)
Expand Down
6 changes: 3 additions & 3 deletions acp/rest/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ func (c *Client) Entitled(ctx context.Context, feature string) error {
}

switch res.StatusCode {
case http.StatusForbidden:
return errors.UnlicensedError("feature %s requires a valid ACP license", feature)
case http.StatusOK:
return nil
case http.StatusForbidden:
return errors.UnlicensedError("feature %s requires a valid ACP license", feature)
}

return fmt.Errorf("unexpected status code: [%s]", res.Status)
return fmt.Errorf("unexpected status code during entitlement check: [%s]", res.Status)
}

// newRequest accepts necessary fields to construct a new http request.
Expand Down
12 changes: 8 additions & 4 deletions frontend/rest/controller_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,12 @@ func GetVersion(w http.ResponseWriter, r *http.Request) {
func GetACPVersion(ctx context.Context) string {
version, err := acp.API().GetVersion(ctx)
if err != nil {
Logc(ctx).WithError(err).Error("Could not get trident-acp version.")
Logc(ctx).WithError(err).Error("Could not get Trident-ACP version.")
return ""
}

if version == nil {
Logc(ctx).WithError(err).Error("trident-acp version is empty.")
Logc(ctx).WithError(err).Error("Trident-ACP version is empty.")
return ""
}

Expand Down Expand Up @@ -616,7 +616,9 @@ func (r *UpdateVolumeResponse) logFailure(ctx context.Context) {
}).Error(r.Error)
}

func volumeLUKSPassphraseNamesUpdater(_ http.ResponseWriter, r *http.Request, response httpResponse, vars map[string]string, body []byte) int {
func volumeLUKSPassphraseNamesUpdater(
_ http.ResponseWriter, r *http.Request, response httpResponse, vars map[string]string, body []byte,
) int {
updateResponse, ok := response.(*UpdateVolumeResponse)
if !ok {
response.setError(fmt.Errorf("response object must be of type UpdateVolumeResponse"))
Expand Down Expand Up @@ -1027,7 +1029,9 @@ func (u *UpdateNodeResponse) logFailure(ctx context.Context) {
}

// nodeUpdater updates a Trident Node's persistent state asynchronously.
func nodeUpdater(_ http.ResponseWriter, r *http.Request, response httpResponse, vars map[string]string, body []byte) int {
func nodeUpdater(
_ http.ResponseWriter, r *http.Request, response httpResponse, vars map[string]string, body []byte,
) int {
updateNodeResponse, ok := response.(*UpdateNodeResponse)
if !ok {
response.setError(fmt.Errorf("response object must be of type UpdateNodeResponse"))
Expand Down
33 changes: 15 additions & 18 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,24 +348,6 @@ func main() {

orchestrator := core.NewTridentOrchestrator(storeClient)

// Set configuration values used for ACP for the lifecycle of Trident.
// This always needs to happen regardless of if ACP is enabled or not.
acp.Initialize(*acpAddress, *enableACP, config.HTTPTimeout)

// Initialize a Trident-ACP Client.
if *enableACP {
Log().Info("Created Trident-ACP REST API Client.")
// Reach out to see if the Trident-ACP API is available.
version, err := acp.API().GetVersionWithBackoff(ctx)
if err != nil {
Log().Warning("Failed to communicate with Trident-ACP REST API.")
} else {
Log().WithField("version", version.String()).Info("Discovered Trident-ACP Version.")
}
} else {
Log().Info("ACP is not enabled; premium ACP workflows will fail.")
}

// Create HTTP metrics frontend
if *enableMetrics {
if *metricsPort == "" {
Expand Down Expand Up @@ -530,6 +512,21 @@ func main() {
}
}

// Set configuration values used for ACP for the lifecycle of Trident.
// This always needs to happen regardless of if ACP is enabled or not and must happen before bootstrapping.
acp.Initialize(*acpAddress, *enableACP, config.HTTPTimeout)
Log().Info("Created Trident-ACP REST API Client.")

// Asynchronously check if the Trident-ACP API is available.
go func() {
version, err := acp.API().GetVersionWithBackoff(ctx)
if err != nil || version == nil {
Log().Warning("Failed to get version from Trident-ACP REST API; premium workflows may fail.")
} else {
Log().WithField("version", version.String()).Info("Discovered Trident-ACP Version.")
}
}()

// Bootstrap the orchestrator and start its frontends. Some frontends, notably REST and Docker, must
// start before the core so that the external interfaces are minimally responding while the core is
// still initializing. Other frontends such as legacy Kubernetes and CSI benefit from starting after
Expand Down

0 comments on commit 33fd0cf

Please sign in to comment.