Skip to content

Commit

Permalink
make docusaurus public-facing area exclusive to extensions (rancher#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
aalves08 authored Jun 3, 2024
1 parent 09814e9 commit 4ae1459
Show file tree
Hide file tree
Showing 67 changed files with 316 additions and 74 deletions.
128 changes: 126 additions & 2 deletions docusaurus/docs/extensions/advanced/localization.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,129 @@
# Localization

Extensive documentation on translations and localizations can be found in the [On-screen Text and Translations](../../code-base-works/on-screen-text-and-translations.md) section. Apart from directory location, the same rules for Rancher Dashboard apply for extensions.

Generating localizations in extensions is done per package via a translation YAML file found in the `./pkg/<extension-name>/l10n` directory. If a translation is not included in the user's selected language, it will fall back to English.

## Internationalization (i18n)

Any code producing messages, labels, numbers, dates, times, and the like should use the `i18n` store and translation strings to generate and format them instead of hardcoding English or American-isms anywhere. Messages and number formatting uses [ICU templating](https://formatjs.io/docs/intl-messageformat) for very powerful pluralization and customizing.

The `assets/translations` dir stores a YAML file with translations for each supported language.
- English is automatically used as the "fallback" if a particular key is missing from a non-English language.
- If you don't have a native translation for a particular key, just leave that key out of the language
- Do not duplicate the English string into other languages.

Translations should be the largest phrase that makes sense as a single key, rather than several separate things rendered in a fixed order.
- For example "about 2 minutes remaining" should be a single translation: `About {n, number} {n, plural, one { minute }, other { minutes }} remaining`.
- Not one for `About`, one for `minute`, one for `minutes`, one for `remaining`, and some code picking and choosing which to concatenate.

All on screen text should be localised and implemented in the default `en-US` locale. There are different ways to access localised text

> `t` can be exposed via adding the i18n getter as a computed property with `...mapGetters({ t: 'i18n/t' })`
In HTML

```html
<t k="<path to localisation>" />
{{ t("<path to localisation>") }}
```

Many components will also accept a localisation path via a `value-key` property, instead of the translated text in `value`.

In JS/TS

```ts
this.t('<path to localisation>')
```

A localisation can be checked with

```ts
this.$store.getters['i18n/exists']('<path to localisation>')

this.$store.getters['i18n/withFallback']('<path to localisation>', null, '<fallback>'))
```

## Using Variables in i18n Paths

In Javascript files, variables in localisation paths must be wrapped in quotation marks when the variable contains a slash.

For example, if we want to dynamically fill in the description of a resource based on its type, we can use a `type` variable when referencing the localisation path to the description:

```ts
{
description: this.t(`secret.typeDescriptions.'${ type }'.description`),
}
```

In this case, the quotation marks are required because some Secret types, such as `kubernetes.io/basic-auth`, include a slash.

## l10n

Localisation files can be found in `./assets/translations/en-us.yaml`.

Please follow precedents in file to determine where new translations should be place.

Form fields are conventionally defined in translations as `<some prefix>`.`<field name>`.{label,description,enum options if applicable} e.g.

```yml
account:
apiKey:
description:
label: Description
placeholder: Optionally enter a description to help you identify this API Key
```
If a translation is not included in the user's selected language, it will fall back to English. The only time the Rancher UI devs should modify a non-English translation is when a key is renamed.
## Checking for missing translation strings
The script `scripts/check-i18n` can be used to check for missing translation strings.

It uses a set of regular expressions to detect for translation strings being used in the code base. It will report any string references that it finds that it does not find a corresponding translation for - this is an indication of a missing translation string.

This script is run as part of the dashboard Continuos Integration via GitHub actions.

The script accepts two optional arguments:

- -s Print out the details of translations strings found in the localisation files that don't appear to be used by the code
- -x Don't set the exit code if there are errors detected

### Comments

Since the script uses regular expressions, there are cases where it might:

- Incorrectly detect a use of a translation string in the code that is not such
- Not be able to detect that a translation string has been used

To address these issues, you need to use comments in your code to assist the i18n checker script.

Comments can be placed at the start of the line, or as part of a line of code at the end. They can not be added to templates, so
comments should be added at the top of the code file for these.

#### i18n-uses

You can use a comment of the form:

```
// i18n-uses TRANSLATION
```

to indicate that the string `TRANSLATION` is used in the code.

#### i18n-ignore

You can use a comment of the form:

```
// i18n-ignore TRANSLATION
```

to indicate that the string `TRANSLATION` should be ignored and is not a reference to a translation string.

#### Translation Strings

With both `i18n-uses` and `i18n-ignore`, the `TRANSLATION` string can be:

- A simple string, e.g. `area.subarea.name`
- A regular expression, e.g. `/area\.subarea\.name/`
- A simple string with wild-cards specified using `*`, e.g. `area.subarea.*` or `area.*.name`
10 changes: 9 additions & 1 deletion docusaurus/docs/extensions/advanced/provisioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,15 @@ The class provides a way to...
- It's used in the UI whenever showing the cluster's provider
1. show custom tabs on the Detail page of the custom cluster

> To make API calls from the UI to a different domain see [here](../../code-base-works/machine-drivers.md#api-calls). For instance to fetch region or machine size information used to create a machine config
To make API calls from the UI to a different domain, Rancher includes a [proxy](https://github.com/rancher/rancher/blob/release/v2.6/pkg/httpproxy/proxy.go) that can be used to make requests to third-party domains (like a cloud provider's API) without requiring that the other end supports CORS or other browser shenanigans. Send requests to `/meta/proxy/example.com/whatever/path/you/want` and the request will be made from the Rancher server and proxied back to you.

TLS and port 443 are assumed. Add a port after the hostname to change the port (`example.com:1234`). For plain HTTP, first stop and consider the chain of life decisions which have led you to this point. Then if you still think you need that, use `/meta/proxy/http:/example.com:1234` (note one slash after `http:`, not two). The hostname must be included in the whitelist defined in global settings, or in the configuration for an active node driver. If if isn't your request will be denied. (This prevents a malicious (non-admin) user from abusing the Rancher server as an arbitrary HTTP proxy or reach internal IPs/names that the server can reach directly but the user can't from the outside.)

The rest of the path and query string are sent to the target host as you'd expect.

Normal headers are copied from your request and sent to the target. There are some exceptions for sensitive fields like the user's rancher cookies or saved basic auth creds which will not be copied. If you send an `X-Api-Cookie-Header`, its value will be sent as the normal `Cookie` to the target. If you send `X-API-Auth-Header`, that will be sent out as the normal `Authorization`.

But normally you want to make a request using a Cloud Credential as the authorization, without knowing what the secret values in that credential are. You ask for this by sending an `X-Api-CattleAuth-Header` header. The value of the header specifies what credential Id to use, and a [signer](https://github.com/rancher/rancher/blob/release/v2.6/pkg/httpproxy/sign.go) which describes how that credential should be injected into the request. Common options include `awsv4` (Amazon's complicated HMAC signatures), `bearer`, `basic`, and `digest`. For example if you send `X-Api-CattleAuth-Header: Basic credId=someCredentialId usernameField=user passwordField=pass`, Rancher will retrieve the credential with id `someCredentialId`, read the values of the `user` and `pass` fields from it and add the header `Authorization: Basic <base64(user + ":" + pass)>` to the proxied request for you.

### Components
When creating or editing a cluster the user can see the cloud credential and machine pool components.
Expand Down
35 changes: 30 additions & 5 deletions docusaurus/docs/extensions/api/components/node-drivers.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,34 @@ Rancher allows UI to be created for custom Node Drivers by registering component

In both cases, the `ID` when registering should match the Node Driver name.

For more information, see: [Machine Drivers](../../../code-base-works/machine-drivers).
<!--
## Cloud Credentials
## Cloud Credential

## Machine Configuration
-->
Cloud Credentials store the username & password, or other similar information, needed to talk to a particular provider. There is typically a 1-to-1 mapping of cloud credentials to drivers. If one provider (e.g. Amazon) has both a *Machine* driver for RKE (using EC2) and a *Cluster* driver for Kontainer Engine (using EKS) then you can and should use a single shared type of credential (e.g. `aws`) for both.

The cloud credential component lives in the top-level `cloud-credential` directory in the repo. The file should be named the same as the driver, in all lowercase (e.g. `cloud-credential/digitalocean.vue`).

If there is a reason to rename it or map multiple drivers to the same credential, configure that in `shell/store/plugins.js`. There is also other info in there about how guesses are taken on what each field is for and how it should be displayed. These can be customized for your driver by importing and calling `configureCredential()` and `mapDriver()`.

Create a component which displays each field that is relevant to authentication and lets the user configure them. Only the actual auth fields themselves, the rest of configuring the name, description, save buttons, etc is handled outside of the credential component.

Your component should emit a `validationChanged` event every time a value changes. It should also (but doesn't _have to_ implement a `test()` method. This may be asynchronous, and should make an API call or similar to see if the provided credentials work. Return `true` if they're ok and `false` otherwise. When provided, this is called before saving and the user won't be able to save until their input causes you return `true`.

## Machine Config

Similar to the Cloud Credential component, the Machine Config component should display just controls for the fields on the driver that are relevant to the configuration of the machine to be created. The machine pool name, saving, etc is handled outside of your component. You probably want to use `fetch()` to load some info from the provider's API (e.g. list of regions or instance types).

It should live in the top-level `machine-config` directory, again named the same as the driver and lowercase (e.g. `machine-config/digitalocean.vue`).

The selected cloud credential ID is available as a `credentialId` prop. You will always know that ID, and can use it to make API calls (see [#api-calls] below), but **must not** rely on being able to actually retrieve the cloud credential model corresponding to it. Users with lesser permissions may be able to edit a cluster, but not have permission to see the credential being used to manage it.

### API Calls

Rancher includes a [proxy](https://github.com/rancher/rancher/blob/release/v2.6/pkg/httpproxy/proxy.go) that can be used to make requests to third-party domains (like a cloud provider's API) without requiring that the other end supports CORS or other browser shenanigans. Send requests to `/meta/proxy/example.com/whatever/path/you/want` and the request will be made from the Rancher server and proxied back to you.

TLS and port 443 are assumed. Add a port after the hostname to change the port (`example.com:1234`). For plain HTTP, first stop and consider the chain of life decisions which have led you to this point. Then if you still think you need that, use `/meta/proxy/http:/example.com:1234` (note one slash after `http:`, not two). The hostname must be included in the whitelist defined in global settings, or in the configuration for an active node driver. If if isn't your request will be denied. (This prevents a malicious (non-admin) user from abusing the Rancher server as an arbitrary HTTP proxy or reach internal IPs/names that the server can reach directly but the user can't from the outside.)

The rest of the path and query string are sent to the target host as you'd expect.

Normal headers are copied from your request and sent to the target. There are some exceptions for sensitive fields like the user's rancher cookies or saved basic auth creds which will not be copied. If you send an `X-Api-Cookie-Header`, its value will be sent as the normal `Cookie` to the target. If you send `X-API-Auth-Header`, that will be sent out as the normal `Authorization`.

But normally you want to make a request using a Cloud Credential as the authorization, without knowing what the secret values in that credential are. You ask for this by sending an `X-Api-CattleAuth-Header` header. The value of the header specifies what credential Id to use, and a [signer](https://github.com/rancher/rancher/blob/release/v2.6/pkg/httpproxy/sign.go) which describes how that credential should be injected into the request. Common options include `awsv4` (Amazon's complicated HMAC signatures), `bearer`, `basic`, and `digest`. For example if you send `X-Api-CattleAuth-Header: Basic credId=someCredentialId usernameField=user passwordField=pass`, Rancher will retrieve the credential with id `someCredentialId`, read the values of the `user` and `pass` fields from it and add the header `Authorization: Basic <base64(user + ":" + pass)>` to the proxied request for you.
Loading

0 comments on commit 4ae1459

Please sign in to comment.