k8s

package
v1.5.2-rc1 Latest Latest
Warning

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

Go to latest
Published: May 17, 2019 License: Apache-2.0 Imports: 54 Imported by: 0

Documentation

Overview

Package k8s abstracts all Kubernetes specific behaviour

Package k8s abstracts all Kubernetes specific behaviour

Package k8s abstracts all Kubernetes specific behaviour

Index

Constants

View Source
const (
	// BackOffLoopTimeout is the default duration when trying to reach the
	// kube-apiserver.
	BackOffLoopTimeout = 2 * time.Minute

	// EnvNodeNameSpec is the environment label used by Kubernetes to
	// specify the node's name.
	EnvNodeNameSpec = "K8S_NODE_NAME"
)
View Source
const (
	// AnnotationIstioSidecarStatus is the annotation added by Istio into a pod
	// when it is injected with a sidecar proxy.
	// Since Istio 0.5.0, the value of this annotation is a serialized JSON object
	// with the following structure ("imagePullSecrets" was added in Istio 0.8.0):
	//
	//     {
	//         "version": "0213afe1274259d2f23feb4820ad2f8eb8609b84a5538e5f51f711545b6bde88",
	//         "initContainers": ["sleep", "istio-init"],
	//         "containers": ["istio-proxy"],
	//         "volumes": ["cilium-unix-sock-dir", "istio-envoy", "istio-certs"],
	//         "imagePullSecrets": null
	//     }
	AnnotationIstioSidecarStatus = "sidecar.istio.io/status"

	// DefaultSidecarIstioProxyImageRegexp is the default regexp compiled into
	// SidecarIstioProxyImageRegexp.
	DefaultSidecarIstioProxyImageRegexp = "cilium/istio_proxy"
)
View Source
const (
	// maximum number of operations a single json patch may contain.
	// See https://github.com/kubernetes/kubernetes/pull/74000
	MaxJSONPatchOperations = 10000
)

Variables

View Source
var (
	// ErrNilNode is returned when the Kubernetes API server has returned a nil node
	ErrNilNode = goerrors.New("API server returned nil node")
)
View Source
var (
	// SidecarIstioProxyImageRegexp is the regular expression matching
	// compatible Istio sidecar istio-proxy container image names.
	// This is set by the "sidecar-istio-proxy-image" configuration flag.
	SidecarIstioProxyImageRegexp = regexp.MustCompile(DefaultSidecarIstioProxyImageRegexp)
)

Functions

func Configure added in v1.5.0

func Configure(apiServer, kubeconfigPath string)

Configure sets the parameters of the Kubernetes package

func ConvertToCNP added in v1.5.0

func ConvertToCNP(obj interface{}) interface{}

ConvertToCNP converts a *cilium_v2.CiliumNetworkPolicy into a *types.SlimCNP without the Status field of the given CNP. WARNING calling this function will set *all* fields of the given CNP as empty.

func ConvertToCNPWithStatus added in v1.5.0

func ConvertToCNPWithStatus(obj interface{}) interface{}

ConvertToCNPWithStatus converts a *cilium_v2.CiliumNetworkPolicy into a *types.SlimCNP

func ConvertToIngress added in v1.5.0

func ConvertToIngress(obj interface{}) interface{}

ConvertToIngress converts a *v1beta1.Ingress into a *v1beta1.Ingress

func ConvertToK8sEndpoints added in v1.5.0

func ConvertToK8sEndpoints(obj interface{}) interface{}

ConvertToK8sEndpoints converts a *v1.Endpoints into a *types.Endpoints

func ConvertToK8sService added in v1.5.0

func ConvertToK8sService(obj interface{}) interface{}

ConvertToK8sService converts a *v1.Service into a *types.Service

func ConvertToNamespace added in v1.5.0

func ConvertToNamespace(obj interface{}) interface{}

ConvertToNamespace converts a *v1.Namespace into a *types.Namespace. WARNING calling this function will set *all* fields of the given Namespace as empty.

func ConvertToNetworkPolicy added in v1.5.0

func ConvertToNetworkPolicy(obj interface{}) interface{}

ConvertToNetworkPolicy converts a *networkingv1.NetworkPolicy into a *types.NetworkPolicy

func ConvertToNode added in v1.5.0

func ConvertToNode(obj interface{}) interface{}

