common

package
v0.0.0-...-58b7b8b Latest Latest
Warning

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

Go to latest
Published: Mar 19, 2024 License: Apache-2.0 Imports: 112 Imported by: 0

Documentation

Index

Constants

View Source
const (
	TestingIDPRealm = "testing-idp"

	DefaultTestUserName = "test-user"
)
View Source
const (
	TestAuthThreeScaleUsername = "testauth-threescale"
)

Variables

View Source
var (
	ALL_TESTS = []TestSuite{
		{
			[]TestCase{

				{"Verify RHMI CRD Exists", TestIntegreatlyCRDExists},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi, v1alpha1.InstallationTypeMultitenantManagedApi},
		},
	}

	HAPPY_PATH_TESTS = []TestSuite{

		{
			[]TestCase{
				{"A32 - Validate SSO config", TestSSOconfig},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi},
		},
		{
			[]TestCase{
				{"E10 - Verify Customer Grafana Route is accessible", TestCustomerGrafanaExternalRouteAccessible},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi, v1alpha1.InstallationTypeMultitenantManagedApi},
		},
		{
			[]TestCase{

				{"A01 - Verify that all stages in the integreatly-operator CR report completed", TestIntegreatlyStagesStatus},
				{"A03 - Verify all namespaces have been created with the correct name", TestNamespaceCreated},
				{"A05 - Verify product operator version", TestProductOperatorVersions},
				{"A07 - Verify product versions", TestProductVersions},
				{"A08 - Verify all products routes are created", TestIntegreatlyRoutesExist},
				{"A09 - Verify Subscription Install Plan Strategy", TestSubscriptionInstallPlanType},
				{"A10 - Verify CRO Postgres CRs Successful", TestCROPostgresSuccessfulState},
				{"A11 - Verify CRO Redis CRs Successful", TestCRORedisSuccessfulState},
				{"A13 - Verify Deployment resources have the expected replicas", TestDeploymentExpectedReplicas},
				{"A14 - Verify Deployment Config resources have the expected replicas", TestDeploymentConfigExpectedReplicas},
				{"A15 - Verify Stateful Set resources have the expected replicas", TestStatefulSetsExpectedReplicas},
				{"A26 - Verify Sendgrid Credentials Are Configured Properly", TestSendgridCredentialsAreValid},
				{"C01 - Verify Alerts are not pending or firing apart from DeadMansSwitch", TestIntegreatlyAlertsPendingOrFiring},
				{"F02 - Verify PodDisruptionBudgets exist", TestIntegreatlyPodDisruptionBudgetsExist},
				{"A27 + A28 - Verify pod priority class is created and set", TestPriorityClass},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi, v1alpha1.InstallationTypeMultitenantManagedApi},
		},
		{
			[]TestCase{
				{"M01 - Verify multitenancy works as expected", TestMultitenancy},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeMultitenantManagedApi},
		},
		{
			[]TestCase{
				{"Validate resource requirements are set", ValidateResourceRequirements},
				{"Verify addon instance status conditions", TestStatusConditions},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi},
		},
	}

	OBSERVABILITY_TESTS = []TestSuite{

		{
			[]TestCase{
				{"Test if cluster package is available", TestClusterPackageAvailable},
				{"Test RHMI installation CR metric", TestRHMICRMetrics},
				{"A06 - Verify PVC", TestPVClaims},
				{"C04 - Verify Alerts exist", TestIntegreatlyAlertsExist},
				{"C10B - Verify Prometheus blackbox targets", TestAdditionalBlackboxTargets},
				{"C08B - Verify alert links to SOPs", TestSOPUrls},
				{"Verify Alerts are not firing during or after installation apart from DeadMansSwitch", TestIntegreatlyAlertsFiring},
				{"Verify prometheus metrics scrapped", TestMetricsScrappedByPrometheus},
				{"E09 - Verify customer dashboards exist", TestIntegreatlyCustomerDashboardsExist},
				{"Verify ClusterObjectTemplates ready state", TestClusterObjectTemplateState},
				{"Verify package operator resource stability", TestPackageOperatorResourceStability},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi, v1alpha1.InstallationTypeMultitenantManagedApi},
		},
		{
			[]TestCase{
				{"M02B - Verify RHOAM version metric is exposed in Prometheus", TestRhoamVersionMetricExposed},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi},
		},
	}

	//Threescale cluster scoped test suite to be used when Threescale becomes cluster scoped.
	THREESCALE_CLUSTER_SCOPED_TESTS = []TestSuite{
		{
			[]TestCase{
				{"H29 - Verify that backend can be created via backend CR", Test3scaleBackendViaCR},
				{"H30 - Verify that product can be created via product CR", Test3scaleProductViaCR},
				{"H31 - Verify that tenant can be created via tenant CR", Test3scaleTenantViaCr},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi},
		},
	}

	IDP_BASED_TESTS = []TestSuite{
		{
			[]TestCase{
				{"B06 - Verify users with no email get default email", TestDefaultUserEmail},
				{"Verify Network Policy allows cross NS access to SVC", TestNetworkPolicyAccessNSToSVC},
				{"C19 - Validate creation of invalid username triggers alert", TestInvalidUserNameAlert},
				{"H34 - Verify 3scale custom SMTP full config", Test3ScaleCustomSMTPFullConfig},
				{"H35 - Verify 3scale custom SMTP partial config", Test3ScaleCustomSMTPPartialConfig},
				{"H24 - Verify selfmanaged Apicast", TestSelfmanagedApicast},
				{"A33 - Verify console links", TestConsoleLinks},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi, v1alpha1.InstallationTypeMultitenantManagedApi},
		},
		{
			[]TestCase{
				{"B01B - Verify users can login to products", TestProductLogins},
				{"B08B - Verify users can create a Realm in User SSO", TestUsersCreateRealmSSO},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi},
		},
		{
			[]TestCase{
				{"A16 - Custom first broker login flow", TestAuthDelayFirstBrokerLogin},
				{"B03 - Verify RHMI Developer User Permissions are Correct", TestRHMIDeveloperUserPermissions},
				{"B04 - Verify Dedicated Admin User Permissions are Correct", TestDedicatedAdminUserPermissions},
				{"B09 - Verify dedicated admin users are synced with User SSO", TestDedicatedAdminUsersSyncedSSO},
				{"H03 - Verify 3scale CRUDL permissions", Test3ScaleCrudlPermissions},
				{"H07 - ThreeScale User Promotion", Test3ScaleUserPromotion},

				{"H11 - Verify 3scale SMTP config", Test3ScaleSMTPConfig},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi},
		},
	}

	SCALABILITY_TESTS = []TestSuite{
		{
			[]TestCase{
				{"F05 - Verify Replicas Scale correctly in Threescale", TestReplicasInThreescale},
				{"F08 - Verify Replicas Scale correctly in RHSSO", TestReplicasInRHSSO},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi, v1alpha1.InstallationTypeMultitenantManagedApi},
		},
		{
			[]TestCase{
				{"F08 - Verify Replicas Scale correctly in User SSO", TestReplicasInUserSSO},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi},
		},
		{
			[]TestCase{
				{"A34 - Verify Quota values", TestQuotaValues},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi, v1alpha1.InstallationTypeMultitenantManagedApi},
		},
	}

	FAILURE_TESTS = []TestCase{
		{"C03 - Verify that alerting mechanism works", TestIntegreatlyAlertsMechanism},
	}

	DESTRUCTIVE_TESTS = []TestCase{

		{"J03 - Verify namespaces restored when deleted", TestNamespaceRestoration},
		{"C14B - Verify 3scale UIBBT alerts", TestThreeScaleUIBBTAlerts},
	}

	AWS_SPECIFIC_TESTS = []TestSuite{
		{
			[]TestCase{
				{"A12 - Verify CRO BlobStorage CRs Successful", TestCROBlobStorageSuccessfulState},
			},
			[]v1alpha1.InstallationType{v1alpha1.InstallationTypeManagedApi, v1alpha1.InstallationTypeMultitenantManagedApi},
		},
	}
)

