v1alpha1

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2018 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package v1alpha1 is the v1alpha1 version of the API. +k8s:deepcopy-gen=package +groupName=eventing.knative.dev

Index

Constants

View Source
const (
	// ChannelConditionReady has status True when the Channel is ready to
	// accept traffic.
	ChannelConditionReady = duckv1alpha1.ConditionReady

	// ChannelConditionProvisioned has status True when the Channel's
	// backing resources have been provisioned.
	ChannelConditionProvisioned duckv1alpha1.ConditionType = "Provisioned"

	// ChannelConditionAddressable has status true when this Channel meets
	// the Addressable contract and has a non-empty hostname.
	ChannelConditionAddressable duckv1alpha1.ConditionType = "Addressable"
)
View Source
const (
	// SubscriptionConditionReady has status True when all subconditions below have been set to True.
	SubscriptionConditionReady = duckv1alpha1.ConditionReady

	// SubscriptionConditionReferencesResolved has status True when all the specified references have been successfully
	// resolved.
	SubscriptionConditionReferencesResolved duckv1alpha1.ConditionType = "Resolved"

	// SubscriptionConditionChannelReady has status True when controller has successfully added a
	// subscription to the spec.channel resource.
	SubscriptionConditionChannelReady duckv1alpha1.ConditionType = "ChannelReady"
)
View Source
const (
	// ClusterChannelProvisionerConditionReady has status True when the Controller reconciling objects
	// controlled by it is ready to control them.
	ClusterChannelProvisionerConditionReady = duckv1alpha1.ConditionReady
)

Variables

View Source
var (
	SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
	AddToScheme   = SchemeBuilder.AddToScheme
)
View Source
var SchemeGroupVersion = schema.GroupVersion{Group: eventing.GroupName, Version: "v1alpha1"}

SchemeGroupVersion is group version used to register these objects

Functions

func Kind

func Kind(kind string) schema.GroupKind

Kind takes an unqualified kind and returns back a Group qualified GroupKind

func Resource

func Resource(resource string) schema.GroupResource

Resource takes an unqualified resource and returns a Group qualified GroupResource

Types

type Channel

type Channel struct {
	metav1.TypeMeta `json:",inline"`
	// +optional
	metav1.ObjectMeta `json:"metadata,omitempty"`

	// Spec defines the desired state of the Channel.
	Spec ChannelSpec `json:"spec,omitempty"`

	// Status represents the current state of the Channel. This data may be out of
	// date.
	// +optional
	Status ChannelStatus `json:"status,omitempty"`
}

Channel is an abstract resource that implements the Addressable contract. The Provisioner provisions infrastructure to accepts events and deliver to Subscriptions.

func (*Channel) CheckImmutableFields

func (current *Channel) CheckImmutableFields(og apis.Immutable) *apis.FieldError

func (*Channel) DeepCopy

func (in *Channel) DeepCopy() *Channel

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

func (*Channel) DeepCopyInto

func (in *Channel) DeepCopyInto(out *Channel)

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

func (*Channel) DeepCopyObject

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

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

func (*Channel) SetDefaults

func (c *Channel) SetDefaults()

TODO replace this with openapi defaults when https://github.com/kubernetes/features/issues/575 lands (scheduled for 1.13)

func (*Channel) Validate

func (c *Channel) Validate() *apis.FieldError

type ChannelList

type ChannelList struct {
	metav1.TypeMeta `json:",inline"`
	// +optional
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []Channel `json:"items"`
}

ChannelList is a collection of Channels.

func (*ChannelList) DeepCopy

func (in *ChannelList) DeepCopy() *ChannelList

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

func (*ChannelList) DeepCopyInto

func (in *ChannelList) DeepCopyInto(out *ChannelList)

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

func (*ChannelList) DeepCopyObject

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

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

type ChannelSpec

