Skip to content

[usage] Configure Stripe Price IDs through installer #14124

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 1 commit into from
Oct 25, 2022
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
6 changes: 6 additions & 0 deletions .werft/jobs/build/installer/installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,12 @@ EOF`);
exec(`yq w -i ${this.options.installerConfigPath} experimental.webapp.usage.defaultSpendingLimit.minForUsersOnStripe 1000`, { slice: slice })
exec(`yq w -i ${this.options.installerConfigPath} experimental.webapp.usage.creditsPerMinuteByWorkspaceClass['default'] 0.1666666667`, { slice: slice })
exec(`yq w -i ${this.options.installerConfigPath} experimental.webapp.usage.creditsPerMinuteByWorkspaceClass['gitpodio-internal-xl'] 0.3333333333`, { slice: slice })

// Configure Price IDs
exec(`yq w -i ${this.options.installerConfigPath} experimental.webapp.stripe.individualUsagePriceIds['EUR'] price_1LmYVxGadRXm50o3AiLq0Qmo`, { slice: slice })
Copy link
Contributor

Choose a reason for hiding this comment

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

I see empty strings in the installer config when I ran kubectl get configmap usage -o yaml, but I expected these ones for preview?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, it's gonna be because changes to .werft don't get triggered by PRs. I need to manually trigger.

Copy link
Member Author

@easyCZ easyCZ Oct 25, 2022

Choose a reason for hiding this comment

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

I've triggered the build. If you look at the preview env now, it does contain the config.

Sorry, this one always catches me out and I forgot to do this for the PR when I created it, I had it on a different branch before.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, looks good!

exec(`yq w -i ${this.options.installerConfigPath} experimental.webapp.stripe.individualUsagePriceIds['USD'] price_1LmYWRGadRXm50o3Ym8PLqnG`, { slice: slice })
exec(`yq w -i ${this.options.installerConfigPath} experimental.webapp.stripe.teamUsagePriceIds['EUR'] price_1LiId7GadRXm50o3OayAS2y4`, { slice: slice })
exec(`yq w -i ${this.options.installerConfigPath} experimental.webapp.stripe.teamUsagePriceIds['USD'] price_1LiIdbGadRXm50o3ylg5S44r`, { slice: slice })
}

private configureConfigCat(slice: string) {
Expand Down
13 changes: 13 additions & 0 deletions components/usage/pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ type Config struct {
Server *baseserver.Configuration `json:"server,omitempty"`

DefaultSpendingLimit db.DefaultSpendingLimit `json:"defaultSpendingLimit"`

// StripePrices configure which Stripe Price IDs should be used
StripePrices StripePrices `json:"stripePrices"`
}

type PriceConfig struct {
EUR string `json:"eur"`
USD string `json:"usd"`
}

type StripePrices struct {
IndividualUsagePriceIDs PriceConfig `json:"individualUsagePriceIds"`
TeamUsagePriceIDs PriceConfig `json:"teamUsagePriceIds"`
}

func Start(cfg Config, version string) error {
Expand Down
29 changes: 22 additions & 7 deletions install/installer/pkg/components/usage/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,31 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) {
MinForUsersOnStripe: 0,
},
}
expConfig := getExperimentalConfig(ctx)

if expConfig != nil {
if expConfig.Schedule != "" {
cfg.ControllerSchedule = expConfig.Schedule
expWebAppConfig := getExperimentalWebAppConfig(ctx)
if expWebAppConfig != nil && expWebAppConfig.Stripe != nil {
cfg.StripePrices = server.StripePrices{
IndividualUsagePriceIDs: server.PriceConfig{
EUR: expWebAppConfig.Stripe.IndividualUsagePriceIDs.EUR,
USD: expWebAppConfig.Stripe.IndividualUsagePriceIDs.USD,
},
TeamUsagePriceIDs: server.PriceConfig{
EUR: expWebAppConfig.Stripe.TeamUsagePriceIDs.EUR,
USD: expWebAppConfig.Stripe.TeamUsagePriceIDs.USD,
},
}
}

expUsageConfig := getExperimentalUsageConfig(ctx)

if expUsageConfig != nil {
if expUsageConfig.Schedule != "" {
cfg.ControllerSchedule = expUsageConfig.Schedule
}
if expConfig.DefaultSpendingLimit != nil {
cfg.DefaultSpendingLimit = *expConfig.DefaultSpendingLimit
if expUsageConfig.DefaultSpendingLimit != nil {
cfg.DefaultSpendingLimit = *expUsageConfig.DefaultSpendingLimit
}
cfg.CreditsPerMinuteByWorkspaceClass = expConfig.CreditsPerMinuteByWorkspaceClass
cfg.CreditsPerMinuteByWorkspaceClass = expUsageConfig.CreditsPerMinuteByWorkspaceClass
}

_ = ctx.WithExperimental(func(ucfg *experimental.Config) error {
Expand Down
10 changes: 10 additions & 0 deletions install/installer/pkg/components/usage/configmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ func TestConfigMap_ContainsSchedule(t *testing.T) {
"forTeams": 1000000000,
"minForUsersOnStripe": 0
},
"stripePrices": {
"individualUsagePriceIds": {
"eur": "",
"usd": ""
},
"teamUsagePriceIds": {
"eur": "",
"usd": ""
}
},
"server": {
"services": {
"grpc": {
Expand Down
18 changes: 14 additions & 4 deletions install/installer/pkg/components/usage/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

func Objects(ctx *common.RenderContext) ([]runtime.Object, error) {
cfg := getExperimentalConfig(ctx)
cfg := getExperimentalUsageConfig(ctx)
if cfg == nil {
return nil, nil
}
Expand All @@ -27,17 +27,27 @@ func Objects(ctx *common.RenderContext) ([]runtime.Object, error) {
)(ctx)
}

func getExperimentalConfig(ctx *common.RenderContext) *experimental.UsageConfig {
func getExperimentalWebAppConfig(ctx *common.RenderContext) *experimental.WebAppConfig {
var experimentalCfg *experimental.Config

_ = ctx.WithExperimental(func(ucfg *experimental.Config) error {
experimentalCfg = ucfg
return nil
})

if experimentalCfg == nil || experimentalCfg.WebApp == nil || experimentalCfg.WebApp.Usage == nil {
if experimentalCfg == nil || experimentalCfg.WebApp == nil {
return nil
}

return experimentalCfg.WebApp.Usage
return experimentalCfg.WebApp
}

func getExperimentalUsageConfig(ctx *common.RenderContext) *experimental.UsageConfig {
experimentalWebAppCfg := getExperimentalWebAppConfig(ctx)
if experimentalWebAppCfg == nil || experimentalWebAppCfg.Usage == nil {

return nil
}

return experimentalWebAppCfg.Usage
}
11 changes: 11 additions & 0 deletions install/installer/pkg/config/v1/experimental/experimental.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,16 @@ type WorkspaceTemplates struct {
Regular *corev1.Pod `json:"regular"`
}

type StripePriceIDs struct {
EUR string `json:"eur"`
USD string `json:"usd"`
}

type StripeConfig struct {
IndividualUsagePriceIDs StripePriceIDs `json:"individualUsagePriceIds"`
TeamUsagePriceIDs StripePriceIDs `json:"teamUsagePriceIds"`
}

Comment on lines +170 to +179
Copy link
Contributor

Choose a reason for hiding this comment

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

Hey Milan, I've just joined the team so I'm still catching up on decisions around the installer 😬

How do we decide if things go to "experimental" or not? maybe @mrsimonemms could help clarifying as well?

Copy link
Contributor

Choose a reason for hiding this comment

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

@ArthurSens as a general rule, anything that's in experimental is for config that's either specific to SaaS or (in rarer cases) to support a specific paying customer. Anything in experimental should be considered liable to change without notice.

Things are only added to the main config if it's something that we are happy to publicly support (including community/open source users), we have updated the public documentation (and usually added to the KOTS config) and that we are confident we won't need to amend.

Looking at this, it looks like @easyCZ has correctly put it in experimental as this is a SaaS-specific config parameter.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks Simon. Yes, indeed this is config only specific to SaaS at this point, hence defined in the experimental section.

type WebAppConfig struct {
PublicAPI *PublicAPIConfig `json:"publicApi,omitempty"`
Server *ServerConfig `json:"server,omitempty"`
Expand All @@ -178,6 +188,7 @@ type WebAppConfig struct {
Usage *UsageConfig `json:"usage,omitempty"`
ConfigcatKey string `json:"configcatKey"`
WorkspaceClasses []WebAppWorkspaceClass `json:"workspaceClasses"`
Stripe *StripeConfig `json:"stripe,omitempty"`
}

type WorkspaceDefaults struct {
Expand Down