benefitutilizationsummariesasync

package
v0.0.0-...-a81a29a Latest Latest
Warning

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

Go to latest
Published: Jun 15, 2023 License: MPL-2.0 Imports: 13 Imported by: 0

README

github.com/hashicorp/go-azure-sdk/resource-manager/costmanagement/2023-03-01/benefitutilizationsummariesasync Documentation

The benefitutilizationsummariesasync SDK allows for interaction with the Azure Resource Manager Service costmanagement (API Version 2023-03-01).

This readme covers example usages, but further information on using this SDK can be found in the project root.

Import Path

import "github.com/hashicorp/go-azure-sdk/resource-manager/costmanagement/2023-03-01/benefitutilizationsummariesasync"

Client Initialization

client := benefitutilizationsummariesasync.NewBenefitUtilizationSummariesAsyncClientWithBaseURI("https://management.azure.com")
client.Client.Authorizer = authorizer

Example Usage: BenefitUtilizationSummariesAsyncClient.GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanId

ctx := context.TODO()
id := benefitutilizationsummariesasync.NewSavingsPlanID("savingsPlanOrderIdValue", "savingsPlanIdValue")

payload := benefitutilizationsummariesasync.BenefitUtilizationSummariesRequest{
	// ...
}


if err := client.GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanIdThenPoll(ctx, id, payload); err != nil {
	// handle the error
}

Example Usage: BenefitUtilizationSummariesAsyncClient.GenerateBenefitUtilizationSummariesReportGenerateByBillingAccount

ctx := context.TODO()
id := benefitutilizationsummariesasync.NewBillingAccountID("billingAccountIdValue")

payload := benefitutilizationsummariesasync.BenefitUtilizationSummariesRequest{
	// ...
}


if err := client.GenerateBenefitUtilizationSummariesReportGenerateByBillingAccountThenPoll(ctx, id, payload); err != nil {
	// handle the error
}

Example Usage: BenefitUtilizationSummariesAsyncClient.GenerateBenefitUtilizationSummariesReportGenerateByBillingProfile

ctx := context.TODO()
id := benefitutilizationsummariesasync.NewBillingProfileID("billingAccountIdValue", "billingProfileIdValue")

payload := benefitutilizationsummariesasync.BenefitUtilizationSummariesRequest{
	// ...
}


if err := client.GenerateBenefitUtilizationSummariesReportGenerateByBillingProfileThenPoll(ctx, id, payload); err != nil {
	// handle the error
}

Example Usage: BenefitUtilizationSummariesAsyncClient.GenerateBenefitUtilizationSummariesReportGenerateByReservationId

ctx := context.TODO()
id := benefitutilizationsummariesasync.NewReservationID("reservationOrderIdValue", "reservationIdValue")

payload := benefitutilizationsummariesasync.BenefitUtilizationSummariesRequest{
	// ...
}


if err := client.GenerateBenefitUtilizationSummariesReportGenerateByReservationIdThenPoll(ctx, id, payload); err != nil {
	// handle the error
}

Example Usage: BenefitUtilizationSummariesAsyncClient.GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderId

ctx := context.TODO()
id := benefitutilizationsummariesasync.NewReservationOrderID("reservationOrderIdValue")

payload := benefitutilizationsummariesasync.BenefitUtilizationSummariesRequest{
	// ...
}


if err := client.GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderIdThenPoll(ctx, id, payload); err != nil {
	// handle the error
}

Example Usage: BenefitUtilizationSummariesAsyncClient.GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderId

ctx := context.TODO()
id := benefitutilizationsummariesasync.NewSavingsPlanOrderID("savingsPlanOrderIdValue")

payload := benefitutilizationsummariesasync.BenefitUtilizationSummariesRequest{
	// ...
}