type ChannelSpec struct {
	// TODO: Generation does not work correctly with CRD. They are scrubbed
	// by the APIserver (https://github.com/kubernetes/kubernetes/issues/58778)
	// So, we add Generation here. Once that gets fixed, remove this and use
	// ObjectMeta.Generation instead.
	// +optional
	Generation int64 `json:"generation,omitempty"`

	// Provisioner defines the name of the Provisioner backing this channel.
	Provisioner *corev1.ObjectReference `json:"provisioner,omitempty"`

	// Arguments defines the arguments to pass to the Provisioner which
	// provisions this Channel.
	// +optional
	Arguments *runtime.RawExtension `json:"arguments,omitempty"`

	// Channel conforms to Duck type Subscribable.
	Subscribable *eventingduck.Subscribable `json:"subscribable,omitempty"`
}

ChannelSpec specifies the Provisioner backing a channel and the configuration arguments for a Channel.

func (*ChannelSpec) DeepCopy

func (in *ChannelSpec) DeepCopy() *ChannelSpec

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

func (*ChannelSpec) DeepCopyInto

func (in *ChannelSpec) DeepCopyInto(out *ChannelSpec)

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

func (*ChannelSpec) SetDefaults

func (fs *ChannelSpec) SetDefaults()

func (*ChannelSpec) Validate

func (cs *ChannelSpec) Validate() *apis.FieldError

type ChannelStatus

type ChannelStatus struct {
	// ObservedGeneration is the most recent generation observed for this Channel.
	// It corresponds to the Channel's generation, which is updated on mutation by
	// the API Server.
	// TODO: The above comment is only true once
	// https://github.com/kubernetes/kubernetes/issues/58778 is fixed.
	// +optional
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`

	// Channel is Addressable. It currently exposes the endpoint as a
	// fully-qualified DNS name which will distribute traffic over the
	// provided targets from inside the cluster.
	//
	// It generally has the form {channel}.{namespace}.svc.cluster.local
	Address duckv1alpha1.Addressable `json:"address,omitempty"`

	// Represents the latest available observations of a channel's current state.
	// +optional
	// +patchMergeKey=type
	// +patchStrategy=merge
	Conditions duckv1alpha1.Conditions `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
}

ChannelStatus represents the current state of a Channel.

func (*ChannelStatus) DeepCopy

func (in *ChannelStatus) DeepCopy() *ChannelStatus

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

func (*ChannelStatus) DeepCopyInto

func (in *ChannelStatus) DeepCopyInto(out *ChannelStatus)

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

func (*ChannelStatus) GetCondition

GetCondition returns the condition currently associated with the given type, or nil.

func (*ChannelStatus) InitializeConditions

func (cs *ChannelStatus) InitializeConditions()

InitializeConditions sets relevant unset conditions to Unknown state.

func (*ChannelStatus) IsReady

func (cs *ChannelStatus) IsReady() bool

IsReady returns true if the resource is ready overall.

func (*ChannelStatus) MarkNotProvisioned

func (cs *ChannelStatus) MarkNotProvisioned(reason, messageFormat string, messageA ...interface{})

MarkNotProvisioned sets ChannelConditionProvisioned condition to False state.

func (*ChannelStatus) MarkProvisioned

func (cs *ChannelStatus) MarkProvisioned()

MarkProvisioned sets ChannelConditionProvisioned condition to True state.

func (*ChannelStatus) SetAddress

func (cs *ChannelStatus) SetAddress(hostname string)

SetAddress makes this Channel addressable by setting the hostname. It also sets the ChannelConditionAddressable to true.

type ClusterChannelProvisioner

type ClusterChannelProvisioner struct {
	metav1.TypeMeta `json:",inline"`
	// +optional
	metav1.ObjectMeta `json:"metadata,omitempty"`

	// Spec defines the Types provisioned by this Provisioner.
	Spec ClusterChannelProvisionerSpec `json:"spec"`

	// Status is the current status of the Provisioner.
	// +optional
	Status ClusterChannelProvisionerStatus `json:"status,omitempty"`
}

ClusterChannelProvisioner encapsulates a provisioning strategy for the backing resources required to realize a particular resource type.

func (*ClusterChannelProvisioner) DeepCopy

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

func (*ClusterChannelProvisioner) DeepCopyInto

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

func (*ClusterChannelProvisioner) DeepCopyObject

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

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

func (*ClusterChannelProvisioner) SetDefaults

