Skip to content
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
27 changes: 27 additions & 0 deletions packages/orchestrator/pkg/factories/featureflags_context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//go:build linux

package factories

import (
"context"

"github.com/launchdarkly/go-sdk-common/v3/ldcontext"

"github.com/e2b-dev/infra/packages/shared/pkg/featureflags"
)

const (
orchestratorKind ldcontext.Kind = "orchestrator"
orchestratorCommitAttribute string = "commit"
)

func orchestratorContextProvider(nodeID, commit string) featureflags.ContextProvider {
versionContext := ldcontext.NewBuilder(nodeID).
Kind(orchestratorKind).
SetString(orchestratorCommitAttribute, commit).
Build()

return func(context.Context) ldcontext.Context {
return versionContext
}
}
1 change: 1 addition & 0 deletions packages/orchestrator/pkg/factories/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ func run(config cfg.Config, opts Options) (success bool) {
closers = append(closers, closer{"feature flags", featureFlags.Close})

featureFlags.SetDeploymentName(config.DomainName)
featureFlags.RegisterContextProvider(orchestratorContextProvider(nodeID, commitSHA))

// gcp concurrent upload limiter
limiter, err := limit.New(ctx, featureFlags)
Expand Down
1 change: 0 additions & 1 deletion packages/orchestrator/pkg/server/sandboxes.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ func (s *Server) Create(ctx context.Context, req *orchestrator.SandboxCreateRequ
ldcontext.NewBuilder(req.GetSandbox().GetTeamId()).
Kind(featureflags.TeamKind).
Build(),
featureflags.VersionContext(s.info.ClientId, s.info.SourceCommit),
)

// BYOP egress proxy kill-switch; mirrors the API gate for direct gRPC
Expand Down
33 changes: 24 additions & 9 deletions packages/shared/pkg/featureflags/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@ var launchDarklyApiKey = os.Getenv("LAUNCH_DARKLY_API_KEY")
const waitForInit = 5 * time.Second

type Client struct {
ld *ldclient.LDClient
deploymentName string
serviceName string
ld *ldclient.LDClient
deploymentName string
serviceName string
contextProviders []ContextProvider
}

// ContextProvider supplies an additional LD context on every flag evaluation.
// Services register providers to inject specific contexts without leaking that
// specificity into the shared client.
type ContextProvider func(ctx context.Context) ldcontext.Context

func NewClientWithDatasource(source *ldtestdata.TestDataSource) (*Client, error) {
ldClient, err := ldclient.MakeCustomClient(
"",
Expand Down Expand Up @@ -98,12 +104,18 @@ func (c *Client) SetServiceName(serviceName string) {
c.serviceName = serviceName
}

// RegisterContextProvider registers a provider whose contexts are appended to
// every flag evaluation.
func (c *Client) RegisterContextProvider(provider ContextProvider) {
c.contextProviders = append(c.contextProviders, provider)
}

func (c *Client) BoolFlag(ctx context.Context, flag BoolFlag, contexts ...ldcontext.Context) bool {
return getFlag(ctx, c.ld, c.ld.BoolVariationCtx, flag, c.allContexts(contexts))
return getFlag(ctx, c.ld, c.ld.BoolVariationCtx, flag, c.allContexts(ctx, contexts))
}

func (c *Client) JSONFlag(ctx context.Context, flag JSONFlag, contexts ...ldcontext.Context) ldvalue.Value {
return getFlag(ctx, c.ld, c.ld.JSONVariationCtx, flag, c.allContexts(contexts))
return getFlag(ctx, c.ld, c.ld.JSONVariationCtx, flag, c.allContexts(ctx, contexts))
}

func (c *Client) WatchJSONFlag(ctx context.Context, flag JSONFlag, contexts ...ldcontext.Context) (<-chan interfaces.FlagValueChangeEvent, func()) {
Expand All @@ -116,7 +128,7 @@ func (c *Client) WatchJSONFlag(ctx context.Context, flag JSONFlag, contexts ...l

listener := c.ld.GetFlagTracker().AddFlagValueChangeListener(
flag.Key(),
mergeContexts(ctx, c.allContexts(contexts)),
mergeContexts(ctx, c.allContexts(ctx, contexts)),
flag.Fallback(),
)

Expand All @@ -126,11 +138,11 @@ func (c *Client) WatchJSONFlag(ctx context.Context, flag JSONFlag, contexts ...l
}

func (c *Client) IntFlag(ctx context.Context, flag IntFlag, contexts ...ldcontext.Context) int {
return getFlag(ctx, c.ld, c.ld.IntVariationCtx, flag, c.allContexts(contexts))
return getFlag(ctx, c.ld, c.ld.IntVariationCtx, flag, c.allContexts(ctx, contexts))
}

func (c *Client) StringFlag(ctx context.Context, flag StringFlag, contexts ...ldcontext.Context) string {
return getFlag(ctx, c.ld, c.ld.StringVariationCtx, flag, c.allContexts(contexts))
return getFlag(ctx, c.ld, c.ld.StringVariationCtx, flag, c.allContexts(ctx, contexts))
}

type typedFlag[T any] interface {
Expand Down Expand Up @@ -174,13 +186,16 @@ func (c *Client) Close(ctx context.Context) error {
return nil
}

func (c *Client) allContexts(contexts []ldcontext.Context) []ldcontext.Context {
func (c *Client) allContexts(ctx context.Context, contexts []ldcontext.Context) []ldcontext.Context {
if c.deploymentName != "" {
contexts = append(contexts, deploymentContext(c.deploymentName))
}
if c.serviceName != "" {
contexts = append(contexts, ServiceContext(c.serviceName))
}
for _, provider := range c.contextProviders {
contexts = append(contexts, provider(ctx))
}

return contexts
}
Comment thread
arkamar marked this conversation as resolved.
22 changes: 21 additions & 1 deletion packages/shared/pkg/featureflags/client_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package featureflags

import (
"context"
"testing"

"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
Expand Down Expand Up @@ -43,7 +44,7 @@ func TestAllContextsIncludesServiceAndDeployment(t *testing.T) {
client.SetDeploymentName("dev")
client.SetServiceName("orchestration-api")

merged := mergeContexts(t.Context(), client.allContexts(nil))
merged := mergeContexts(t.Context(), client.allContexts(t.Context(), nil))
contexts := merged.GetAllIndividualContexts(nil)

seen := map[ldcontext.Kind]string{}
Expand All @@ -54,3 +55,22 @@ func TestAllContextsIncludesServiceAndDeployment(t *testing.T) {
require.Equal(t, "dev", seen[deploymentKind])
require.Equal(t, "orchestration-api", seen[ServiceKind])
}

func TestAllContextsIncludesRegisteredProviders(t *testing.T) {
t.Parallel()

client := &Client{}
client.RegisterContextProvider(func(context.Context) ldcontext.Context {
return ldcontext.NewWithKind("node", "node-1")
})

merged := mergeContexts(t.Context(), client.allContexts(t.Context(), nil))
contexts := merged.GetAllIndividualContexts(nil)

seen := map[ldcontext.Kind]string{}
for _, item := range contexts {
seen[item.Kind()] = item.Key()
}

require.Equal(t, "node-1", seen["node"])
}
7 changes: 0 additions & 7 deletions packages/shared/pkg/featureflags/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,3 @@ func CompressFileTypeContext(fileType string) ldcontext.Context {
func CompressUseCaseContext(useCase string) ldcontext.Context {
return ldcontext.NewWithKind(CompressUseCaseKind, useCase)
}

func VersionContext(orchestratorID, commit string) ldcontext.Context {
return ldcontext.NewBuilder(orchestratorID).
Kind(OrchestratorKind).
SetString(OrchestratorCommitAttribute, commit).
Build()
}
3 changes: 0 additions & 3 deletions packages/shared/pkg/featureflags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ const (
VolumeKind ldcontext.Kind = "volume"
CompressFileTypeKind ldcontext.Kind = "compress-file-type"
CompressUseCaseKind ldcontext.Kind = "compress-use-case"

OrchestratorKind ldcontext.Kind = "orchestrator"
OrchestratorCommitAttribute string = "commit"
)

// All flags must be defined here: https://app.launchdarkly.com/projects/default/flags/
Expand Down
Loading