All tests are be linked[1] to the integreatly-test-cases[2] repo by using the same ID 1. https://gitlab.cee.redhat.com/integreatly-qe/integreatly-test-cases#how-to-automate-a-test-case-and-link-it-back 2. https://gitlab.cee.redhat.com/integreatly-qe/integreatly-test-cases

View Source
var (
	NamespacePrefix                = GetNamespacePrefix()
	OpenShiftConsoleRoute          = "console"
	OpenShiftConsoleNamespace      = "openshift-console"
	RHOAMOperatorNamespace         = NamespacePrefix + "operator"
	ObservabilityProductNamespace  = NamespacePrefix + "operator-observability"
	ObservabilityNamespacePrefix   = ObservabilityProductNamespace + "-"
	ObservabilityPrometheusPodName = "prometheus-rhoam-0"
	SMTPSecretName                 = NamespacePrefix + "smtp"
	DMSSecretName                  = NamespacePrefix + "deadmanssnitch"
	CloudResourceOperatorNamespace = NamespacePrefix + "cloud-resources-operator"
	RHSSOUserProductNamespace      = NamespacePrefix + "user-sso"
	RHSSOUserOperatorNamespace     = RHSSOUserProductNamespace + "-operator"
	RHSSOProductNamespace          = NamespacePrefix + "rhsso"
	RHSSOOperatorNamespace         = RHSSOProductNamespace + "-operator"
	ThreeScaleProductNamespace     = NamespacePrefix + "3scale"
	ThreeScaleOperatorNamespace    = ThreeScaleProductNamespace + "-operator"
	Marin3rOperatorNamespace       = NamespacePrefix + "marin3r-operator"
	Marin3rProductNamespace        = NamespacePrefix + "marin3r"
	CustomerGrafanaNamespace       = NamespacePrefix + "customer-monitoring"
	CustomerGrafanaNamespacePrefix = CustomerGrafanaNamespace + "-"
)
View Source
var (
	TestingIdpPassword = utils.GetIdpPassword(defaultPassword)
)