ConvertToNode converts a *v1.Node into a *types.Node. WARNING calling this function will set *all* fields of the given Node as empty.

func ConvertToPod added in v1.5.0

func ConvertToPod(obj interface{}) interface{}

ConvertToPod converts a *v1.Pod into a *types.Pod. WARNING calling this function will set *all* fields of the given Pod as empty.

func CopyObjToV1Endpoints added in v1.5.0

func CopyObjToV1Endpoints(obj interface{}) *types.Endpoints

func CopyObjToV1Namespace added in v1.5.0

func CopyObjToV1Namespace(obj interface{}) *types.Namespace

func CopyObjToV1NetworkPolicy added in v1.5.0

func CopyObjToV1NetworkPolicy(obj interface{}) *types.NetworkPolicy

func CopyObjToV1Node added in v1.5.0

func CopyObjToV1Node(obj interface{}) *types.Node

func CopyObjToV1Pod added in v1.5.0

func CopyObjToV1Pod(obj interface{}) *types.Pod

func CopyObjToV1Services added in v1.5.0

func CopyObjToV1Services(obj interface{}) *types.Service

func CopyObjToV1beta1Ingress added in v1.5.0

func CopyObjToV1beta1Ingress(obj interface{}) *types.Ingress

func CopyObjToV2CNP added in v1.5.0

func CopyObjToV2CNP(obj interface{}) *types.SlimCNP

func CreateClient added in v0.10.0

func CreateClient(config *rest.Config) (*kubernetes.Clientset, error)

CreateClient creates a new client to access the Kubernetes API

func CreateConfig added in v0.10.0

func CreateConfig() (*rest.Config, error)

CreateConfig creates a client configuration based on the configured API server and Kubeconfig path

func CreateConfigFromAgentResponse added in v1.5.0

func CreateConfigFromAgentResponse(resp *models.DaemonConfiguration) (*rest.Config, error)

CreateConfigFromAgentResponse creates a client configuration from a models.DaemonConfigurationResponse

func EqualV1Endpoints added in v1.5.0

func EqualV1Endpoints(ep1, ep2 *types.Endpoints) bool

func EqualV1Namespace added in v1.5.0

func EqualV1Namespace(ns1, ns2 *types.Namespace) bool

func EqualV1NetworkPolicy added in v1.5.0

func EqualV1NetworkPolicy(np1, np2 *types.NetworkPolicy) bool

func EqualV1Node added in v1.5.0

func EqualV1Node(node1, node2 *types.Node) bool

func EqualV1Pod added in v1.5.0

func EqualV1Pod(pod1, pod2 *types.Pod) bool

func EqualV1Services added in v1.5.0

func EqualV1Services(svc1, svc2 *types.Service) bool

func EqualV1beta1Ingress added in v1.5.0

func EqualV1beta1Ingress(ing1, ing2 *types.Ingress) bool

func EqualV2CNP added in v1.5.0

func EqualV2CNP(cnp1, cnp2 *types.SlimCNP) bool

func GetAPIServer added in v1.5.0

func GetAPIServer() string

GetAPIServer returns the configured API server address

func GetKubeconfigPath added in v1.5.0

func GetKubeconfigPath() string

GetKubeconfigPath returns the configured path to the kubeconfig configuration file

func GetNode added in v0.10.0

func GetNode(c kubernetes.Interface, nodeName string) (*v1.Node, error)

GetNode returns the kubernetes nodeName's node information from the kubernetes api server

func GetPodLabels added in v1.5.0

func GetPodLabels(namespace, podName string) (map[string]string, error)

GetPodLabels returns the labels of a pod

func GetPolicyLabelsv1 added in v1.5.0

func GetPolicyLabelsv1(np *networkingv1.NetworkPolicy) labels.LabelArray

GetPolicyLabelsv1 extracts the name of np. It uses the name from the Cilium annotation if present. If the policy's annotations do not contain the Cilium annotation, the policy's name field is used instead.

func Init added in v1.5.0

func Init() error

Init initializes the Kubernetes package. It is required to call Configure() beforehand.

func IsEnabled added in v1.5.0

func IsEnabled() bool

IsEnabled checks if Cilium is being used in tandem with Kubernetes.

func IsErrParse added in v1.5.0

func IsErrParse(e error) bool

