v1alpha1

package
v1.4.2 Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2021 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package v1alpha1 contains API Schema definitions for the operator.ibm.com v1alpha1 API group +kubebuilder:object:generate=true +groupName=operator.ibm.com

Index

Constants

View Source
const OperandLicensingImageEnvVar = "IBM_LICENSING_IMAGE"
View Source
const OperandReporterDatabaseImageEnvVar = "IBM_POSTGRESQL_IMAGE"
View Source
const OperandReporterReceiverImageEnvVar = "IBM_LICENSE_SERVICE_REPORTER_IMAGE"
View Source
const OperandReporterUIImageEnvVar = "IBM_LICENSE_SERVICE_REPORTER_UI_IMAGE"
View Source
const OperandUsageImageEnvVar = "IBM_LICENSING_USAGE_IMAGE"

Variables

View Source
var (
	// GroupVersion is group version used to register these objects
	GroupVersion = schema.GroupVersion{Group: "operator.ibm.com", Version: "v1alpha1"}

	// SchemeBuilder is used to add go types to the GroupVersionKind scheme
	SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}

	// AddToScheme adds the types in this group-version to the given scheme.
	AddToScheme = SchemeBuilder.AddToScheme
)

Functions

func CheckOperandEnvVar

func CheckOperandEnvVar() error

Types

type Container

type Container struct {
	// IBM Licensing Service docker Image Registry, will override default value and disable IBM_LICENSING_IMAGE env value in operator deployment
	ImageRegistry string `json:"imageRegistry,omitempty"`
	// IBM Licensing Service docker Image Name, will override default value and disable IBM_LICENSING_IMAGE env value in operator deployment
	ImageName string `json:"imageName,omitempty"`
	// IBM Licensing Service docker Image Tag or Digest, will override default value and disable IBM_LICENSING_IMAGE env value in operator deployment
	ImageTagPostfix string `json:"imageTagPostfix,omitempty"`

	Resources corev1.ResourceRequirements `json:"resources,omitempty"`

	// +kubebuilder:validation:Enum=Always;IfNotPresent;Never
	ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
}

func (*Container) DeepCopy

func (in *Container) DeepCopy() *Container

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Container.

func (*Container) DeepCopyInto

func (in *Container) DeepCopyInto(out *Container)

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

func (*Container) GetFullImage

func (container *Container) GetFullImage() string

type HTTPSCertsSource

type HTTPSCertsSource string

HTTPSCertsSource describes how certificate is set in available APIs

const (
	// OcpCertsSource means application will use cert manager
	OcpCertsSource HTTPSCertsSource = "ocp"
	// SelfSignedCertsSource means application will create certificate by itself and use it
	SelfSignedCertsSource HTTPSCertsSource = "self-signed"
	// CustomCertsSource means application will use certificate created by user
	CustomCertsSource HTTPSCertsSource = "custom"
)

type IBMLicenseServiceBaseSpec

type IBMLicenseServiceBaseSpec struct {
	// Should application pod show additional information, options: DEBUG, INFO
	// +kubebuilder:validation:Enum=DEBUG;INFO
	LogLevel string `json:"logLevel,omitempty"`
	// Secret name used to store application token, either one that exists, or one that will be created
	APISecretToken string `json:"apiSecretToken,omitempty"`
	// Array of pull secrets which should include existing at InstanceNamespace secret to allow pulling IBM Licensing image
	ImagePullSecrets []string `json:"imagePullSecrets,omitempty"`
	// options: self-signed or custom
	// +kubebuilder:validation:Enum=self-signed;custom;ocp
	HTTPSCertsSource HTTPSCertsSource `json:"httpsCertsSource,omitempty"`
	// Route parameters
	RouteOptions *IBMLicenseServiceRouteOptions `json:"routeOptions,omitempty"`
	// Version
	Version string `json:"version,omitempty"`
}

func (*IBMLicenseServiceBaseSpec) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicenseServiceBaseSpec.

func (*IBMLicenseServiceBaseSpec) DeepCopyInto

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

type IBMLicenseServiceReporter

type IBMLicenseServiceReporter struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   IBMLicenseServiceReporterSpec   `json:"spec,omitempty"`
	Status IBMLicenseServiceReporterStatus `json:"status,omitempty"`
}

IBMLicenseServiceReporter is the Schema for the ibmlicenseservicereporters API +kubebuilder:subresource:status +kubebuilder:resource:path=ibmlicenseservicereporters,scope=Namespaced