func (p *ClusterChannelProvisioner) SetDefaults()

SetDefaults defaults

func (*ClusterChannelProvisioner) Validate

func (p *ClusterChannelProvisioner) Validate() *apis.FieldError

Validate validates the ClusterChannelProvisioner resource.

type ClusterChannelProvisionerList

type ClusterChannelProvisionerList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []ClusterChannelProvisioner `json:"items"`
}

ClusterChannelProvisionerList is a list of ClusterChannelProvisioner resources

func (*ClusterChannelProvisionerList) DeepCopy

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

func (*ClusterChannelProvisionerList) DeepCopyInto

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

func (*ClusterChannelProvisionerList) DeepCopyObject

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

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

type ClusterChannelProvisionerSpec

type ClusterChannelProvisionerSpec struct {
	// TODO: Generation does not work correctly with CRD. They are scrubbed
	// by the APIserver (https://github.com/kubernetes/kubernetes/issues/58778)
	// So, we add Generation here. Once that gets fixed, remove this and use
	// ObjectMeta.Generation instead.
	// +optional
	Generation int64 `json:"generation,omitempty"`
}

ClusterChannelProvisionerSpec is the spec for a ClusterChannelProvisioner resource.

func (*ClusterChannelProvisionerSpec) DeepCopy

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

func (*ClusterChannelProvisionerSpec) DeepCopyInto

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

func (*ClusterChannelProvisionerSpec) SetDefaults

func (ps *ClusterChannelProvisionerSpec) SetDefaults()

SetDefaults defaults the ClusterChannelProvisioner spec.

func (*ClusterChannelProvisionerSpec) Validate

Validate validates the ClusterChannelProvisioner spec

type ClusterChannelProvisionerStatus

type ClusterChannelProvisionerStatus struct {
	// Conditions holds the state of a cluster provisioner at a point in time.
	// +optional
	// +patchMergeKey=type
	// +patchStrategy=merge
	Conditions duckv1alpha1.Conditions `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`

	// ObservedGeneration is the 'Generation' of the ClusterChannelProvisioner that
	// was last reconciled by the controller.
	// +optional
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}

ClusterChannelProvisionerStatus is the status for a ClusterChannelProvisioner resource

func (*ClusterChannelProvisionerStatus) DeepCopy

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

func (*ClusterChannelProvisionerStatus) DeepCopyInto

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

func (*ClusterChannelProvisionerStatus) GetCondition

GetCondition returns the condition currently associated with the given type, or nil.

func (*ClusterChannelProvisionerStatus) InitializeConditions

func (ps *ClusterChannelProvisionerStatus) InitializeConditions()

InitializeConditions sets relevant unset conditions to Unknown state.

func (*ClusterChannelProvisionerStatus) IsReady

func (ps *ClusterChannelProvisionerStatus) IsReady() bool

IsReady returns true if the resource is ready overall.

func (*ClusterChannelProvisionerStatus) MarkNotReady

func (ps *ClusterChannelProvisionerStatus) MarkNotReady(reason, messageFormat string, messageA ...interface{})

MarkProvisionerNotReady sets the condition that the provisioner is not ready to provision backing resource.

func (*ClusterChannelProvisionerStatus) MarkReady

func (ps *ClusterChannelProvisionerStatus) MarkReady()

MarkReady marks this ClusterChannelProvisioner as Ready=true.

Note that this is not the normal pattern for duck conditions, but because there is (currently) no other condition on ClusterChannelProvisioners, the normal IsReady() logic doesn't work well.

type ReplyStrategy

type ReplyStrategy struct {
	// This object must be a Channel.
	//
	// You can specify only the following fields of the ObjectReference:
	//   - Kind
	//   - APIVersion
	//   - Name
	// Kind must be "Channel" and APIVersion must be
	// "eventing.knative.dev/v1alpha1"
	// +optional
	Channel *corev1.ObjectReference `json:"channel,omitempty"`
}

ReplyStrategy specifies the handling of the SubscriberSpec's returned replies. If no SubscriberSpec is specified, the identity function is assumed.

func (*ReplyStrategy) DeepCopy