IsErrParse returns true if the error is a ErrParse

func K8sErrorHandler added in v1.5.0

func K8sErrorHandler(e error)

K8sErrorHandler handles the error messages in a non verbose way by omitting repeated instances of the same error message for a timeout defined with k8sErrLogTimeout.

func NewClusterService added in v1.5.0

func NewClusterService(id ServiceID, k8sService *Service, k8sEndpoints *Endpoints) service.ClusterService

NewClusterService returns the service.ClusterService representing a Kubernetes Service

func NewInformer added in v1.5.0

func NewInformer(
	lw cache.ListerWatcher,
	objType runtime.Object,
	resyncPeriod time.Duration,
	h cache.ResourceEventHandler,
	convertFunc ConvertFunc,
) (cache.Store, cache.Controller)

NewInformer is a copy of k8s.io/client-go/tools/cache/NewInformer with a new argument which converts an object into another object that can be stored in the local cache.

func NewInformerWithStore added in v1.5.0

func NewInformerWithStore(
	lw cache.ListerWatcher,
	objType runtime.Object,
	resyncPeriod time.Duration,
	h cache.ResourceEventHandler,
	convertFunc ConvertFunc,
	clientState cache.Store,
) cache.Controller

NewInformerWithStore uses the same arguments as NewInformer for which a caller can also set a cache.Store.

func ParseEndpoints added in v1.5.0

func ParseEndpoints(ep *types.Endpoints) (ServiceID, *Endpoints)

ParseEndpoints parses a Kubernetes Endpoints resource

func ParseIngress added in v1.5.0

func ParseIngress(ingress *types.Ingress, host net.IP) (ServiceID, *Service, error)

ParseIngress parses an ingress resources and returns the Service definition

func ParseNetworkPolicy added in v0.10.0

func ParseNetworkPolicy(np *networkingv1.NetworkPolicy) (api.Rules, error)

ParseNetworkPolicy parses a k8s NetworkPolicy. Returns a list of Cilium policy rules that can be added, along with an error if there was an error sanitizing the rules.

func ParseNode added in v0.10.0

func ParseNode(k8sNode *types.Node, source node.Source) *node.Node

ParseNode parses a kubernetes node to a cilium node

func ParseNodeAddressType added in v1.5.0

func ParseNodeAddressType(k8sAddress v1.NodeAddressType) (addressing.AddressType, error)

ParseNodeAddressType converts a Kubernetes NodeAddressType to a Cilium NodeAddressType. If the Kubernetes NodeAddressType does not have a corresponding Cilium AddressType, returns an error.

func ParseService added in v1.5.0

func ParseService(svc *types.Service) (ServiceID, *Service)

ParseService parses a Kubernetes service and returns a Service

func PreprocessRules added in v1.5.0

func PreprocessRules(r api.Rules, cache *ServiceCache) error

PreprocessRules translates rules that apply to headless services

func SetNodeNetworkUnavailableFalse added in v1.5.1

func SetNodeNetworkUnavailableFalse(c kubernetes.Interface, nodeName string) error

SetNodeNetworkUnavailableFalse sets Kubernetes NodeNetworkUnavailable to false as Cilium is managing the network connectivity. https://kubernetes.io/docs/concepts/architecture/nodes/#condition

Types

type CNPStatusUpdateContext added in v1.5.0

type CNPStatusUpdateContext struct {
	// CiliumNPClient is the CiliumNetworkPolicy client
	CiliumNPClient clientset.Interface

	// CiliumV2Store is a store containing all CiliumNetworkPolicy
	CiliumV2Store cache.Store

	// NodeName is the name of the node, it is used to separate status
	// field entries per node
	NodeName string

	// NodeManager implements the backoff.NodeManager interface and is used
	// to provide cluster-size dependent backoff
	NodeManager backoff.NodeManager

	// UpdateDuration must be populated using spanstart.Start() to provide
	// the timestamp of when the status update operation was started. It is
	// used to provide the latency in the Prometheus metrics.
	UpdateDuration *spanstat.SpanStat

	// WaitForEndpointsAtPolicyRev must point to a function that will wait
	// for all local endpoints to reach the particular policy revision
	WaitForEndpointsAtPolicyRev func(ctx context.Context, rev uint64) error
}