func (*IBMLicenseServiceReporter) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicenseServiceReporter.

func (*IBMLicenseServiceReporter) DeepCopyInto

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

func (*IBMLicenseServiceReporter) DeepCopyObject

func (in *IBMLicenseServiceReporter) DeepCopyObject() runtime.Object

DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.

type IBMLicenseServiceReporterList

type IBMLicenseServiceReporterList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []IBMLicenseServiceReporter `json:"items"`
}

IBMLicenseServiceReporterList contains a list of IBMLicenseServiceReporter

func (*IBMLicenseServiceReporterList) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicenseServiceReporterList.

func (*IBMLicenseServiceReporterList) DeepCopyInto

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

func (*IBMLicenseServiceReporterList) DeepCopyObject

func (in *IBMLicenseServiceReporterList) DeepCopyObject() runtime.Object

DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.

type IBMLicenseServiceReporterSpec

type IBMLicenseServiceReporterSpec struct {
	// Receiver Settings
	ReceiverContainer Container `json:"receiverContainer,omitempty"`
	// Receiver Settings
	ReporterUIContainer Container `json:"reporterUIContainer,omitempty"`
	// Database Settings
	DatabaseContainer Container `json:"databaseContainer,omitempty"`
	// Common Parameters for operator
	IBMLicenseServiceBaseSpec `json:",inline"`
	// Storage class used by database to provide persistency
	StorageClass string `json:"storageClass,omitempty"`
	// Persistent Volume Claim Capacity
	Capacity resource.Quantity `json:"capacity,omitempty" protobuf:"bytes,2,opt,name=capacity"`
}

IBMLicenseServiceReporterSpec defines the desired state of IBMLicenseServiceReporter

func (*IBMLicenseServiceReporterSpec) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicenseServiceReporterSpec.

func (*IBMLicenseServiceReporterSpec) DeepCopyInto

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

func (*IBMLicenseServiceReporterSpec) FillDefaultValues

func (spec *IBMLicenseServiceReporterSpec) FillDefaultValues(reqLogger logr.Logger, r client_reader.Reader) error

type IBMLicenseServiceReporterStatus

type IBMLicenseServiceReporterStatus struct {
	// Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
	// Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html
	LicensingReporterPods []corev1.PodStatus `json:"LicensingReporterPods"`
}

IBMLicenseServiceReporterStatus defines the observed state of IBMLicenseServiceReporter

func (*IBMLicenseServiceReporterStatus) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicenseServiceReporterStatus.

func (*IBMLicenseServiceReporterStatus) DeepCopyInto

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

type IBMLicenseServiceRouteOptions

type IBMLicenseServiceRouteOptions struct {
	TLS *routev1.TLSConfig `json:"tls,omitempty"`
}

func (*IBMLicenseServiceRouteOptions) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicenseServiceRouteOptions.

func (*IBMLicenseServiceRouteOptions) DeepCopyInto

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

type IBMLicensing

type IBMLicensing struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   IBMLicensingSpec   `json:"spec,omitempty"`
	Status IBMLicensingStatus `json:"status,omitempty"`
}

IBM License Service is the Schema for the ibmlicensings API +kubebuilder:printcolumn:name="Pod Phase",type=string,JSONPath=`.status..phase` +kubebuilder:subresource:status +kubebuilder:resource:path=ibmlicensings,scope=Cluster +operator-sdk:csv:customresourcedefinitions:displayName="IBM License Service" +operator-sdk:csv:customresourcedefinitions:resources={{Service,v1,},{Pod,v1,}} +operator-sdk:csv:customresourcedefinitions:resources={{Deployment,v1,},{Secret,v1,}} +operator-sdk:csv:customresourcedefinitions:resources={{Route,v1,},{ServiceAccount,v1,}} +operator-sdk:csv:customresourcedefinitions:resources={{ClusterRole,v1,},{ClusterRoleBinding,v1,}} +operator-sdk:csv:customresourcedefinitions:resources={{Role,v1,},{RoleBinding,v1,}} +operator-sdk:csv:customresourcedefinitions:resources={{ReplicaSets,v1,},{Ingresses,v1beta1,}} +operator-sdk:csv:customresourcedefinitions:resources={{status,v1alpha1,},{configmaps,v1,}} +operator-sdk:csv:customresourcedefinitions:resources={{ibmlicensings,v1alpha1,},{ibmlicenseservicereporters,v1alpha1,}}