func (in *ReplyStrategy) DeepCopy() *ReplyStrategy

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

func (*ReplyStrategy) DeepCopyInto

func (in *ReplyStrategy) DeepCopyInto(out *ReplyStrategy)

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

type SubscriberSpec

type SubscriberSpec struct {

	// Reference to an object that will be used to find the target
	// endpoint, which should implement the Addressable duck type.
	// For example, this could be a reference to a Route resource
	// or a Knative Service resource.
	// TODO: Specify the required fields the target object must
	// have in the status.
	// You can specify only the following fields of the ObjectReference:
	//   - Kind
	//   - APIVersion
	//   - Name
	// +optional
	Ref *corev1.ObjectReference `json:"ref,omitempty"`

	// Reference to a 'known' endpoint where no resolving is done.
	// http://k8s-service for example
	// http://myexternalhandler.example.com/foo/bar
	// +optional
	DNSName *string `json:"dnsName,omitempty"`
}

SubscriberSpec specifies the reference to an object that's expected to provide the resolved target of the action. Currently we inspect the objects Status and see if there's a predefined Status field that we will then use to dispatch events to be processed by the target. Currently must resolve to a k8s service or Istio virtual service. Note that in the future we should try to utilize subresources (/resolve ?) to make this cleaner, but CRDs do not support subresources yet, so we need to rely on a specified Status field today. By relying on this behaviour we can utilize a dynamic client instead of having to understand all kinds of different types of objects. As long as they adhere to this particular contract, they can be used as a Target.

This ensures that we can support external targets and for ease of use we also allow for an URI to be specified. There of course is also a requirement for the resolved SubscriberSpec to behave properly at the data plane level. TODO: Add a pointer to a real spec for this. For now, this means: Receive an event payload, and respond with one of: success and an optional response event, or failure. Delivery failures may be retried by the channel

func (*SubscriberSpec) DeepCopy

func (in *SubscriberSpec) DeepCopy() *SubscriberSpec

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

func (*SubscriberSpec) DeepCopyInto

func (in *SubscriberSpec) DeepCopyInto(out *SubscriberSpec)

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

type Subscription

type Subscription struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              SubscriptionSpec   `json:"spec"`
	Status            SubscriptionStatus `json:"status,omitempty"`
}

Subscription routes events received on a Channel to a DNS name and corresponds to the subscriptions.channels.knative.dev CRD.

func (*Subscription) CheckImmutableFields

func (current *Subscription) CheckImmutableFields(og apis.Immutable) *apis.FieldError

func (*Subscription) DeepCopy

func (in *Subscription) DeepCopy() *Subscription

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

func (*Subscription) DeepCopyInto

func (in *Subscription) DeepCopyInto(out *Subscription)

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

func (*Subscription) DeepCopyObject

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

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

func (*Subscription) SetDefaults

func (s *Subscription) SetDefaults()

func (*Subscription) Validate

func (s *Subscription) Validate() *apis.FieldError

type SubscriptionList

type SubscriptionList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []Subscription `json:"items"`
}

SubscriptionList returned in list operations

func (*SubscriptionList) DeepCopy

func (in *SubscriptionList) DeepCopy() *SubscriptionList

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

func (*SubscriptionList) DeepCopyInto

func (in *SubscriptionList) DeepCopyInto(out *SubscriptionList)

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

func (*SubscriptionList) DeepCopyObject

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

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

type SubscriptionSpec

