Skip to content

Commit

Permalink
refactor: align resource types in typespec and db (#1695)
Browse files Browse the repository at this point in the history
We have the resource type in typespec, this patch enforces that we
are actually using the same type in golang via the ManagedResource
interface.

This also ensures that we are not "forgetting" to add certian fields
supported by the model.
  • Loading branch information
turip authored Oct 17, 2024
1 parent 1b5ac66 commit 92de1c6
Show file tree
Hide file tree
Showing 48 changed files with 1,499 additions and 421 deletions.
192 changes: 99 additions & 93 deletions api/api.gen.go

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,12 @@ paths:
description: |-
The API key for the provider.
For example, the Stripe API key.
name:
type: string
description: |-
Name of the application to install.
If not set defaults to the marketplace item's description.
required:
- apiKey
/api/v1/marketplace/listings/{type}/install/oauth2:
Expand Down
7 changes: 7 additions & 0 deletions api/spec/src/app/marketplace.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ model MarketplaceApiKeyInstallRequest {
* For example, the Stripe API key.
*/
apiKey: string;

/**
* Name of the application to install.
*
* If not set defaults to the marketplace item's description.
*/
name?: string;
};
}

Expand Down
22 changes: 11 additions & 11 deletions openmeter/app/adapter/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,18 +220,18 @@ func (a adapter) UninstallApp(ctx context.Context, input appentity.UninstallAppI
func mapAppBaseFromDB(dbApp *db.App, registryItem appentity.RegistryItem) appentitybase.AppBase {
return appentitybase.AppBase{
ManagedResource: models.NewManagedResource(models.ManagedResourceInput{
ID: dbApp.ID,
Namespace: dbApp.Namespace,
CreatedAt: dbApp.CreatedAt,
UpdatedAt: dbApp.UpdatedAt,
DeletedAt: dbApp.DeletedAt,
ID: dbApp.ID,
Namespace: dbApp.Namespace,
CreatedAt: dbApp.CreatedAt,
UpdatedAt: dbApp.UpdatedAt,
DeletedAt: dbApp.DeletedAt,
Name: dbApp.Name,
Description: dbApp.Description,
}),
Type: dbApp.Type,
Name: dbApp.Name,
Description: dbApp.Description,
Status: dbApp.Status,
Listing: registryItem.Listing,
Metadata: dbApp.Metadata,
Type: dbApp.Type,
Status: dbApp.Status,
Listing: registryItem.Listing,
Metadata: dbApp.Metadata,
}
}

Expand Down
6 changes: 6 additions & 0 deletions openmeter/app/adapter/marketplace.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,17 @@ func (a adapter) InstallMarketplaceListingWithAPIKey(ctx context.Context, input
return nil, fmt.Errorf("failed to get listing for app %s: %w", input.Type, err)
}

name, ok := lo.Coalesce(input.Name, registryItem.Listing.Name)
if !ok {
return nil, fmt.Errorf("name is required, listing doesn't have a name either")
}

// Install app
app, err := registryItem.Factory.InstallAppWithAPIKey(ctx, appentity.AppFactoryInstallAppWithAPIKeyInput{
Namespace: input.Namespace,
APIKey: input.APIKey,
BaseURL: a.baseURL,
Name: name,
})
if err != nil {
return nil, fmt.Errorf("failed to install app: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion openmeter/app/entity/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type App interface {
GetID() appentitybase.AppID
GetType() appentitybase.AppType
GetName() string
GetDescription() string
GetDescription() *string
GetStatus() appentitybase.AppStatus
GetMetadata() map[string]string
GetListing() appentitybase.MarketplaceListing
Expand Down
12 changes: 5 additions & 7 deletions openmeter/app/entity/base/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,10 @@ const (
type AppBase struct {
models.ManagedResource

Type AppType `json:"type"`
Name string `json:"name"`
Description string `json:"description"`
Status AppStatus `json:"status"`
Listing MarketplaceListing `json:"listing"`
Metadata map[string]string `json:"metadata"`
Type AppType `json:"type"`
Status AppStatus `json:"status"`
Listing MarketplaceListing `json:"listing"`
Metadata map[string]string `json:"metadata"`
}

func (a AppBase) GetAppBase() AppBase {
Expand All @@ -63,7 +61,7 @@ func (a AppBase) GetName() string {
return a.Name
}

func (a AppBase) GetDescription() string {
func (a AppBase) GetDescription() *string {
return a.Description
}

Expand Down
1 change: 1 addition & 0 deletions openmeter/app/entity/marketplace.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type InstallAppWithAPIKeyInput struct {

Namespace string
APIKey string
Name string
}

func (i InstallAppWithAPIKeyInput) Validate() error {
Expand Down
9 changes: 7 additions & 2 deletions openmeter/app/entity/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ type UninstallAppInput = appentitybase.AppID

type AppFactoryInstallAppWithAPIKeyInput struct {
Namespace string
APIKey string `json:"-"`
BaseURL string `json:"-"`
APIKey string
BaseURL string
Name string
}

func (i AppFactoryInstallAppWithAPIKeyInput) Validate() error {
Expand All @@ -35,6 +36,10 @@ func (i AppFactoryInstallAppWithAPIKeyInput) Validate() error {
return errors.New("base url is required")
}

if i.Name == "" {
return errors.New("name is required")
}

return nil
}

Expand Down
8 changes: 2 additions & 6 deletions openmeter/app/httpdriver/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,7 @@ func mapAppToAPI(item appentity.App) api.App {
DeletedAt: item.GetAppBase().DeletedAt,
}

if item.GetDescription() != "" {
apiApp.Description = lo.ToPtr(item.GetDescription())
}
apiApp.Description = item.GetDescription()

if item.GetMetadata() != nil {
apiApp.Metadata = lo.ToPtr(item.GetMetadata())
Expand All @@ -188,9 +186,7 @@ func mapStripeAppToAPI(stripeApp appstripeentityapp.App) api.StripeApp {
Livemode: stripeApp.Livemode,
}

if stripeApp.GetDescription() != "" {
apiStripeApp.Description = lo.ToPtr(stripeApp.GetDescription())
}
apiStripeApp.Description = stripeApp.GetDescription()

if stripeApp.GetMetadata() != nil {
apiStripeApp.Metadata = lo.ToPtr(stripeApp.GetMetadata())
Expand Down
1 change: 1 addition & 0 deletions openmeter/app/httpdriver/marketplace.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ func (h *handler) MarketplaceAppAPIKeyInstall() MarketplaceAppAPIKeyInstallHandl
MarketplaceListingID: appentity.MarketplaceListingID{Type: appentitybase.AppType(appType)},
Namespace: namespace,
APIKey: body.ApiKey,
Name: lo.FromPtrOr(body.Name, ""),
}

return req, nil
Expand Down
2 changes: 1 addition & 1 deletion openmeter/app/stripe/adapter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (a adapter) InstallAppWithAPIKey(ctx context.Context, input appentity.AppFa
createStripeAppInput := appstripeentity.CreateAppStripeInput{
ID: &appID.ID,
Namespace: input.Namespace,
Name: "Stripe",
Name: input.Name,
Description: fmt.Sprintf("Stripe account %s", stripeAccount.StripeAccountID),
StripeAccountID: stripeAccount.StripeAccountID,
Livemode: livemode,
Expand Down
12 changes: 9 additions & 3 deletions openmeter/billing/adapter/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ func (a adapter) CreateProfile(ctx context.Context, input billing.CreateProfileI
dbProfile, err := c.BillingProfile.Create().
SetNamespace(input.Namespace).
SetDefault(input.Default).
SetName(input.Name).
SetNillableDescription(input.Description).
SetTaxProvider(input.TaxConfiguration.Type).
SetInvoicingProvider(input.InvoicingConfiguration.Type).
SetPaymentProvider(input.PaymentConfiguration.Type).
Expand Down Expand Up @@ -156,6 +158,8 @@ func (a adapter) UpdateProfile(ctx context.Context, input billing.UpdateProfileA

update := a.client().BillingProfile.UpdateOneID(targetState.ID).
Where(billingprofile.Namespace(targetState.Namespace)).
SetName(targetState.Name).
SetNillableDescription(targetState.Description).
SetTaxProvider(targetState.TaxConfiguration.Type).
SetInvoicingProvider(targetState.InvoicingConfiguration.Type).
SetPaymentProvider(targetState.PaymentConfiguration.Type).
Expand Down Expand Up @@ -199,9 +203,11 @@ func mapProfileFromDB(dbProfile *db.BillingProfile) *billing.Profile {
}

return &billing.Profile{
Namespace: dbProfile.Namespace,
ID: dbProfile.ID,
Default: dbProfile.Default,
Namespace: dbProfile.Namespace,
ID: dbProfile.ID,
Default: dbProfile.Default,
Name: dbProfile.Name,
Description: dbProfile.Description,

CreatedAt: dbProfile.CreatedAt,
UpdatedAt: dbProfile.UpdatedAt,
Expand Down
7 changes: 7 additions & 0 deletions openmeter/billing/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ type Profile struct {
ID string `json:"id"`
Namespace string `json:"namespace"`

Name string `json:"name"`
Description *string `json:"description"`

CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt *time.Time `json:"deletedAt"`
Expand All @@ -192,6 +195,10 @@ func (p Profile) Validate() error {
return errors.New("namespace is required")
}

if p.Name == "" {
return errors.New("name is required")
}

if err := p.TaxConfiguration.Validate(); err != nil {
return fmt.Errorf("invalid tax configuration: %w", err)
}
Expand Down
2 changes: 2 additions & 0 deletions openmeter/customer/adapter/customer.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func (a *adapter) CreateCustomer(ctx context.Context, input customerentity.Creat
query := a.db.Customer.Create().
SetNamespace(input.Namespace).
SetName(input.Name).
SetNillableDescription(input.Description).
SetNillablePrimaryEmail(input.PrimaryEmail).
SetNillableCurrency(input.Currency).
SetNillableTimezone(input.Timezone)
Expand Down Expand Up @@ -287,6 +288,7 @@ func (a *adapter) UpdateCustomer(ctx context.Context, input customerentity.Updat
Where(customerdb.Namespace(input.Namespace)).
SetUpdatedAt(clock.Now().UTC()).
SetName(input.Name).
SetOrClearDescription(input.Description).
SetNillablePrimaryEmail(input.PrimaryEmail).
SetNillableTimezone(input.Timezone).
SetNillableCurrency(input.Currency)
Expand Down
13 changes: 7 additions & 6 deletions openmeter/customer/adapter/entitymapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ func CustomerFromDBEntity(e db.Customer) *customerentity.Customer {

result := &customerentity.Customer{
ManagedResource: models.NewManagedResource(models.ManagedResourceInput{
ID: e.ID,
Namespace: e.Namespace,
CreatedAt: e.CreatedAt,
UpdatedAt: e.UpdatedAt,
DeletedAt: e.DeletedAt,
ID: e.ID,
Namespace: e.Namespace,
CreatedAt: e.CreatedAt,
UpdatedAt: e.UpdatedAt,
DeletedAt: e.DeletedAt,
Name: e.Name,
Description: e.Description,
}),
Name: e.Name,
UsageAttribution: customerentity.CustomerUsageAttribution{
SubjectKeys: subjectKeys,
},
Expand Down
2 changes: 1 addition & 1 deletion openmeter/customer/entity/customer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
type Customer struct {
models.ManagedResource

Name string `json:"name"`
Timezone *timezone.Timezone `json:"timezone"`
UsageAttribution CustomerUsageAttribution `json:"usageAttribution"`
PrimaryEmail *string `json:"primaryEmail"`
Expand All @@ -36,6 +35,7 @@ func (c Customer) AsAPICustomer() (api.Customer, error) {
Name: c.Name,
UsageAttribution: api.CustomerUsageAttribution{SubjectKeys: c.UsageAttribution.SubjectKeys},
PrimaryEmail: c.PrimaryEmail,
Description: c.Description,
}

if c.BillingAddress != nil {
Expand Down
11 changes: 5 additions & 6 deletions openmeter/customer/httpdriver/apimapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ func newUpdateCustomerInput(namespace string, apiCustomer api.Customer) customer
// newFromAPICustomer creates a new customer.Customer from an api.Customer.
func newFromAPICustomer(namespace string, apiCustomer api.Customer) customerentity.Customer {
customerModel := customerentity.Customer{
ManagedResource: models.ManagedResource{
NamespacedModel: models.NamespacedModel{
Namespace: namespace,
},
},
Name: apiCustomer.Name,
ManagedResource: models.NewManagedResource(models.ManagedResourceInput{
Namespace: namespace,
Name: apiCustomer.Name,
Description: apiCustomer.Description,
}),
UsageAttribution: customerentity.CustomerUsageAttribution(apiCustomer.UsageAttribution),
PrimaryEmail: apiCustomer.PrimaryEmail,
}
Expand Down
11 changes: 7 additions & 4 deletions openmeter/ent/db/app.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions openmeter/ent/db/app/where.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 92de1c6

Please sign in to comment.