Functions

func ChromeDpTimeOutWithActions

func ChromeDpTimeOutWithActions(t TestingTB, timeOut time.Duration, actions ...chromedp.Action)

func ExecToPod

func ExecToPod(client kubernetes.Interface, config *rest.Config, command, podName, namespace, container string) (string, error)

func ExecToPodArgs

func ExecToPodArgs(client kubernetes.Interface, config *rest.Config, command []string, podName, namespace, container string) (string, error)

func GetGrafanaRouteHostname

func GetGrafanaRouteHostname(c client.Client, namespace string) (string, error)

func GetInstallType

func GetInstallType(config *rest.Config) (string, error)

func GetListOptions

func GetListOptions(namespace string, podLabels ...string) []k8sclient.ListOption

func GetNamespacePrefix

func GetNamespacePrefix() string

func GetPlatformType

func GetPlatformType(ctx *TestingContext) string

func GetPrefixedNamespace

func GetPrefixedNamespace(subNS string) string

func GetRHMI

func GetRHMI(client k8sclient.Client, failNotExist bool) (*rhmiv1alpha1.RHMI, error)

func HasSelfSignedCerts

func HasSelfSignedCerts(url string, httpClient *http.Client) (bool, error)

func IsClusterScoped

func IsClusterScoped(restConfig *rest.Config) (bool, error)

func NewTestingHTTPClient

func NewTestingHTTPClient(kubeConfig *rest.Config) (*http.Client, error)

func Test3ScaleCrudlPermissions

func Test3ScaleCrudlPermissions(t TestingTB, ctx *TestingContext)

Tests that a user in group dedicated-admins can create an integration

func Test3ScaleCustomSMTPFullConfig

func Test3ScaleCustomSMTPFullConfig(t TestingTB, ctx *TestingContext)

func Test3ScaleCustomSMTPPartialConfig

func Test3ScaleCustomSMTPPartialConfig(t TestingTB, ctx *TestingContext)

func Test3ScaleSMTPConfig