CNPStatusUpdateContext is the context required to update the status of a CNP. It is filled out by the owner of the Kubernetes client before UpdateStatus() is called.

func (*CNPStatusUpdateContext) UpdateStatus added in v1.5.0

func (c *CNPStatusUpdateContext) UpdateStatus(ctx context.Context, cnp *types.SlimCNP, rev uint64, policyImportErr error) error

UpdateStatus updates the status section of a CiliumNetworkPolicy. It will retry as long as required to update the status unless a non-temporary error occurs in which case it expects a surrounding controller to restart or give up.

type CacheAction added in v1.5.0

type CacheAction int

CacheAction is the type of action that was performed on the cache

const (
	// UpdateService reflects that the service was updated or added
	UpdateService CacheAction = iota

	// DeleteService reflects that the service was deleted
	DeleteService

	// UpdateIngress reflects that the ingress was updated or added
	UpdateIngress

	// DeleteIngress reflects that the ingress was deleted
	DeleteIngress
)

func (CacheAction) String added in v1.5.0

func (c CacheAction) String() string

String returns the cache action as a string

type ConvertFunc added in v1.5.0

type ConvertFunc func(obj interface{}) interface{}

type Endpoints added in v1.5.0

type Endpoints struct {
	// Backends is a map containing all backend IPs and ports. The key to
	// the map is the backend IP in string form. The value defines the list
	// of ports for that backend IP in the form of a PortConfiguration.
	Backends map[string]service.PortConfiguration
}

Endpoints is an abstraction for the Kubernetes endpoints object. Endpoints consists of a set of backend IPs in combination with a set of ports and protocols. The name of the backend ports must match the names of the frontend ports of the corresponding service.

func (*Endpoints) CIDRPrefixes added in v1.5.0

func (e *Endpoints) CIDRPrefixes() ([]*net.IPNet, error)

CIDRPrefixes returns the endpoint's backends as a slice of IPNets.

func (*Endpoints) DeepEquals added in v1.5.0

func (e *Endpoints) DeepEquals(o *Endpoints) bool

DeepEquals returns true if both endpoints are deep equal.

func (*Endpoints) String added in v1.5.0

func (e *Endpoints) String() string

String returns the string representation of an endpoints resource, with backends and ports sorted.

type ErrParse added in v1.5.0

type ErrParse struct {
	// contains filtered or unexported fields
}

ErrParse is an error to describe where policy fails to parse due any invalid rule.

func (ErrParse) Error added in v1.5.0

func (e ErrParse) Error() string

Error returns the error message for parsing

type FrontendList added in v1.5.0

type FrontendList map[string]struct{}

FrontendList is the list of all k8s service frontends

func (FrontendList) LooseMatch added in v1.5.0

func (l FrontendList) LooseMatch(frontend loadbalancer.L3n4Addr) (exists bool)

LooseMatch returns true if the provided frontend is found in the FrontendList. If the frontend has a protocol value set, it only matches a k8s service with a matching protocol. If no protocol is set, any k8s service matching frontend IP and port is considered a match, regardless of protocol.

type JSONPatch added in v1.5.0

type JSONPatch struct {
	OP    string      `json:"op,omitempty"`
	Path  string      `json:"path,omitempty"`
	Value interface{} `json:"value"`
}

JSONPatch structure based on the RFC 6902

type K8sCiliumClient added in v1.5.0

type K8sCiliumClient struct {
	clientset.Interface
}

K8sCiliumClient is a wrapper around clientset.Interface.

func CiliumClient added in v1.5.0

func CiliumClient() *K8sCiliumClient

CiliumClient returns the default Cilium Kubernetes client.

type K8sClient added in v1.5.0

type K8sClient struct {
	// kubernetes.Interface is the object through which interactions with
	// Kubernetes are performed.
	kubernetes.Interface
}

K8sClient is a wrapper around kubernetes.Interface.

func Client added in v1.5.0

func Client() *K8sClient

Client returns the default Kubernetes client.

func (K8sClient) AnnotateNode added in v1.5.0

func (k8sCli K8sClient) AnnotateNode(nodeName string, v4CIDR, v6CIDR *cidr.CIDR, v4HealthIP, v6HealthIP, v4CiliumHostIP, v6CiliumHostIP net.IP) error