type SubscriptionSpec struct {
	// TODO: Generation used to not work correctly with CRD. They were scrubbed
	// by the APIserver (https://github.com/kubernetes/kubernetes/issues/58778)
	// So, we add Generation here. Once the above bug gets rolled out to production
	// clusters, remove this and use ObjectMeta.Generation instead.
	// +optional
	Generation int64 `json:"generation,omitempty"`

	// Reference to a channel that will be used to create the subscription
	// for receiving events. The channel must have spec.subscriptions
	// list which will then be modified accordingly.
	//
	// You can specify only the following fields of the ObjectReference:
	//   - Kind
	//   - APIVersion
	//   - Name
	// Kind must be "Channel" and APIVersion must be
	// "eventing.knative.dev/v1alpha1"
	//
	// This field is immutable. We have no good answer on what happens to
	// the events that are currently in the channel being consumed from
	// and what the semantics there should be. For now, you can always
	// delete the Subscription and recreate it to point to a different
	// channel, giving the user more control over what semantics should
	// be used (drain the channel first, possibly have events dropped,
	// etc.)
	Channel corev1.ObjectReference `json:"channel"`

	// Subscriber is reference to (optional) function for processing events.
	// Events from the Channel will be delivered here and replies are
	// sent to a channel as specified by the Reply.
	// +optional
	Subscriber *SubscriberSpec `json:"subscriber,omitempty"`

	// Reply specifies (optionally) how to handle events returned from
	// the Subscriber target.
	// +optional
	Reply *ReplyStrategy `json:"reply,omitempty"`
}

SubscriptionSpec specifies the Channel for incoming events, a Subscriber target for processing those events and where to put the result of the processing. Only From (where the events are coming from) is always required. You can optionally only Process the events (results in no output events) by leaving out the Result. You can also perform an identity transformation on the invoming events by leaving out the Subscriber and only specifying Result.

The following are all valid specifications: channel --[subscriber]--> reply Sink, no outgoing events: channel -- subscriber no-op function (identity transformation): channel --> reply

func (*SubscriptionSpec) DeepCopy

func (in *SubscriptionSpec) DeepCopy() *SubscriptionSpec

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

func (*SubscriptionSpec) DeepCopyInto

func (in *SubscriptionSpec) DeepCopyInto(out *SubscriptionSpec)

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

func (*SubscriptionSpec) SetDefaults

func (ss *SubscriptionSpec) SetDefaults()

func (*SubscriptionSpec) Validate

func (ss *SubscriptionSpec) Validate() *apis.FieldError

We require always Channel Also at least one of 'subscriber' and 'reply' must be defined (non-nill and non-empty)

type SubscriptionStatus

type SubscriptionStatus struct {
	// Represents the latest available observations of a subscription's current state.
	// +patchMergeKey=type
	// +patchStrategy=merge
	Conditions duckv1alpha1.Conditions `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`

	// PhysicalSubscription is the fully resolved values that this Subscription represents.
	PhysicalSubscription SubscriptionStatusPhysicalSubscription `json:"physicalSubscription,omitEmpty"`
}

SubscriptionStatus (computed) for a subscription

func (*SubscriptionStatus) DeepCopy

func (in *SubscriptionStatus) DeepCopy() *SubscriptionStatus

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

func (*SubscriptionStatus) DeepCopyInto

func (in *SubscriptionStatus) DeepCopyInto(out *SubscriptionStatus)

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

func (*SubscriptionStatus) GetCondition

GetCondition returns the condition currently associated with the given type, or nil.

func (*SubscriptionStatus) InitializeConditions

func (ss *SubscriptionStatus) InitializeConditions()

InitializeConditions sets relevant unset conditions to Unknown state.

func (*SubscriptionStatus) IsReady

func (ss *SubscriptionStatus) IsReady() bool

IsReady returns true if the resource is ready overall.

func (*SubscriptionStatus) MarkChannelReady

func (ss *SubscriptionStatus) MarkChannelReady()

MarkChannelReady sets the ChannelReady condition to True state.

func (*SubscriptionStatus) MarkReferencesResolved

func (ss *SubscriptionStatus) MarkReferencesResolved()

MarkReferencesResolved sets the ReferencesResolved condition to True state.

type SubscriptionStatusPhysicalSubscription

type SubscriptionStatusPhysicalSubscription struct {
	// SubscriberURI is the fully resolved URI for spec.subscriber.
	SubscriberURI string `json:"subscriberURI,omitEmpty"`

	// ReplyURI is the fully resolved URI for the spec.reply.
	ReplyURI string `json:"replyURI,omitEmpty"`
}

SubscriptionStatusPhysicalSubscription represents the fully resolved values for this Subscription.

func (*SubscriptionStatusPhysicalSubscription) DeepCopy

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

func (*SubscriptionStatusPhysicalSubscription) DeepCopyInto

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