if err := client.GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderIdThenPoll(ctx, id, payload); err != nil {
	// handle the error
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func PossibleValuesForBenefitKind

func PossibleValuesForBenefitKind() []string

func PossibleValuesForBenefitUtilizationSummaryReportSchema

func PossibleValuesForBenefitUtilizationSummaryReportSchema() []string

func PossibleValuesForGrain

func PossibleValuesForGrain() []string

func PossibleValuesForOperationStatusType

func PossibleValuesForOperationStatusType() []string

func ValidateBillingAccountID

func ValidateBillingAccountID(input interface{}, key string) (warnings []string, errors []error)

ValidateBillingAccountID checks that 'input' can be parsed as a Billing Account ID

func ValidateBillingProfileID

func ValidateBillingProfileID(input interface{}, key string) (warnings []string, errors []error)

ValidateBillingProfileID checks that 'input' can be parsed as a Billing Profile ID

func ValidateReservationID

func ValidateReservationID(input interface{}, key string) (warnings []string, errors []error)

ValidateReservationID checks that 'input' can be parsed as a Reservation ID

func ValidateReservationOrderID

func ValidateReservationOrderID(input interface{}, key string) (warnings []string, errors []error)

ValidateReservationOrderID checks that 'input' can be parsed as a Reservation Order ID

func ValidateSavingsPlanID

func ValidateSavingsPlanID(input interface{}, key string) (warnings []string, errors []error)

ValidateSavingsPlanID checks that 'input' can be parsed as a Savings Plan ID

func ValidateSavingsPlanOrderID

func ValidateSavingsPlanOrderID(input interface{}, key string) (warnings []string, errors []error)

ValidateSavingsPlanOrderID checks that 'input' can be parsed as a Savings Plan Order ID

Types

type AsyncOperationStatusProperties

type AsyncOperationStatusProperties struct {
	ReportUrl          *BenefitUtilizationSummaryReportSchema `json:"reportUrl,omitempty"`
	SecondaryReportUrl *BenefitUtilizationSummaryReportSchema `json:"secondaryReportUrl,omitempty"`
	ValidUntil         *string                                `json:"validUntil,omitempty"`
}

func (*AsyncOperationStatusProperties) GetValidUntilAsTime

func (o *AsyncOperationStatusProperties) GetValidUntilAsTime() (*time.Time, error)

func (*AsyncOperationStatusProperties) SetValidUntilAsTime

func (o *AsyncOperationStatusProperties) SetValidUntilAsTime(input time.Time)

type BenefitKind

type BenefitKind string
const (
	BenefitKindIncludedQuantity BenefitKind = "IncludedQuantity"
	BenefitKindReservation      BenefitKind = "Reservation"
	BenefitKindSavingsPlan      BenefitKind = "SavingsPlan"
)

func (*BenefitKind) UnmarshalJSON

func (s *BenefitKind) UnmarshalJSON(bytes []byte) error

type BenefitUtilizationSummariesAsyncClient

type BenefitUtilizationSummariesAsyncClient struct {
	Client *resourcemanager.Client
}

func NewBenefitUtilizationSummariesAsyncClientWithBaseURI

func NewBenefitUtilizationSummariesAsyncClientWithBaseURI(api environments.Api) (*BenefitUtilizationSummariesAsyncClient, error)

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanId

GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanId ...

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanIdThenPoll

func (c BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanIdThenPoll(ctx context.Context, id SavingsPlanId, input BenefitUtilizationSummariesRequest) error

GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanIdThenPoll performs GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanId then polls until it's completed

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByBillingAccount

GenerateBenefitUtilizationSummariesReportGenerateByBillingAccount ...

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByBillingAccountThenPoll

func (c BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByBillingAccountThenPoll(ctx context.Context, id BillingAccountId, input BenefitUtilizationSummariesRequest) error

GenerateBenefitUtilizationSummariesReportGenerateByBillingAccountThenPoll performs GenerateBenefitUtilizationSummariesReportGenerateByBillingAccount then polls until it's completed

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByBillingProfile

GenerateBenefitUtilizationSummariesReportGenerateByBillingProfile ...

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByBillingProfileThenPoll

func (c BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByBillingProfileThenPoll(ctx context.Context, id BillingProfileId, input BenefitUtilizationSummariesRequest) error

GenerateBenefitUtilizationSummariesReportGenerateByBillingProfileThenPoll performs GenerateBenefitUtilizationSummariesReportGenerateByBillingProfile then polls until it's completed

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByReservationId

GenerateBenefitUtilizationSummariesReportGenerateByReservationId ...

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByReservationIdThenPoll

func (c BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByReservationIdThenPoll(ctx context.Context, id ReservationId, input BenefitUtilizationSummariesRequest) error

GenerateBenefitUtilizationSummariesReportGenerateByReservationIdThenPoll performs GenerateBenefitUtilizationSummariesReportGenerateByReservationId then polls until it's completed

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderId

GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderId ...

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderIdThenPoll

func (c BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderIdThenPoll(ctx context.Context, id ReservationOrderId, input BenefitUtilizationSummariesRequest) error

GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderIdThenPoll performs GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderId then polls until it's completed

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderId

GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderId ...

func (BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderIdThenPoll

func (c BenefitUtilizationSummariesAsyncClient) GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderIdThenPoll(ctx context.Context, id SavingsPlanOrderId, input BenefitUtilizationSummariesRequest) error

GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderIdThenPoll performs GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderId then polls until it's completed

type BenefitUtilizationSummariesOperationStatus

type BenefitUtilizationSummariesOperationStatus struct {
	Input      *BenefitUtilizationSummariesRequest `json:"input,omitempty"`
	Properties *AsyncOperationStatusProperties     `json:"properties,omitempty"`
	Status     *OperationStatusType                `json:"status,omitempty"`
}

type BenefitUtilizationSummariesRequest

type BenefitUtilizationSummariesRequest struct {
	BenefitId        *string      `json:"benefitId,omitempty"`
	BenefitOrderId   *string      `json:"benefitOrderId,omitempty"`
	BillingAccountId *string      `json:"billingAccountId,omitempty"`
	BillingProfileId *string      `json:"billingProfileId,omitempty"`
	EndDate          string       `json:"endDate"`
	Grain            Grain        `json:"grain"`
	Kind             *BenefitKind `json:"kind,omitempty"`
	StartDate        string       `json:"startDate"`
}

func (*BenefitUtilizationSummariesRequest) GetEndDateAsTime

func (o *BenefitUtilizationSummariesRequest) GetEndDateAsTime() (*time.Time, error)

func (*BenefitUtilizationSummariesRequest) GetStartDateAsTime

func (o *BenefitUtilizationSummariesRequest) GetStartDateAsTime() (*time.Time, error)

func (*BenefitUtilizationSummariesRequest) SetEndDateAsTime

func (o *BenefitUtilizationSummariesRequest) SetEndDateAsTime(input time.Time)

func (*BenefitUtilizationSummariesRequest) SetStartDateAsTime

func (o *BenefitUtilizationSummariesRequest) SetStartDateAsTime(input time.Time)

type BenefitUtilizationSummaryReportSchema

type BenefitUtilizationSummaryReportSchema string
const (
	BenefitUtilizationSummaryReportSchemaAvgUtilizationPercentage BenefitUtilizationSummaryReportSchema = "AvgUtilizationPercentage"
	BenefitUtilizationSummaryReportSchemaBenefitId                BenefitUtilizationSummaryReportSchema = "BenefitId"
	BenefitUtilizationSummaryReportSchemaBenefitOrderId           BenefitUtilizationSummaryReportSchema = "BenefitOrderId"
	BenefitUtilizationSummaryReportSchemaBenefitType              BenefitUtilizationSummaryReportSchema = "BenefitType"
	BenefitUtilizationSummaryReportSchemaKind                     BenefitUtilizationSummaryReportSchema = "Kind"
	BenefitUtilizationSummaryReportSchemaMaxUtilizationPercentage BenefitUtilizationSummaryReportSchema = "MaxUtilizationPercentage"
	BenefitUtilizationSummaryReportSchemaMinUtilizationPercentage BenefitUtilizationSummaryReportSchema = "MinUtilizationPercentage"
	BenefitUtilizationSummaryReportSchemaUsageDate                BenefitUtilizationSummaryReportSchema = "UsageDate"
	BenefitUtilizationSummaryReportSchemaUtilizedPercentage       BenefitUtilizationSummaryReportSchema = "UtilizedPercentage"
)

func (*BenefitUtilizationSummaryReportSchema) UnmarshalJSON

func (s *BenefitUtilizationSummaryReportSchema) UnmarshalJSON(bytes []byte) error

type BillingAccountId

type BillingAccountId struct {
	BillingAccountId string
}

BillingAccountId is a struct representing the Resource ID for a Billing Account

func NewBillingAccountID

func NewBillingAccountID(billingAccountId string) BillingAccountId

NewBillingAccountID returns a new BillingAccountId struct

func ParseBillingAccountID

func ParseBillingAccountID(input string) (*BillingAccountId, error)

ParseBillingAccountID parses 'input' into a BillingAccountId

func ParseBillingAccountIDInsensitively

func ParseBillingAccountIDInsensitively(input string) (*BillingAccountId, error)

ParseBillingAccountIDInsensitively parses 'input' case-insensitively into a BillingAccountId note: this method should only be used for API response data and not user input

func (BillingAccountId) ID

func (id BillingAccountId) ID() string

ID returns the formatted Billing Account ID

func (BillingAccountId) Segments

func (id BillingAccountId) Segments() []resourceids.Segment

Segments returns a slice of Resource ID Segments which comprise this Billing Account ID

func (BillingAccountId) String

func (id BillingAccountId) String() string

String returns a human-readable description of this Billing Account ID

type BillingProfileId

type BillingProfileId struct {
	BillingAccountId string
	BillingProfileId string
}

BillingProfileId is a struct representing the Resource ID for a Billing Profile

func NewBillingProfileID

func NewBillingProfileID(billingAccountId string, billingProfileId string) BillingProfileId

NewBillingProfileID returns a new BillingProfileId struct

func ParseBillingProfileID

func ParseBillingProfileID(input string) (*BillingProfileId, error)

ParseBillingProfileID parses 'input' into a BillingProfileId

func ParseBillingProfileIDInsensitively

func ParseBillingProfileIDInsensitively(input string) (*BillingProfileId, error)

ParseBillingProfileIDInsensitively parses 'input' case-insensitively into a BillingProfileId note: this method should only be used for API response data and not user input

func (BillingProfileId) ID

func (id BillingProfileId) ID() string

ID returns the formatted Billing Profile ID

func (BillingProfileId) Segments

func (id BillingProfileId) Segments() []resourceids.Segment

Segments returns a slice of Resource ID Segments which comprise this Billing Profile ID

func (BillingProfileId) String

func (id BillingProfileId) String() string

String returns a human-readable description of this Billing Profile ID

type GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanIdOperationResponse

type GenerateBenefitUtilizationSummariesReportAsyncGenerateBySavingsPlanIdOperationResponse struct {
	Poller       pollers.Poller
	HttpResponse *http.Response
	OData        *odata.OData
}

type GenerateBenefitUtilizationSummariesReportGenerateByBillingAccountOperationResponse

type GenerateBenefitUtilizationSummariesReportGenerateByBillingAccountOperationResponse struct {
	Poller       pollers.Poller
	HttpResponse *http.Response
	OData        *odata.OData
}

type GenerateBenefitUtilizationSummariesReportGenerateByBillingProfileOperationResponse

type GenerateBenefitUtilizationSummariesReportGenerateByBillingProfileOperationResponse struct {
	Poller       pollers.Poller
	HttpResponse *http.Response
	OData        *odata.OData
}

type GenerateBenefitUtilizationSummariesReportGenerateByReservationIdOperationResponse

type GenerateBenefitUtilizationSummariesReportGenerateByReservationIdOperationResponse struct {
	Poller       pollers.Poller
	HttpResponse *http.Response
	OData        *odata.OData
}

type GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderIdOperationResponse

type GenerateBenefitUtilizationSummariesReportGenerateByReservationOrderIdOperationResponse struct {
	Poller       pollers.Poller
	HttpResponse *http.Response
	OData        *odata.OData
}

type GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderIdOperationResponse

type GenerateBenefitUtilizationSummariesReportGenerateBySavingsPlanOrderIdOperationResponse struct {
	Poller       pollers.Poller
	HttpResponse *http.Response
	OData        *odata.OData
}

type Grain

type Grain string
const (
	GrainDaily   Grain = "Daily"
	GrainHourly  Grain = "Hourly"
	GrainMonthly Grain = "Monthly"
)

func (*Grain) UnmarshalJSON

func (s *Grain) UnmarshalJSON(bytes []byte) error

type OperationStatusType

type OperationStatusType string
const (
	OperationStatusTypeComplete OperationStatusType = "Complete"
	OperationStatusTypeFailed   OperationStatusType = "Failed"
	OperationStatusTypeRunning  OperationStatusType = "Running"
)

func (*OperationStatusType) UnmarshalJSON

func (s *OperationStatusType) UnmarshalJSON(bytes []byte) error

type ReservationId

type ReservationId struct {
	ReservationOrderId string
	ReservationId      string
}

ReservationId is a struct representing the Resource ID for a Reservation

func NewReservationID

func NewReservationID(reservationOrderId string, reservationId string) ReservationId

NewReservationID returns a new ReservationId struct

func ParseReservationID

func ParseReservationID(input string) (*ReservationId, error)

ParseReservationID parses 'input' into a ReservationId

func ParseReservationIDInsensitively

func ParseReservationIDInsensitively(input string) (*ReservationId, error)

ParseReservationIDInsensitively parses 'input' case-insensitively into a ReservationId note: this method should only be used for API response data and not user input

func (ReservationId) ID

func (id ReservationId) ID() string

ID returns the formatted Reservation ID

func (ReservationId) Segments

func (id ReservationId) Segments() []resourceids.Segment

Segments returns a slice of Resource ID Segments which comprise this Reservation ID

func (ReservationId) String

func (id ReservationId) String() string

String returns a human-readable description of this Reservation ID

type ReservationOrderId

type ReservationOrderId struct {
	ReservationOrderId string
}

ReservationOrderId is a struct representing the Resource ID for a Reservation Order

func NewReservationOrderID

func NewReservationOrderID(reservationOrderId string) ReservationOrderId

NewReservationOrderID returns a new ReservationOrderId struct

func ParseReservationOrderID

func ParseReservationOrderID(input string) (*ReservationOrderId, error)

ParseReservationOrderID parses 'input' into a ReservationOrderId

func ParseReservationOrderIDInsensitively

func ParseReservationOrderIDInsensitively(input string) (*ReservationOrderId, error)

ParseReservationOrderIDInsensitively parses 'input' case-insensitively into a ReservationOrderId note: this method should only be used for API response data and not user input

func (ReservationOrderId) ID

func (id ReservationOrderId) ID() string

ID returns the formatted Reservation Order ID

func (ReservationOrderId) Segments

func (id ReservationOrderId) Segments() []resourceids.Segment

Segments returns a slice of Resource ID Segments which comprise this Reservation Order ID

func (ReservationOrderId) String

func (id ReservationOrderId) String() string

String returns a human-readable description of this Reservation Order ID

type SavingsPlanId

type SavingsPlanId struct {
	SavingsPlanOrderId string
	SavingsPlanId      string
}

SavingsPlanId is a struct representing the Resource ID for a Savings Plan

func NewSavingsPlanID

func NewSavingsPlanID(savingsPlanOrderId string, savingsPlanId string) SavingsPlanId

NewSavingsPlanID returns a new SavingsPlanId struct

func ParseSavingsPlanID

func ParseSavingsPlanID(input string) (*SavingsPlanId, error)

ParseSavingsPlanID parses 'input' into a SavingsPlanId

func ParseSavingsPlanIDInsensitively

func ParseSavingsPlanIDInsensitively(input string) (*SavingsPlanId, error)

ParseSavingsPlanIDInsensitively parses 'input' case-insensitively into a SavingsPlanId note: this method should only be used for API response data and not user input

func (SavingsPlanId) ID

func (id SavingsPlanId) ID() string

ID returns the formatted Savings Plan ID

func (SavingsPlanId) Segments

func (id SavingsPlanId) Segments() []resourceids.Segment

Segments returns a slice of Resource ID Segments which comprise this Savings Plan ID

func (SavingsPlanId) String

func (id SavingsPlanId) String() string

String returns a human-readable description of this Savings Plan ID

type SavingsPlanOrderId

type SavingsPlanOrderId struct {
	SavingsPlanOrderId string
}

SavingsPlanOrderId is a struct representing the Resource ID for a Savings Plan Order

func NewSavingsPlanOrderID

func NewSavingsPlanOrderID(savingsPlanOrderId string) SavingsPlanOrderId

NewSavingsPlanOrderID returns a new SavingsPlanOrderId struct

func ParseSavingsPlanOrderID

func ParseSavingsPlanOrderID(input string) (*SavingsPlanOrderId, error)

ParseSavingsPlanOrderID parses 'input' into a SavingsPlanOrderId

func ParseSavingsPlanOrderIDInsensitively

func ParseSavingsPlanOrderIDInsensitively(input string) (*SavingsPlanOrderId, error)

ParseSavingsPlanOrderIDInsensitively parses 'input' case-insensitively into a SavingsPlanOrderId note: this method should only be used for API response data and not user input

func (SavingsPlanOrderId) ID

func (id SavingsPlanOrderId) ID() string

ID returns the formatted Savings Plan Order ID

func (SavingsPlanOrderId) Segments

func (id SavingsPlanOrderId) Segments() []resourceids.Segment

Segments returns a slice of Resource ID Segments which comprise this Savings Plan Order ID

func (SavingsPlanOrderId) String

func (id SavingsPlanOrderId) String() string

String returns a human-readable description of this Savings Plan Order ID

Jump to

Keyboard shortcuts

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