Skip to content

FFM-11164 Re-generate Client and Metrics API code, plus fixes #148

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 14 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .harness/ffgolangserversdk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pipeline:
identifier: Build_and_Test
spec:
connectorRef: DockerHub
image: golang:1.19.9
image: golang:1.20.0
shell: Sh
command: |-
go install github.com/jstemmer/go-junit-report@latest
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ $(GOPATH)/bin/gosec:

$(GOPATH)/bin/oapi-codegen:
@echo "🔘 Installing oapicodegen ... (`date '+%H:%M:%S'`)"
@go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.11.0
@go install github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen@v2.1.0

PHONY+= tools
tools: $(GOPATH)/bin/golangci-lint $(GOPATH)/bin/golint $(GOPATH)/bin/gosec $(GOPATH)/bin/goimports $(GOPATH)/bin/oapi-codegen
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ For a sample FF Golang SDK project, see our [test Golang project](examples/getti
![FeatureFlags](./docs/images/ff-gui.png)

## Requirements
[Golang 1.6](https://go.dev/doc/install) or newer (go version)<br>

- Starting with SDK version v0.1.21, Golang version 1.20 or later is required.
- Earlier versions of the SDK require Golang versions newer than 1.6 but older than 1.19.
- For installation details, please refer to [Golang's official installation guide](https://go.dev/doc/install).
## Quickstart
To follow along with our test code sample, make sure you’ve:

Expand Down
2 changes: 1 addition & 1 deletion analyticsservice/analytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func (as *AnalyticsService) sendDataAndResetCache(ctx context.Context) {
}
as.logger.Debug(string(jsonData))

resp, err := mClient.PostMetricsWithResponse(ctx, metricsclient.EnvironmentPathParam(as.environmentID), analyticsPayload)
resp, err := mClient.PostMetricsWithResponse(ctx, metricsclient.EnvironmentPathParam(as.environmentID), nil, analyticsPayload)
if err != nil {
as.logger.Warn(err)
return
Expand Down
84 changes: 51 additions & 33 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"github.com/harness/ff-golang-server-sdk/analyticsservice"
"github.com/harness/ff-golang-server-sdk/metricsclient"

"github.com/deepmap/oapi-codegen/pkg/securityprovider"
"github.com/deepmap/oapi-codegen/v2/pkg/securityprovider"
"github.com/golang-jwt/jwt"
"github.com/harness/ff-golang-server-sdk/rest"
"github.com/harness/ff-golang-server-sdk/stream"
Expand Down Expand Up @@ -333,30 +333,9 @@ func (c *CfClient) authenticate(ctx context.Context) error {
return err
}

responseError := findErrorInResponse(response)

// Indicate that we should retry
if responseError != nil && responseError.Code == "500" {
return RetryableAuthError{
StatusCode: responseError.Code,
Message: responseError.Message,
}
}

// Indicate that we shouldn't retry on non-500 errors
if responseError != nil {
return NonRetryableAuthError{
StatusCode: responseError.Code,
Message: responseError.Message,
}
}

// Defensive check to handle the case that all responses are nil
if response.JSON200 == nil {
return RetryableAuthError{
StatusCode: "No error status code returned from server",
Message: "No error message returned from server ",
}
// Use processAuthResponse to handle any errors based on the HTTP response
if processedError := processAuthResponse(response); processedError != nil {
return processedError
}

c.token = response.JSON200.AuthToken
Expand Down Expand Up @@ -554,7 +533,7 @@ func (c *CfClient) retrieveFlags(ctx context.Context) error {
c.mux.RLock()
defer c.mux.RUnlock()
c.config.Logger.Info("Retrieving flags started")
flags, err := c.api.GetFeatureConfigWithResponse(ctx, c.environmentID)
flags, err := c.api.GetFeatureConfigWithResponse(ctx, c.environmentID, nil)
if err != nil {
// log
return err
Expand All @@ -579,7 +558,7 @@ func (c *CfClient) retrieveSegments(ctx context.Context) error {
c.mux.RLock()
defer c.mux.RUnlock()
c.config.Logger.Info("Retrieving segments started")
segments, err := c.api.GetAllSegmentsWithResponse(ctx, c.environmentID)
segments, err := c.api.GetAllSegmentsWithResponse(ctx, c.environmentID, nil)
if err != nil {
// log
return err
Expand Down Expand Up @@ -769,13 +748,52 @@ func getLogger(options ...ConfigOption) logger.Logger {
return dummyConfig.Logger
}

// findErrorInResponse parses an auth response and returns the response error if it exists
func findErrorInResponse(resp *rest.AuthenticateResponse) *rest.Error {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The types have changed here, presumably because of the v2 tool

responseErrors := []*rest.Error{resp.JSON401, resp.JSON403, resp.JSON404, resp.JSON500}
for _, responseError := range responseErrors {
if responseError != nil {
return responseError
// processAuthResponse checks the authentication response for errors and categorizes them as retryable or non-retryable.
func processAuthResponse(response *rest.AuthenticateResponse) error {
if response == nil {
return RetryableAuthError{
StatusCode: "No error status code returned from server",
Message: "No error message returned from server ",
}
}

if response.JSON200 != nil {
return nil
}

// Handle retryable error
if response.JSON500 != nil {
return RetryableAuthError{
StatusCode: response.JSON500.Code,
Message: response.JSON500.Message,
}
}

// Handle non-retryable errors.
var nonRetryableError *rest.Error
switch {
case response.JSON401 != nil:
nonRetryableError = &rest.Error{Code: response.JSON401.Code, Message: response.JSON401.Message}
case response.JSON403 != nil:
nonRetryableError = &rest.Error{Code: response.JSON403.Code, Message: response.JSON403.Message}
case response.JSON404 != nil:
nonRetryableError = &rest.Error{Code: response.JSON404.Code, Message: response.JSON404.Message}
}

if nonRetryableError != nil {
return NonRetryableAuthError{
StatusCode: nonRetryableError.Code,
Message: nonRetryableError.Message,
}
}

// Defensive check to handle the case that all responses are nil
if response.JSON200 == nil {
return RetryableAuthError{
StatusCode: "No error status code returned from server",
Message: "No error message returned from server ",
}
}

return nil
}
4 changes: 2 additions & 2 deletions evaluation/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ func (e Evaluator) evaluateVariationMap(variationsMap []rest.VariationMap, targe
for _, variationMap := range variationsMap {
if variationMap.Targets != nil {
for _, t := range *variationMap.Targets {
if *t.Identifier != "" && *t.Identifier == target.Identifier {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again types have changed. Now a string instead of *String

e.logger.Debugf("Specific targeting matched in Variation Map: Variation Map (%v) Target(%v), Variation returned (%s)", *t.Identifier, target, variationMap.Variation)
if t.Identifier != "" && t.Identifier == target.Identifier {
e.logger.Debugf("Specific targeting matched in Variation Map: Variation Map (%v) Target(%v), Variation returned (%s)", t.Identifier, target, variationMap.Variation)
return variationMap.Variation
}
}
Expand Down
4 changes: 2 additions & 2 deletions evaluation/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ func TestEvaluator_evaluateVariationMap(t *testing.T) {
Variation: identifierTrue,
Targets: &[]rest.TargetMap{
{
Identifier: &targetIdentifier,
Identifier: targetIdentifier,
},
},
},
Expand Down Expand Up @@ -1074,7 +1074,7 @@ func TestEvaluator_evaluateFlag(t *testing.T) {
Variation: identifierTrue,
Targets: &[]rest.TargetMap{
{
Identifier: &targetIdentifier,
Identifier: targetIdentifier,
},
},
},
Expand Down
23 changes: 13 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,42 +1,45 @@
module github.com/harness/ff-golang-server-sdk

go 1.18
go 1.20

require (
github.com/cenkalti/backoff/v4 v4.2.1
github.com/deepmap/oapi-codegen v1.11.0
github.com/getkin/kin-openapi v0.94.0
github.com/deepmap/oapi-codegen/v2 v2.1.0
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v2 has pretty significant benefits, mainly around reduced dependency bundle. See https://www.jvt.me/posts/2023/10/23/oapi-codegen-v2-decrease/

github.com/getkin/kin-openapi v0.124.0
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.3.0
github.com/google/uuid v1.5.0
github.com/harness-community/sse/v3 v3.1.0
github.com/hashicorp/go-retryablehttp v0.7.4
github.com/hashicorp/golang-lru v0.5.4
github.com/jarcoal/httpmock v1.0.8
github.com/json-iterator/go v1.1.12
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.3.3
github.com/oapi-codegen/runtime v1.1.1
github.com/spaolacci/murmur3 v1.1.0
github.com/stretchr/testify v1.7.1
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.16.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
)

require (
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/go-openapi/jsonpointer v0.20.2 // indirect
github.com/go-openapi/swag v0.22.8 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/invopop/yaml v0.2.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/net v0.19.0 // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading
Loading