func (*IBMLicensing) DeepCopy

func (in *IBMLicensing) DeepCopy() *IBMLicensing

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicensing.

func (*IBMLicensing) DeepCopyInto

func (in *IBMLicensing) DeepCopyInto(out *IBMLicensing)

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

func (*IBMLicensing) DeepCopyObject

func (in *IBMLicensing) DeepCopyObject() runtime.Object

DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.

type IBMLicensingIngressOptions

type IBMLicensingIngressOptions struct {

	// Path after host where API will be available f.e. https://<hostname>:<port>/ibm-licensing-service-instance
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Path",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	Path *string `json:"path,omitempty"`

	// Additional annotations that should include f.e. ingress class if using not default ingress controller
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Annotations",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	Annotations map[string]string `json:"annotations,omitempty"`

	// TLS Options to enable secure connection
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="TLS",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	TLS []extensionsv1.IngressTLS `json:"tls,omitempty"`

	// If you use non-default host include it here
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Host",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	Host *string `json:"host,omitempty"`
}

func (*IBMLicensingIngressOptions) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicensingIngressOptions.

func (*IBMLicensingIngressOptions) DeepCopyInto

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

type IBMLicensingList

type IBMLicensingList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []IBMLicensing `json:"items"`
}

IBMLicensingList contains a list of IBMLicensing

func (*IBMLicensingList) DeepCopy

func (in *IBMLicensingList) DeepCopy() *IBMLicensingList

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicensingList.

func (*IBMLicensingList) DeepCopyInto

func (in *IBMLicensingList) DeepCopyInto(out *IBMLicensingList)

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

func (*IBMLicensingList) DeepCopyObject

func (in *IBMLicensingList) DeepCopyObject() runtime.Object

DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.

type IBMLicensingRouteOptions

type IBMLicensingRouteOptions struct {

	// TLS Config
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="TLS Config",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	TLS *routev1.TLSConfig `json:"tls,omitempty"`
}

func (*IBMLicensingRouteOptions) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicensingRouteOptions.

func (*IBMLicensingRouteOptions) DeepCopyInto

func (in *IBMLicensingRouteOptions) DeepCopyInto(out *IBMLicensingRouteOptions)

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

type IBMLicensingSecurityContext

type IBMLicensingSecurityContext struct {
	RunAsUser int64 `json:"runAsUser"`
}

func (*IBMLicensingSecurityContext) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicensingSecurityContext.

func (*IBMLicensingSecurityContext) DeepCopyInto

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

type IBMLicensingSenderSpec

type IBMLicensingSenderSpec struct {

	// URL for License Service Reporter receiver that collects and aggregate multi cluster licensing data.
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Reporter URL",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	ReporterURL string `json:"reporterURL,omitempty"`

	// License Service Reporter authentication token, provided by secret that you need to create in instance namespace
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Reporter Secret Token",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	ReporterSecretToken string `json:"reporterSecretToken,omitempty"`

	// What is the name of this reporting cluster in multi-cluster system. If not provided, CLUSTER_ID will be used as CLUSTER_NAME at Operand level
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Cluster Name",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	ClusterName string `json:"clusterName,omitempty"`

	// Unique ID of reporting cluster
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Cluster ID",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	ClusterID string `json:"clusterID,omitempty"`
}

func (*IBMLicensingSenderSpec) DeepCopy

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicensingSenderSpec.

func (*IBMLicensingSenderSpec) DeepCopyInto

func (in *IBMLicensingSenderSpec) DeepCopyInto(out *IBMLicensingSenderSpec)

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

type IBMLicensingSpec