AnnotateNode writes v4 and v6 CIDRs and health IPs in the given k8s node name. In case of failure while updating the node, this function while spawn a go routine to retry the node update indefinitely.

type RuleTranslator added in v1.5.0

type RuleTranslator struct {
	Service       ServiceID
	Endpoint      Endpoints
	ServiceLabels map[string]string
	Revert        bool
	IPCache       ipcache.Implementation
}

RuleTranslator implements pkg/policy.Translator interface Translate populates/depopulates given rule with ToCIDR rules Based on provided service/endpoint

func NewK8sTranslator added in v1.5.0

func NewK8sTranslator(
	serviceInfo ServiceID,
	endpoint Endpoints,
	revert bool,
	labels map[string]string,
	ipcache ipcache.Implementation) RuleTranslator

NewK8sTranslator returns RuleTranslator

func (RuleTranslator) Translate added in v1.5.0

func (k RuleTranslator) Translate(r *api.Rule, result *policy.TranslationResult) error

Translate calls TranslateEgress on all r.Egress rules

func (RuleTranslator) TranslateEgress added in v1.5.0

func (k RuleTranslator) TranslateEgress(r *api.EgressRule, result *policy.TranslationResult) error

TranslateEgress populates/depopulates egress rules with ToCIDR entries based on toService entries

type Service added in v1.5.0

type Service struct {
	FrontendIP net.IP
	IsHeadless bool

	// IncludeExternal is true when external endpoints from other clusters
	// should be included
	IncludeExternal bool

	// Shared is true when the service should be exposed/shared to other clusters
	Shared bool

	Ports    map[loadbalancer.FEPortName]*loadbalancer.FEPort
	Labels   map[string]string
	Selector map[string]string
}

Service is an abstraction for a k8s service that is composed by the frontend IP address (FEIP) and the map of the frontend ports (Ports).

func NewService added in v1.5.0

func NewService(ip net.IP, headless bool, labels map[string]string, selector map[string]string) *Service

NewService returns a new Service with the Ports map initialized.

func (*Service) DeepEquals added in v1.5.0

func (s *Service) DeepEquals(o *Service) bool

DeepEquals returns true if both services are equal

func (Service) IsExternal added in v1.5.0

func (s Service) IsExternal() bool

IsExternal returns true if the service is expected to serve out-of-cluster endpoints:

func (*Service) String added in v1.5.0

func (s *Service) String() string

String returns the string representation of a service resource

func (*Service) UniquePorts added in v1.5.0

func (s *Service) UniquePorts() map[uint16]bool

UniquePorts returns a map of all unique ports configured in the service

type ServiceCache added in v1.5.0

type ServiceCache struct {
	Events chan ServiceEvent
	// contains filtered or unexported fields
}

ServiceCache is a list of services and ingresses correlated with the matching endpoints. The Events member will receive events as services and ingresses

func NewServiceCache added in v1.5.0

func NewServiceCache() ServiceCache

NewServiceCache returns a new ServiceCache

func (*ServiceCache) DebugStatus added in v1.5.0

func (s *ServiceCache) DebugStatus() string

DebugStatus implements debug.StatusObject to provide debug status collection ability

func (*ServiceCache) DeleteEndpoints added in v1.5.0

func (s *ServiceCache) DeleteEndpoints(k8sEndpoints *types.Endpoints) ServiceID

DeleteEndpoints parses a Kubernetes endpoints and removes it from the ServiceCache

func (*ServiceCache) DeleteIngress added in v1.5.0

func (s *ServiceCache) DeleteIngress(ingress *types.Ingress)

DeleteIngress parses a Kubernetes ingress and removes it from the ServiceCache

func (*ServiceCache) DeleteService added in v1.5.0

func (s *ServiceCache) DeleteService(k8sSvc *types.Service)

DeleteService parses a Kubernetes service and removes it from the ServiceCache

func (*ServiceCache) GetRandomBackendIP added in v1.5.0

func (s *ServiceCache) GetRandomBackendIP(svcID ServiceID) *loadbalancer.L3n4Addr

GetRandomBackendIP returns a random L3n4Addr that is backing the given Service ID.

func (*ServiceCache) MergeExternalServiceDelete added in v1.5.0

func (s *ServiceCache) MergeExternalServiceDelete(service *service.ClusterService)

