azure

package
v1.40.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 2, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

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

View Source
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

List returns all subscriptions with the given status.

func (*MemorySubscriptionStore) Put

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

type PlanDetails struct {
	PlanID   string `json:"planId"`
	Quantity int    `json:"quantity,omitempty"`
}

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

func (m *SubscriptionManager) IsActive(ctx context.Context, subscriptionID string) (bool, error)

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

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"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL