Documentation
¶
Overview ¶
Package azure provides Azure Marketplace integration for Zerfoo Cloud, including SaaS Fulfillment API v2, Marketplace Metering Service, subscription lifecycle management, and webhook handling.
Index ¶
- Constants
- type BatchUsageResult
- type FulfillmentAPI
- type FulfillmentClient
- func (c *FulfillmentClient) Activate(ctx context.Context, subscriptionID string, plan PlanDetails) error
- func (c *FulfillmentClient) Delete(ctx context.Context, subscriptionID string) error
- func (c *FulfillmentClient) GetSubscription(ctx context.Context, subscriptionID string) (*SaaSSubscription, error)
- func (c *FulfillmentClient) ListSubscriptions(ctx context.Context) ([]SaaSSubscription, error)
- func (c *FulfillmentClient) Resolve(ctx context.Context, marketplaceToken string) (*ResolvedSubscription, error)
- func (c *FulfillmentClient) Suspend(ctx context.Context, subscriptionID string) error
- func (c *FulfillmentClient) UpdateSubscription(ctx context.Context, subscriptionID string, update SubscriptionUpdate) (*OperationLocation, error)
- type MemorySubscriptionStore
- func (s *MemorySubscriptionStore) Delete(_ context.Context, subscriptionID string) error
- func (s *MemorySubscriptionStore) Get(_ context.Context, subscriptionID string) (*SaaSSubscription, error)
- func (s *MemorySubscriptionStore) List(_ context.Context, status SaaSStatus) ([]SaaSSubscription, error)
- func (s *MemorySubscriptionStore) Put(_ context.Context, sub SaaSSubscription) error
- type MeteringAPI
- type MeteringClient
- type MeteringStatus
- type OperationLocation
- type PlanDetails
- type ResolvedSubscription
- type SaaSBeneficiary
- type SaaSPurchaser
- type SaaSStatus
- type SaaSSubscription
- type SaaSTerm
- type SubscriptionManager
- func (m *SubscriptionManager) ChangePlan(ctx context.Context, subscriptionID, newPlanID string) (*OperationLocation, error)
- func (m *SubscriptionManager) ChangeQuantity(ctx context.Context, subscriptionID string, quantity int) (*OperationLocation, error)
- func (m *SubscriptionManager) IsActive(ctx context.Context, subscriptionID string) (bool, error)
- func (m *SubscriptionManager) Reinstate(ctx context.Context, subscriptionID string) error
- func (m *SubscriptionManager) ResolveAndActivate(ctx context.Context, marketplaceToken string, plan PlanDetails) (*SaaSSubscription, error)
- func (m *SubscriptionManager) Suspend(ctx context.Context, subscriptionID string) error
- func (m *SubscriptionManager) Unsubscribe(ctx context.Context, subscriptionID string) error
- type SubscriptionStore
- type SubscriptionUpdate
- type TokenBillingTracker
- type TokenProvider
- type TokenUsageRecord
- type UsageEvent
- type UsageEventResult
- type WebhookAction
- type WebhookHandler
- type WebhookPayload
- type WebhookStatus
Constants ¶
const DimensionTokens = "tokens_1m"
DimensionTokens is the metering dimension name for token-based billing.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BatchUsageResult ¶
type BatchUsageResult struct {
Results []UsageEventResult `json:"result"`
Count int `json:"count"`
}
BatchUsageResult contains the result of posting a batch of usage events.
type FulfillmentAPI ¶
type FulfillmentAPI interface {
// Resolve resolves a marketplace purchase identification token to a subscription.
Resolve(ctx context.Context, marketplaceToken string) (*ResolvedSubscription, error)
// Activate activates a SaaS subscription after the publisher provisions the resource.
Activate(ctx context.Context, subscriptionID string, plan PlanDetails) error
// GetSubscription retrieves the details of a SaaS subscription.
GetSubscription(ctx context.Context, subscriptionID string) (*SaaSSubscription, error)
// UpdateSubscription updates the plan or seat quantity for a subscription.
UpdateSubscription(ctx context.Context, subscriptionID string, update SubscriptionUpdate) (*OperationLocation, error)
// Suspend marks a subscription as suspended (e.g. payment failure).
Suspend(ctx context.Context, subscriptionID string) error
// Delete cancels and deletes a SaaS subscription.
Delete(ctx context.Context, subscriptionID string) error
// ListSubscriptions returns all SaaS subscriptions for the publisher.
ListSubscriptions(ctx context.Context) ([]SaaSSubscription, error)
}
FulfillmentAPI abstracts Azure Marketplace SaaS Fulfillment API v2 calls.
type FulfillmentClient ¶
type FulfillmentClient struct {
// Endpoint is the base URL for the SaaS Fulfillment API.
// Default: https://marketplaceapi.microsoft.com/api
Endpoint string
// APIVersion is the API version query parameter.
// Default: 2018-08-31
APIVersion string
// TokenProvider obtains bearer tokens for API authentication.
TokenProvider TokenProvider
// HTTPClient is the HTTP client used for API calls.
HTTPClient *http.Client
}
FulfillmentClient implements FulfillmentAPI by calling the Azure Marketplace SaaS Fulfillment API v2 REST endpoints.
func NewFulfillmentClient ¶
func NewFulfillmentClient(endpoint string, tokenProvider TokenProvider) *FulfillmentClient
NewFulfillmentClient creates a new FulfillmentClient with the given endpoint and token provider.
func (*FulfillmentClient) Activate ¶
func (c *FulfillmentClient) Activate(ctx context.Context, subscriptionID string, plan PlanDetails) error
Activate activates a SaaS subscription.
func (*FulfillmentClient) Delete ¶
func (c *FulfillmentClient) Delete(ctx context.Context, subscriptionID string) error
Delete cancels and deletes a SaaS subscription.
func (*FulfillmentClient) GetSubscription ¶
func (c *FulfillmentClient) GetSubscription(ctx context.Context, subscriptionID string) (*SaaSSubscription, error)
GetSubscription retrieves a SaaS subscription by ID.
func (*FulfillmentClient) ListSubscriptions ¶
func (c *FulfillmentClient) ListSubscriptions(ctx context.Context) ([]SaaSSubscription, error)
ListSubscriptions returns all SaaS subscriptions.
func (*FulfillmentClient) Resolve ¶
func (c *FulfillmentClient) Resolve(ctx context.Context, marketplaceToken string) (*ResolvedSubscription, error)
Resolve resolves a marketplace purchase token to a subscription.
func (*FulfillmentClient) Suspend ¶
func (c *FulfillmentClient) Suspend(ctx context.Context, subscriptionID string) error
Suspend marks a subscription as suspended.
func (*FulfillmentClient) UpdateSubscription ¶
func (c *FulfillmentClient) UpdateSubscription(ctx context.Context, subscriptionID string, update SubscriptionUpdate) (*OperationLocation, error)
UpdateSubscription updates the plan or seat quantity for a subscription.
type MemorySubscriptionStore ¶
type MemorySubscriptionStore struct {
// contains filtered or unexported fields
}
MemorySubscriptionStore is an in-memory SubscriptionStore for testing.
func NewMemorySubscriptionStore ¶
func NewMemorySubscriptionStore() *MemorySubscriptionStore
NewMemorySubscriptionStore creates a new in-memory subscription store.
func (*MemorySubscriptionStore) Delete ¶
func (s *MemorySubscriptionStore) Delete(_ context.Context, subscriptionID string) error
Delete removes a subscription by ID.
func (*MemorySubscriptionStore) Get ¶
func (s *MemorySubscriptionStore) Get(_ context.Context, subscriptionID string) (*SaaSSubscription, error)
Get retrieves a subscription by ID.
func (*MemorySubscriptionStore) List ¶
func (s *MemorySubscriptionStore) List(_ context.Context, status SaaSStatus) ([]SaaSSubscription, error)
List returns all subscriptions with the given status.
func (*MemorySubscriptionStore) Put ¶
func (s *MemorySubscriptionStore) Put(_ context.Context, sub SaaSSubscription) error
Put stores a subscription.
type MeteringAPI ¶
type MeteringAPI interface {
// PostUsageEvent submits a single usage event for a metered dimension.
PostUsageEvent(ctx context.Context, event UsageEvent) (*UsageEventResult, error)
// PostBatchUsageEvent submits a batch of usage events.
PostBatchUsageEvent(ctx context.Context, events []UsageEvent) (*BatchUsageResult, error)
}
MeteringAPI abstracts Azure Marketplace Metering Service API calls.
type MeteringClient ¶
type MeteringClient struct {
// Endpoint is the Azure Marketplace Metering Service endpoint URL.
// Default: https://marketplaceapi.microsoft.com/api
Endpoint string
// APIVersion is the API version query parameter.
// Default: 2018-08-31
APIVersion string
// TokenProvider obtains bearer tokens for authentication.
TokenProvider TokenProvider
// HTTPClient is the HTTP client used for API calls.
HTTPClient *http.Client
// Retry configures exponential backoff for metering calls.
// Zero value disables retry.
Retry marketplace.RetryConfig
}
MeteringClient implements MeteringAPI by calling the Azure Marketplace Metering Service REST endpoints.
func NewMeteringClient ¶
func NewMeteringClient(endpoint string, tokenProvider TokenProvider) *MeteringClient
NewMeteringClient creates a new MeteringClient with the given endpoint and token provider.
func (*MeteringClient) PostBatchUsageEvent ¶
func (c *MeteringClient) PostBatchUsageEvent(ctx context.Context, events []UsageEvent) (*BatchUsageResult, error)
PostBatchUsageEvent submits a batch of usage events.
func (*MeteringClient) PostUsageEvent ¶
func (c *MeteringClient) PostUsageEvent(ctx context.Context, event UsageEvent) (*UsageEventResult, error)
PostUsageEvent submits a single usage event.
type MeteringStatus ¶
type MeteringStatus string
MeteringStatus represents the status of a metering event.
const ( MeteringStatusAccepted MeteringStatus = "Accepted" MeteringStatusDuplicate MeteringStatus = "Duplicate" MeteringStatusExpired MeteringStatus = "Expired" MeteringStatusResourceNotFound MeteringStatus = "ResourceNotFound" )
type OperationLocation ¶
type OperationLocation struct {
Location string `json:"location"`
}
OperationLocation is returned by async operations, containing a URL to poll for status.
type PlanDetails ¶
PlanDetails identifies the plan to activate.
type ResolvedSubscription ¶
type ResolvedSubscription struct {
ID string `json:"id"`
SubscriptionName string `json:"subscriptionName"`
OfferID string `json:"offerId"`
PlanID string `json:"planId"`
Quantity int `json:"quantity,omitempty"`
PublisherID string `json:"publisherId"`
BeneficiaryTenant string `json:"beneficiary.tenantId"`
}
ResolvedSubscription is the result of resolving a marketplace token.
type SaaSBeneficiary ¶
type SaaSBeneficiary struct {
TenantID string `json:"tenantId"`
ObjectID string `json:"objectId"`
Email string `json:"emailId"`
}
SaaSBeneficiary identifies the Azure AD tenant and user benefiting from the subscription.
type SaaSPurchaser ¶
type SaaSPurchaser struct {
TenantID string `json:"tenantId"`
ObjectID string `json:"objectId"`
Email string `json:"emailId"`
}
SaaSPurchaser identifies the Azure AD tenant and user that purchased the subscription.
type SaaSStatus ¶
type SaaSStatus string
SaaSStatus represents the lifecycle state of an Azure SaaS subscription.
const ( SaaSStatusPendingConfiguration SaaSStatus = "PendingFulfillmentStart" SaaSStatusSubscribed SaaSStatus = "Subscribed" SaaSStatusSuspended SaaSStatus = "Suspended" SaaSStatusUnsubscribed SaaSStatus = "Unsubscribed" )
type SaaSSubscription ¶
type SaaSSubscription struct {
ID string `json:"id"`
SubscriptionName string `json:"name"`
OfferID string `json:"offerId"`
PlanID string `json:"planId"`
Quantity int `json:"quantity,omitempty"`
Status SaaSStatus `json:"saasSubscriptionStatus"`
Beneficiary SaaSBeneficiary `json:"beneficiary"`
Purchaser SaaSPurchaser `json:"purchaser"`
Term SaaSTerm `json:"term"`
Created time.Time `json:"created"`
}
SaaSSubscription represents an Azure Marketplace SaaS subscription.
type SaaSTerm ¶
type SaaSTerm struct {
StartDate time.Time `json:"startDate"`
EndDate time.Time `json:"endDate"`
TermUnit string `json:"termUnit"` // "P1M" or "P1Y"
}
SaaSTerm describes the subscription billing term.
type SubscriptionManager ¶
type SubscriptionManager struct {
// contains filtered or unexported fields
}
SubscriptionManager handles the Azure SaaS subscription lifecycle using the Fulfillment API and a local subscription store.
func NewSubscriptionManager ¶
func NewSubscriptionManager(store SubscriptionStore, fulfillment FulfillmentAPI) *SubscriptionManager
NewSubscriptionManager creates a SubscriptionManager backed by the given store and fulfillment API client.
func (*SubscriptionManager) ChangePlan ¶
func (m *SubscriptionManager) ChangePlan(ctx context.Context, subscriptionID, newPlanID string) (*OperationLocation, error)
ChangePlan updates the subscription's plan via the Fulfillment API.
func (*SubscriptionManager) ChangeQuantity ¶
func (m *SubscriptionManager) ChangeQuantity(ctx context.Context, subscriptionID string, quantity int) (*OperationLocation, error)
ChangeQuantity updates the subscription's seat quantity via the Fulfillment API.
func (*SubscriptionManager) IsActive ¶
IsActive checks whether a subscription is in the Subscribed state.
func (*SubscriptionManager) Reinstate ¶
func (m *SubscriptionManager) Reinstate(ctx context.Context, subscriptionID string) error
Reinstate changes a suspended subscription back to subscribed.
func (*SubscriptionManager) ResolveAndActivate ¶
func (m *SubscriptionManager) ResolveAndActivate(ctx context.Context, marketplaceToken string, plan PlanDetails) (*SaaSSubscription, error)
ResolveAndActivate resolves a marketplace purchase token, activates the subscription with the specified plan, and stores the subscription locally.
func (*SubscriptionManager) Suspend ¶
func (m *SubscriptionManager) Suspend(ctx context.Context, subscriptionID string) error
Suspend suspends a subscription both in Azure and in the local store.
func (*SubscriptionManager) Unsubscribe ¶
func (m *SubscriptionManager) Unsubscribe(ctx context.Context, subscriptionID string) error
Unsubscribe marks a subscription as unsubscribed and deletes it in Azure.
type SubscriptionStore ¶
type SubscriptionStore interface {
// Put stores or updates a subscription.
Put(ctx context.Context, sub SaaSSubscription) error
// Get retrieves a subscription by ID.
Get(ctx context.Context, subscriptionID string) (*SaaSSubscription, error)
// List returns all subscriptions with the given status.
List(ctx context.Context, status SaaSStatus) ([]SaaSSubscription, error)
// Delete removes a subscription by ID.
Delete(ctx context.Context, subscriptionID string) error
}
SubscriptionStore persists Azure SaaS subscription records.
type SubscriptionUpdate ¶
type SubscriptionUpdate struct {
PlanID string `json:"planId,omitempty"`
Quantity int `json:"quantity,omitempty"`
}
SubscriptionUpdate contains fields for updating a subscription.
type TokenBillingTracker ¶
type TokenBillingTracker struct {
// contains filtered or unexported fields
}
TokenBillingTracker accumulates token usage per subscription and flushes metering records to Azure Marketplace in batches.
func NewTokenBillingTracker ¶
func NewTokenBillingTracker(planID string, metering MeteringAPI) *TokenBillingTracker
NewTokenBillingTracker creates a new TokenBillingTracker for the given plan.
func (*TokenBillingTracker) Flush ¶
func (t *TokenBillingTracker) Flush(ctx context.Context) (*BatchUsageResult, error)
Flush sends accumulated usage to Azure Marketplace via PostBatchUsageEvent and resets the accumulators. Usage is billed per 1M tokens.
func (*TokenBillingTracker) RecordUsage ¶
func (t *TokenBillingTracker) RecordUsage(resourceID string, inputTokens, outputTokens int64)
RecordUsage adds token usage for a subscription resource.
func (*TokenBillingTracker) Snapshot ¶
func (t *TokenBillingTracker) Snapshot() []TokenUsageRecord
Snapshot returns the current accumulated usage per subscription without resetting the accumulators.
type TokenProvider ¶
type TokenProvider interface {
// Token returns a valid bearer token for the Azure Marketplace API.
Token(ctx context.Context) (string, error)
}
TokenProvider obtains Azure AD bearer tokens for API authentication.
type TokenUsageRecord ¶
type TokenUsageRecord struct {
ResourceID string `json:"resourceId"`
InputTokens int64 `json:"inputTokens"`
OutputTokens int64 `json:"outputTokens"`
TotalTokens int64 `json:"totalTokens"`
Timestamp time.Time `json:"timestamp"`
}
TokenUsageRecord tracks token usage for a subscription within a billing period.
type UsageEvent ¶
type UsageEvent struct {
ResourceID string `json:"resourceId"`
Quantity float64 `json:"quantity"`
Dimension string `json:"dimension"`
EffectiveTime time.Time `json:"effectiveStartTime"`
PlanID string `json:"planId"`
}
UsageEvent represents a single metering event for Azure Marketplace.
type UsageEventResult ¶
type UsageEventResult struct {
UsageEventID string `json:"usageEventId"`
Status MeteringStatus `json:"status"`
Quantity float64 `json:"quantity"`
Dimension string `json:"dimension"`
EffectiveTime time.Time `json:"effectiveStartTime"`
PlanID string `json:"planId"`
MessageTime time.Time `json:"messageTime"`
}
UsageEventResult contains the result of posting a single usage event.
type WebhookAction ¶
type WebhookAction string
WebhookAction represents the type of subscription lifecycle event.
const ( ActionChangePlan WebhookAction = "ChangePlan" ActionChangeQuantity WebhookAction = "ChangeQuantity" ActionSuspend WebhookAction = "Suspend" ActionReinstate WebhookAction = "Reinstate" ActionUnsubscribe WebhookAction = "Unsubscribe" ActionRenew WebhookAction = "Renew" )
type WebhookHandler ¶
type WebhookHandler struct {
// Secret is the shared secret for HMAC-SHA256 signature validation.
// Must be non-empty; the handler returns 500 if not configured.
Secret string
// Manager handles subscription state transitions.
Manager *SubscriptionManager
// OnEvent is an optional callback invoked after processing each webhook event.
// It can be used for logging, metrics, or custom business logic.
OnEvent func(payload WebhookPayload, err error)
// Now returns the current time. If nil, time.Now is used.
// Exposed for testing timestamp validation.
Now func() time.Time
// contains filtered or unexported fields
}
WebhookHandler handles Azure Marketplace webhook notifications for subscription lifecycle events.
func NewWebhookHandler ¶
func NewWebhookHandler(secret string, manager *SubscriptionManager) *WebhookHandler
NewWebhookHandler creates a WebhookHandler with the given secret and subscription manager.
func (*WebhookHandler) ServeHTTP ¶
func (h *WebhookHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler for Azure Marketplace webhook notifications.
type WebhookPayload ¶
type WebhookPayload struct {
ID string `json:"id"`
ActivityID string `json:"activityId"`
SubscriptionID string `json:"subscriptionId"`
OfferID string `json:"offerId"`
PublisherID string `json:"publisherId"`
PlanID string `json:"planId"`
Quantity int `json:"quantity,omitempty"`
Action WebhookAction `json:"action"`
Timestamp time.Time `json:"timeStamp"`
Status WebhookStatus `json:"status"`
OperationID string `json:"operationId"`
}
WebhookPayload represents the JSON body of an Azure Marketplace webhook notification.
type WebhookStatus ¶
type WebhookStatus string
WebhookStatus represents the status of the operation in the webhook payload.
const ( WebhookStatusInProgress WebhookStatus = "InProgress" WebhookStatusSuccess WebhookStatus = "Success" WebhookStatusFailure WebhookStatus = "Failure" )