type IBMLicensingSpec struct {

	// Container Settings
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Container Settings",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	Container `json:",inline"`

	// Common Parameters for Operator
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Common Parameters",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	IBMLicenseServiceBaseSpec `json:",inline"`

	// Where should data be collected, options: metering, datacollector
	// +kubebuilder:validation:Enum=metering;datacollector
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Datasource",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	Datasource string `json:"datasource"`

	// Enables https access at pod level, httpsCertsSource needed if true
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="HTTPS Enable",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	HTTPSEnable bool `json:"httpsEnable"`

	// Existing or to be created namespace where application will start. In case metering data collection is used,
	// should be the same namespace as metering components
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Instance Namespace",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	InstanceNamespace string `json:"instanceNamespace,omitempty"`

	// If default SCC user ID fails, you can set runAsUser option to fix that
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Security Context",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	SecurityContext *IBMLicensingSecurityContext `json:"securityContext,omitempty"`

	// Should Route be created to expose IBM Licensing Service API? (only on OpenShift cluster)
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Route Enabled",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	RouteEnabled *bool `json:"routeEnabled,omitempty"`

	// Is Red Had Marketplace enabled
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="RHMP Enabled",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	RHMPEnabled *bool `json:"rhmpEnabled,omitempty"`

	// Should collect usage based metrics?
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Usage Enabled",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch"
	// +optional
	UsageEnabled bool `json:"usageEnabled,omitempty"`

	// Usage Container Settings
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Usage Container Settings",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	UsageContainer Container `json:"usageContainer,omitempty"`

	// Consider updating to enable chargeback feature
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Chargeback Enabled",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	ChargebackEnabled *bool `json:"chargebackEnabled,omitempty"`

	// Chargeback data retention period in days. Default value is 62 days.
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Chargeback Retention Period in days",xDescriptors="urn:alm:descriptor:com.tectonic.ui:number"
	// +optional
	ChargebackRetentionPeriod *int `json:"chargebackRetentionPeriod,omitempty"`

	// Should Ingress be created to expose IBM Licensing Service API?
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Ingress Enabled",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	IngressEnabled *bool `json:"ingressEnabled,omitempty"`

	// If ingress is enabled, you can set its parameters
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Ingress Options",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	IngressOptions *IBMLicensingIngressOptions `json:"ingressOptions,omitempty"`

	// Sender configuration, set if you have multi-cluster environment from which you collect data
	// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Sender",xDescriptors="urn:alm:descriptor:com.tectonic.ui:text"
	// +optional
	Sender *IBMLicensingSenderSpec `json:"sender,omitempty"`
}

IBMLicensingSpec defines the desired state of IBMLicensing

func (*IBMLicensingSpec) DeepCopy

func (in *IBMLicensingSpec) DeepCopy() *IBMLicensingSpec

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicensingSpec.

func (*IBMLicensingSpec) DeepCopyInto

func (in *IBMLicensingSpec) DeepCopyInto(out *IBMLicensingSpec)

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

func (*IBMLicensingSpec) FillDefaultValues

func (spec *IBMLicensingSpec) FillDefaultValues(isOCP4CertManager bool, isRouteEnabled bool, rhmpEnabled bool,
	operatorNamespace string) error

func (*IBMLicensingSpec) GetDefaultReporterTokenName

func (spec *IBMLicensingSpec) GetDefaultReporterTokenName() string

func (*IBMLicensingSpec) IsChargebackEnabled

func (spec *IBMLicensingSpec) IsChargebackEnabled() bool

func (*IBMLicensingSpec) IsDebug

func (spec *IBMLicensingSpec) IsDebug() bool

func (*IBMLicensingSpec) IsIngressEnabled

func (spec *IBMLicensingSpec) IsIngressEnabled() bool

func (*IBMLicensingSpec) IsMetering

func (spec *IBMLicensingSpec) IsMetering() bool

func (*IBMLicensingSpec) IsRHMPEnabled

func (spec *IBMLicensingSpec) IsRHMPEnabled() bool

func (*IBMLicensingSpec) IsRouteEnabled

func (spec *IBMLicensingSpec) IsRouteEnabled() bool

func (*IBMLicensingSpec) RemoveDefaultSenderParameters

func (spec *IBMLicensingSpec) RemoveDefaultSenderParameters() bool

func (*IBMLicensingSpec) SetDefaultSenderParameters

func (spec *IBMLicensingSpec) SetDefaultSenderParameters() bool

type IBMLicensingStatus

type IBMLicensingStatus struct {
	// The status of IBM License Service Pods.
	LicensingPods []corev1.PodStatus `json:"licensingPods"`
}

IBMLicensingStatus defines the observed state of IBMLicensing

func (*IBMLicensingStatus) DeepCopy

func (in *IBMLicensingStatus) DeepCopy() *IBMLicensingStatus

DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IBMLicensingStatus.

func (*IBMLicensingStatus) DeepCopyInto

func (in *IBMLicensingStatus) DeepCopyInto(out *IBMLicensingStatus)

DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.

Jump to

Keyboard shortcuts

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