func Test3ScaleSMTPConfig(t TestingTB, ctx *TestingContext)

Test3ScaleSMTPConfig to confirm 3scale can send an email

func Test3ScaleUserPromotion

func Test3ScaleUserPromotion(t TestingTB, ctx *TestingContext)

func Test3scaleBackendViaCR

func Test3scaleBackendViaCR(t TestingTB, ctx *TestingContext)

func Test3scaleProductViaCR

func Test3scaleProductViaCR(t TestingTB, ctx *TestingContext)

func Test3scaleTenantViaCr

func Test3scaleTenantViaCr(t TestingTB, ctx *TestingContext)

Tests that a user in group dedicated-admins can create an integration

func TestAdditionalBlackboxTargets

func TestAdditionalBlackboxTargets(t TestingTB, ctx *TestingContext)

func TestAuthDelayFirstBrokerLogin

func TestAuthDelayFirstBrokerLogin(t TestingTB, ctx *TestingContext)

func TestCROBlobStorageSuccessfulState

func TestCROBlobStorageSuccessfulState(t TestingTB, ctx *TestingContext)

func TestCROPostgresSuccessfulState

func TestCROPostgresSuccessfulState(t TestingTB, ctx *TestingContext)

func TestCRORedisSuccessfulState

func TestCRORedisSuccessfulState(t TestingTB, ctx *TestingContext)

func TestClusterObjectTemplateState

func TestClusterObjectTemplateState(t TestingTB, ctx *TestingContext)

func TestClusterPackageAvailable

func TestClusterPackageAvailable(t TestingTB, ctx *TestingContext)
func TestConsoleLinks(t TestingTB, ctx *TestingContext)

TestConsoleLinks tests the console links are the same as in the RHMI CR status Logins is covered by TestProductLogins

func TestCustomerGrafanaExternalRouteAccessible

func TestCustomerGrafanaExternalRouteAccessible(t TestingTB, ctx *TestingContext)

func TestDedicatedAdminUserPermissions

func TestDedicatedAdminUserPermissions(t TestingTB, ctx *TestingContext)

func TestDedicatedAdminUsersSyncedSSO

func TestDedicatedAdminUsersSyncedSSO(t TestingTB, tc *TestingContext)

func TestDefaultUserEmail

func TestDefaultUserEmail(t TestingTB, ctx *TestingContext)

TestDefaultUserEmail verifies that a user syncronized from the IDP have a default email adress if no email is present from the IDP.

Verify that the email address is generated as <username>@rhmi.io

func TestDeploymentConfigExpectedReplicas

func TestDeploymentConfigExpectedReplicas(t TestingTB, ctx *TestingContext)

func TestDeploymentExpectedReplicas

func TestDeploymentExpectedReplicas(t TestingTB, ctx *TestingContext)

func TestIntegreatlyAlertsExist

func TestIntegreatlyAlertsExist(t TestingTB, ctx *TestingContext)

func TestIntegreatlyAlertsFiring

func TestIntegreatlyAlertsFiring(t TestingTB, ctx *TestingContext)

This test ensures that no alerts are firing during or after installation

func TestIntegreatlyAlertsMechanism

func TestIntegreatlyAlertsMechanism(t TestingTB, ctx *TestingContext)

TestIntegreatlyAlertsMechanism verifies that alert mechanism works

func TestIntegreatlyAlertsPendingOrFiring

func TestIntegreatlyAlertsPendingOrFiring(t TestingTB, ctx *TestingContext)

TestIntegreatlyAlertsFiring reports any firing or pending alerts

func TestIntegreatlyCRDExists

func TestIntegreatlyCRDExists(t TestingTB, ctx *TestingContext)

func TestIntegreatlyCustomerDashboardsExist

func TestIntegreatlyCustomerDashboardsExist(t TestingTB, ctx *TestingContext)

func TestIntegreatlyPodDisruptionBudgetsExist

func TestIntegreatlyPodDisruptionBudgetsExist(t TestingTB, ctx *TestingContext)

func TestIntegreatlyRoutesExist