MergeExternalServiceDelete merges the deletion of a cluster service in a remote cluster into the local service cache. The service endpoints are stored as external endpoints and are correlated on demand with local services via correlateEndpoints().

func (*ServiceCache) MergeExternalServiceUpdate added in v1.5.0

func (s *ServiceCache) MergeExternalServiceUpdate(service *service.ClusterService)

MergeExternalServiceUpdate merges a cluster service of a remote cluster into the local service cache. The service endpoints are stored as external endpoints and are correlated on demand with local services via correlateEndpoints().

func (*ServiceCache) UniqueServiceFrontends added in v1.5.0

func (s *ServiceCache) UniqueServiceFrontends() FrontendList

UniqueServiceFrontends returns all services known to the service cache as a map, indexed by the string representation of a loadbalancer.L3n4Addr

func (*ServiceCache) UpdateEndpoints added in v1.5.0

func (s *ServiceCache) UpdateEndpoints(k8sEndpoints *types.Endpoints) (ServiceID, *Endpoints)

UpdateEndpoints parses a Kubernetes endpoints and adds or updates it in the ServiceCache. Returns the ServiceID unless the Kubernetes endpoints could not be parsed and a bool to indicate whether the endpoints was changed in the cache or not.

func (*ServiceCache) UpdateIngress added in v1.5.0

func (s *ServiceCache) UpdateIngress(ingress *types.Ingress, host net.IP) (ServiceID, error)

UpdateIngress parses a Kubernetes ingress and adds or updates it in the ServiceCache.

func (*ServiceCache) UpdateService added in v1.5.0

func (s *ServiceCache) UpdateService(k8sSvc *types.Service) ServiceID

UpdateService parses a Kubernetes service and adds or updates it in the ServiceCache. Returns the ServiceID unless the Kubernetes service could not be parsed and a bool to indicate whether the service was changed in the cache or not.

type ServiceEvent added in v1.5.0

type ServiceEvent struct {
	// Action is the action that was performed in the cache
	Action CacheAction

	// ID is the identified of the service
	ID ServiceID

	// Service is the service structure
	Service *Service

	// Endpoints is the endpoints structured correlated with the service
	Endpoints *Endpoints
}

ServiceEvent is emitted via the Events channel of ServiceCache and describes the change that occurred in the cache

type ServiceID added in v1.5.0

type ServiceID struct {
	Name      string `json:"serviceName,omitempty"`
	Namespace string `json:"namespace,omitempty"`
}

ServiceID identities the Kubernetes service

func ParseEndpointsID added in v1.5.0

func ParseEndpointsID(svc *types.Endpoints) ServiceID

ParseEndpointsID parses a Kubernetes endpoints and returns the ServiceID

func ParseIngressID added in v1.5.0

func ParseIngressID(svc *types.Ingress) ServiceID

ParseIngressID parses the service ID from the ingress resource

func ParseServiceID added in v1.5.0

func ParseServiceID(svc *types.Service) ServiceID

ParseServiceID parses a Kubernetes service and returns the ServiceID

func ParseServiceIDFrom added in v1.5.0

func ParseServiceIDFrom(dn string) *ServiceID

ParseServiceIDFrom returns a ServiceID derived from the given kubernetes service FQDN.

func (ServiceID) String added in v1.5.0

func (s ServiceID) String() string

String returns the string representation of a service ID

Directories

Path Synopsis
apis
cilium.io/v2
Package v2 is the v2 version of the API.
Package v2 is the v2 version of the API.
client
clientset/versioned
This package has the automatically generated clientset.
This package has the automatically generated clientset.
clientset/versioned/fake
This package has the automatically generated fake clientset.
This package has the automatically generated fake clientset.
clientset/versioned/scheme
This package contains the scheme of the automatically generated clientset.
This package contains the scheme of the automatically generated clientset.
clientset/versioned/typed/cilium.io/v2
This package has the automatically generated typed clients.
This package has the automatically generated typed clients.
clientset/versioned/typed/cilium.io/v2/fake
Package fake has the automatically generated clients.
Package fake has the automatically generated clients.
Package types contains slimmer versions of k8s types.
Package types contains slimmer versions of k8s types.
Package version keeps track of the Kubernetes version the client is connected to
Package version keeps track of the Kubernetes version the client is connected to

Jump to

Keyboard shortcuts

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