func TestIntegreatlyRoutesExist(t TestingTB, ctx *TestingContext)

TestIntegreatlyRoutesExist tests that the routes for all the products are created

func TestIntegreatlyStagesStatus

func TestIntegreatlyStagesStatus(t TestingTB, ctx *TestingContext)

func TestInvalidUserNameAlert

func TestInvalidUserNameAlert(t TestingTB, ctx *TestingContext)

func TestMetricsScrappedByPrometheus

func TestMetricsScrappedByPrometheus(t TestingTB, ctx *TestingContext)

func TestMultitenancy

func TestMultitenancy(t TestingTB, ctx *TestingContext)

func TestMultitenancyPerformance

func TestMultitenancyPerformance(t TestingTB, ctx *TestingContext)

func TestNamespaceCreated

func TestNamespaceCreated(t TestingTB, ctx *TestingContext)

func TestNamespaceRestoration

func TestNamespaceRestoration(t TestingTB, ctx *TestingContext)

func TestNetworkPolicyAccessNSToSVC

func TestNetworkPolicyAccessNSToSVC(t TestingTB, ctx *TestingContext)

func TestPVClaims

func TestPVClaims(t TestingTB, ctx *TestingContext)

func TestPackageOperatorResourceStability

func TestPackageOperatorResourceStability(t TestingTB, ctx *TestingContext)

func TestPriorityClass

func TestPriorityClass(t TestingTB, ctx *TestingContext)

TestPriorityClass tests to ensure the pod priority class is created and verifies various crs are updated accordingly

func TestProductLogins

func TestProductLogins(t TestingTB, ctx *TestingContext)

TestProductLogins Test logins to RHOAM products as dedicated admin and developer user Test login for 3scale is covered by Test3ScaleUserPromotion

func TestProductOperatorVersions

func TestProductOperatorVersions(t TestingTB, ctx *TestingContext)

func TestProductVersions

func TestProductVersions(t TestingTB, ctx *TestingContext)

func TestQuotaValues

func TestQuotaValues(t TestingTB, ctx *TestingContext)

func TestRHMICRMetrics

func TestRHMICRMetrics(t TestingTB, ctx *TestingContext)

func TestRHMIDeveloperUserPermissions

func TestRHMIDeveloperUserPermissions(t TestingTB, ctx *TestingContext)

func TestReplicasInRHSSO

func TestReplicasInRHSSO(t TestingTB, ctx *TestingContext)

func TestReplicasInThreescale

func TestReplicasInThreescale(t TestingTB, ctx *TestingContext)

func TestReplicasInUserSSO

func TestReplicasInUserSSO(t TestingTB, ctx *TestingContext)

func TestRhoamVersionMetricExposed

func TestRhoamVersionMetricExposed(t TestingTB, ctx *TestingContext)

func TestSOPUrls

func TestSOPUrls(t TestingTB, ctx *TestingContext)

func TestSSOconfig

func TestSSOconfig(t TestingTB, ctx *TestingContext)

func TestSelfmanagedApicast

func TestSelfmanagedApicast(t TestingTB, testingCtx *TestingContext)

func TestSendgridCredentialsAreValid

func TestSendgridCredentialsAreValid(t TestingTB, ctx *TestingContext)

func TestStatefulSetsExpectedReplicas

func TestStatefulSetsExpectedReplicas(t TestingTB, ctx *TestingContext)

func TestStatusConditions

func TestStatusConditions(t TestingTB, ctx *TestingContext)

func TestSubscriptionInstallPlanType

func TestSubscriptionInstallPlanType(t TestingTB, ctx *TestingContext)

func TestThreeScaleUIBBTAlerts

func TestThreeScaleUIBBTAlerts(t TestingTB, ctx *TestingContext)

func TestUsersCreateRealmSSO

func TestUsersCreateRealmSSO(t TestingTB, ctx *TestingContext)

func ValidateResourceRequirements

func ValidateResourceRequirements(t TestingTB, ctx *TestingContext)

func WaitForRHMIStageToComplete

func WaitForRHMIStageToComplete(t ginkgo.GinkgoTInterface, restConfig *rest.Config) error

func WriteRHMICRToFile

func WriteRHMICRToFile(client dynclient.Client, file string) error

Types

type Alert

type Alert struct {
	Labels struct {
		AlertName string `json:"alertname"`
	} `json:"labels"`
	State string `json:"state"`
}

type AlertsResults

type AlertsResults struct {
	Alerts []Alert `json:"alerts"`
}

type ConsoleLinkAssertion

type ConsoleLinkAssertion struct {
	URL  string
	Icon string
}

type CustomResource

type CustomResource struct {
	Namespace string
	Name      string
}

type ExpectedPermissions

type ExpectedPermissions struct {
	ExpectedCreateStatusCode int
	ExpectedReadStatusCode   int
	ExpectedUpdateStatusCode int
	ExpectedDeleteStatusCode int
	ExpectedListStatusCode   int
	ListPath                 string
	GetPath                  string
	ObjectToCreate           interface{}
}

type ExpectedRoute

type ExpectedRoute struct {
	// Name is either the name of the route or the generated name (if the
	// `IsGeneratedName` field is true)
	Name string

	// ServiceName is the name of the service that the route points to (used
	// when the name is generated as there can be multiple routes with the same
	// generated name)
	ServiceName string

	IsGeneratedName bool
	// contains filtered or unexported fields
}

ExpectedRoute contains the data of a route that is expected to be found

type LogOptions

type LogOptions struct {
	Container string `url:"container"`
	Follow    string `url:"follow"`
	TailLines string `url:"tailLines"`
}

struct used to create query string for fuse logs endpoint

type Namespace

type Namespace struct {
	Name                     string
	Products                 []Product
	PodDisruptionBudgetNames []string
}

type PersistentVolumeClaim

type PersistentVolumeClaim struct {
	Namespace                  string
	PersistentVolumeClaimNames []string
}

type Product

type Product struct {
	Name             string
	ExpectedReplicas int32
}

type StageDeletion

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

type SubscriptionCheck

type SubscriptionCheck struct {
	Name      string
	Namespace string
}

type TestCase

type TestCase struct {
	Description string
	Test        func(t TestingTB, ctx *TestingContext)
}

func GetAWSSpecificTestCases

func GetAWSSpecificTestCases(installType string) []TestCase

func GetAllTestCases

func GetAllTestCases(installType string) []TestCase

func GetClusterScopedTestCases

func GetClusterScopedTestCases(installType string) []TestCase

func GetHappyPathTestCases

func GetHappyPathTestCases(installType string) []TestCase

func GetIDPBasedTestCases

func GetIDPBasedTestCases(installType string) []TestCase

func GetObservabilityTestCases

func GetObservabilityTestCases(installType string) []TestCase

func GetScalabilityTestCases

func GetScalabilityTestCases(installType string) []TestCase

type TestSuite

type TestSuite struct {
	TestCases   []TestCase
	InstallType []rhmiv1alpha1.InstallationType
}

type TestUser

type TestUser struct {
	UserName  string
	FirstName string
	LastName  string
}

type TestingContext

type TestingContext struct {
	Client          dynclient.Client
	KubeConfig      *rest.Config
	KubeClient      kubernetes.Interface
	ExtensionClient *clientset.Clientset
	HttpClient      *http.Client
	SelfSignedCerts bool
}

func NewTestingContext

func NewTestingContext(kubeConfig *rest.Config) (*TestingContext, error)

type TestingTB

type TestingTB interface {
	Fail()
	Error(args ...interface{})
	Errorf(format string, args ...interface{})
	FailNow()
	Fatal(args ...interface{})
	Fatalf(format string, args ...interface{})
	Log(args ...interface{})
	Logf(format string, args ...interface{})
	Failed() bool
	Parallel()
	Skip(args ...interface{})
	Skipf(format string, args ...interface{})
	SkipNow()
	Skipped() bool
}

type Tests

type Tests struct {
	Type      string
	TestCases []TestCase
}

Jump to

Keyboard shortcuts

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