The documentation guidelines for OpenShift 4 build on top of the Red Hat modular docs reference guide.
- General file guidelines
- Assembly file metadata
- Module file metadata
- Text snippet file metadata
- Content type attributes
- Attribute files
- Assembly/module file names
- Directory names
- Assembly/Module titles and section headings
- Anchoring titles and section headings
- Writing assemblies
- Writing concepts
- Writing procedures
- Writing text snippets
- Auto-generated content
- Using conscious language
- Product title and version
- Conditional content
- Node names
- IP addresses
- Links, hyperlinks, and cross references
- Embedding an external file
- Indicating Technology Preview features
- Indicating deprecated features
- Verification of your content
- Images
- Formatting
- Admonitions
- API object formatting
- Declarative config examples
- Quick markup reference
-
Set your editor to strip trailing whitespace.
-
Do not hard wrap lines at 80 characters (or at any other length).
It is not necessary to update existing content to unwrap lines, but you can remove existing hard wrapping from any lines that you are currently working in.
TipIn the Atom editor, you can use
Ctrl
+J
to undo hard wrapping on a paragraph.
Every assembly file should contain the following metadata at the top, with no line spacing in between, except where noted:
:_content-type: ASSEMBLY (1) [id="<unique-heading-for-assembly>"] (2) = Assembly title (3) include::_attributes/common-attributes.adoc[] (4) :context: <unique-context-for-assembly> (5) (6) toc::[] (7)
-
The content type for the file. For assemblies, always use
:_content-type: ASSEMBLY
. Place this attribute before the anchor ID or, if present, the conditional that contains the anchor ID. -
A unique (within OpenShift docs) anchor ID for this assembly. Use lowercase. Example: cli-developer-commands
-
Human readable title (notice the
=
top-level header) -
Includes attributes common to OpenShift docs.
NoteThe
{product-title}
and{product-version}
common attributes are not defined in the_attributes/common-attributes.adoc
file. Those attributes are pulled by AsciiBinder from the distro mapping definitions in the _distro_map.yml file. See Product title and version and attribute files for more information on this topic. -
Context used for identifying headers in modules that is the same as the anchor ID. Example: cli-developer-commands.
-
A blank line. You must have a blank line here before the toc.
-
The table of contents for the current assembly.
After the heading block and a single whitespace line, you can include any content for this assembly.
Note
|
The assembly title, which is the first line of the document, is the only level 1 ( = ) title. Section headers within the assembly must be level 2 ( == ) or lower. When you include modules, you must add leveloffsets in the include statements. You can manually add more level 2 or lower section headers in the assembly. |
Every module should be placed in the modules folder and should contain the following metadata at the top:
// Module included in the following assemblies: // // * list of assemblies where this module is included (1) :_content-type: <TYPE> (2) [id="<module-anchor>_{context}"] (3) = Module title (4)
-
The content type for the file. Replace
<TYPE>
with the actual type of the module,CONCEPT
,REFERENCE
, orPROCEDURE
. Place this attribute before the anchor ID or, if present, the conditional that contains the anchor ID. -
List of assemblies in which this module is included.
-
A module anchor with {context} that must be lowercase and must match the module’s file name.
-
Human readable title. To ensure consistency in the results of the leveloffset values in include statements, you must use a level one heading ( = ) for the module title.
Example:
// Module included in the following assemblies: // // * cli_reference/openshift_cli/developer-cli-commands.adoc :_content-type: REFERENCE [id="cli-basic-commands_{context}"] = Basic CLI commands
Every text snippet should be placed in the snippets/
folder and should contain the following metadata at the top:
// Text snippet included in the following assemblies: (1) // // * list of assemblies where this text snippet is included // // Text snippet included in the following modules: (2) // // * list of modules where this text snippet is included :_content-type: SNIPPET (3)
-
List of assemblies in which this text snippet is included.
-
List of modules in which this text snippet is included.
-
The content type for the file. For snippets, always use
:_content-type: SNIPPET
. Place this attribute before the anchor ID, the conditional that contains the anchor ID, or the first line of body text.
Note
|
An anchor ID and human readable title are not required metadata. This type of component is text only and not intended to be published or cross referenced on its own. See Writing text snippets. |
Example:
// Text snippet included in the following assemblies: // // * installing/installing_aws/installing-aws-default.adoc // * installing/installing_azure/installing-azure-default.adoc // * installing/installing_gcp/installing-gcp-default.adoc :_content-type: SNIPPET In {product-title} version {product-version}, you can install a cluster on {cloud-provider-first} ({cloud-provider}) that uses the default configuration options.
Each .adoc
file must contain a :_content-type:
attribute in its metadata that indicates its file type. This information is used by some publication processes to sort and label files.
Add the attribute from the following list that corresponds to your file type:
-
:_content-type: ASSEMBLY
-
:_content-type: CONCEPT
-
:_content-type: PROCEDURE
-
:_content-type: REFERENCE
-
:_content-type: SNIPPET
Place the attribute in the file metadata. The following list describes the best attribute placement options:
-
Directly before the first anchor ID in a file
-
If the first anchor ID is enclosed in a conditional, before the conditional
-
Between the list of assemblies in which this module is included and the first line of body text
All attribute files must be placed in the _attributes
directory. In most cases involving OpenShift Container Platform or OKD, add attributes to the common-attributes.adoc
file instead of creating or using a separate attributes file. Before you add an attribute, review the contents of the common-attributes.adoc
file to ensure that it is not already defined.
Important
|
If you think that you need a separate attributes file, check with the docs team before you create it. |
It is acceptable to group related attributes in the common-attributes.adoc
file under a comment, as shown in the following example:
//gitops :gitops-title: Red Hat OpenShift GitOps :gitops-shortname: GitOps
It is also acceptable to enclose attributes in a distro-based conditional, but you must place attribute definitions for the openshift-enterprise
distro first. The following example shows how to set a different value for the :op-system-base:
attribute for OKD:
:op-system-base: RHEL
Try to shorten the file name as much as possible without abbreviating important terms that may cause confusion. For example, the managing-authorization-policies.adoc
file name would be appropriate for an assembly titled "Managing Authorization Policies".
If you create a directory with a multiple-word name, separate each word with an underscore, for example backup_and_restore
.
Note
|
Do not italicize user-replaced values. This guideline is an exception to the Red Hat supplementary style guide. |
Do not create or rename a top-level directory in the repository and topic map without checking with the docs program manager first.
Avoid creating two levels of subdirectories because the breadcrumb bar on docs.openshift.com breaks. If you have a valid use case for two levels of subdirectories, talk with your DPM/CS (and, for aligned teams, the OpenShift DPM) for approval before creating it.
When creating a new directory or subdirectory, you must create four symbolic links in it:
-
An
images
symbolic link to the top-levelimages/
directory -
A
modules
symbolic link to the top-levelmodules/
directory -
A
snippets
symbolic link to the top-levelsnippets/
directory -
An
_attributes
symbolic link to the top-level_attributes/
directory
If the directory that contains an assembly does not have the images
symbolic link, any images in that assembly or its modules will not be included properly when building the docs.
Tip
|
To create the symbolic links:
If you accidentally create an incorrect link, you can remove that link by using |
Use sentence case in all titles and section headings. See http://www.titlecase.com/ or https://convertcase.net/ for a conversion tool.
Try to be as descriptive as possible with the title or section headings without making them unnecessarily long. For assemblies and task modules, use a gerund form in headings, such as:
-
Creating
-
Managing
-
Using
Do not use "Overview" as a heading.
Do not use backticks or other markup in assembly or module headings.
Use only one level 1 heading (=
) in any file.
If you have a section heading that you do not want to appear in the TOC (like if you think that some section is not worth showing up or if there are already too many nested levels), you can use a discrete (or floating) heading:
A discrete heading also will not get a section number in the Customer Portal build of the doc. Previously, we would use plain bold mark-up around a heading like this, but discrete headings also allow you to ignore section nesting rules (like jumping from a ==
section level to a ====
level if you wanted for some style reason).
To use a discrete heading, just add [discrete]
to the line before your unique ID. For example:
[discrete] [id="managing-authorization-policies_{context}"] == Managing authorization policies
All titles and section headings must have an anchor ID. The anchor ID must be similar to the title or section heading.
The following is an example anchor ID in an assembly file:
[id="configuring-alert-notifications"] = Configuring alert notifications
Note
|
Do not include line spaces between the anchor ID and the section title. |
You must add the {context}
variable to the end of each anchor ID in module files. When called, the {context}
variable is resolved into the value declared in the :context:
attribute in the corresponding assembly file. This enables cross-referencing to module IDs in context to a specific assembly and is useful when a module is included in multiple assemblies.
Note
|
The |
The following is an example of an anchor ID for a module file title:
[id="sending-notifications-to-external-systems_{context}"] = Sending notifications to external systems
The following is an example of an anchor ID for a second level (==
) heading:
[id="deployment-scaling-benefits_{context}"] == Deployment and scaling benefits
Use unique IDs for "Prerequisites", "Additional resources", and "Next steps" titles in assemblies. You can add the prefixes prerequisites_
, additional-resources_
, or next-steps_
to a unique string that describes the assembly topic. The unique string can match the value assigned to the :context:
attribute in the assembly.
Note
|
The |
The following examples include IDs that are unique to the "Configuring alert notifications" assembly:
Example unique ID for a "Prerequisites" title
[id="prerequisites_configuring-alert-notifications"] == Prerequisites
Example unique ID for an "Additional resources" title
[role="_additional-resources"] [id="additional-resources_configuring-alert-notifications"] == Additional resources
Example unique ID for a "Next steps" title
[id="next-steps_configuring-alert-notifications"] == Next steps
An assembly is a collection of modules that describes how to accomplish a user story.
Avoid nesting assemblies in other assembly files. You can create more complicated document structures by modifying the topic maps.
For more information about forming assemblies, see the Red Hat modular docs reference guide and the assembly template.
Note
|
When using the "Prerequisites", "Next steps", or "Additional resources" headings in an assembly, use Only use |
A concept contains information to support the tasks that users want to do and must not include task information like commands or numbered steps. In most cases, create your concepts as individual modules and include them in appropriate assemblies.
Avoid using gerunds in concept titles. "About <concept>" is a common concept module title.
For more information about creating concept modules, see the Red Hat modular docs reference guide and the concept template.
A procedure contains the steps that users follow to complete a process or task. Procedures contain ordered steps and explicit commands. In most cases, create your procedures as individual modules and include them in appropriate assemblies.
Use a gerund in the procedure title, such as "Creating".
For more information about writing procedures, see the Red Hat modular docs reference guide and the procedure template.
Note
|
When needed, use |
A text snippet is an optional component that lets you reuse content in multiple modules and assemblies. Text snippets are not a substitute for modules but instead are a more granular form of content reuse. While a module is content that a reader can understand on its own (like an article) or as part of a larger body of work (like an assembly), a text snippet is not self-contained and is not intended to be published or cross referenced on its own.
In the context of modules and assemblies, text snippets do not include headings or anchor IDs. Text snippets also cannot contain xrefs. This type of component is text only. Examples include the following:
-
Admonitions that appear in multiple modules.
-
An introductory paragraph that appears in multiple assemblies.
-
The same series of steps that appear in multiple procedure modules.
-
A deprecation statement that appears in multiple sets of release notes.
Example:
You could write the following paragraph once and include it in each assembly that explains how to install a cluster using the installer-provisioned default values:
In {product-title} version {product-version}, you can install a cluster on {cloud-provider-first} ({cloud-provider}) that uses the default configuration options.
Note
|
In the example, |
For more information about creating text snippets, see the Red Hat modular docs reference guide
The following content is auto-generated in each release and must not be manually edited:
-
The OpenShift CLI (
oc
) command referencesmodules/oc-by-example-content.adoc
andmodules/oc-adm-by-example-content.adoc
. -
The following API references content in the
rest_api
folder: the contents of all<topic>_apis
subfolders and therest_api/objects/index.adoc
andrest_api/index.adoc
assemblies.
Note
|
If the content in these files needs to be updated, the update must be made in the applicable code repository where these files are generated from. The updates are reflected when the files are generated the next time, for example a future release. For help with where to make the updates, you can contact Andrea Hoffer for the CLI docs or Jason Boxman for the API docs. |
To assist with the removal of the problematic word "master" from the documentation, use the following terminology when referring to OpenShift control plane nodes:
Branch | Control plane node reference |
---|---|
|
Control plane node |
|
Control plane (also known as master) node |
|
Master node |
You can replace "node" in the preceding examples with "machine", "host", or another suitable description.
Note
|
If you are cherry picking from |
If you create a release notes assembly for a sub-product within the openshift/openshift-docs
repo, you might include a "Making open source more inclusive" statement. Instead of pasting the statement from the OpenShift Release Notes, use the following module, which is available in the enterprise-4.8
branch and later:
include::modules/making-open-source-more-inclusive.adoc[leveloffset=+1]
When possible, generalize references to the product name and/or version by using
the {product-title}
and/or {product-version}
attributes. These attributes
are pulled by AsciiBinder from the OpenShift distribution, or distro, mapping definitions in the
_distro_map.yml
file.
The {product-title}
comes from the first name:
field in a distro mapping,
while the associated {product-version}
comes from the name:
fields on any
branches:
defined.
How these attributes render is dependent on which distro and branch build you
are viewing. The following table shows the current distros and the
possible values for {product-title}
and {product-version}
, depending on the branch:
Distro | {product-title} |
{product-version} |
---|---|---|
|
OKD |
|
|
OpenShift Container Platform |
|
|
OpenShift Dedicated |
|
|
Red Hat OpenShift Service on AWS |
No value set for the |
|
OpenShift Online |
Pro |
For example:
You can deploy applications on {product-title}.
This is a safe statement that could appear in probably any of the builds, so an
ifdef/endif
statement is not necessary. For example, if you were viewing a build for the
openshift-enterprise
distro (for any of the distro-defined branches), this
would render as:
You can deploy applications on OpenShift Container Platform.
And for the openshift-origin
distro:
You can deploy applications on OKD.
Considering that we use distinct branches to keep content for product versions separated, global use of {product-version}
across all branches is probably less useful, but it is available if you come across a requirement for it. Just consider how it will render across any branches that the content appears in.
If it makes more sense in context to refer to the major version of the product instead of a specific minor version (for example, if comparing how something in OpenShift Container Platform 4 differs from OpenShift Container Platform 3), just use the major version number. Do not prepend with a v
, as in v3
or v4
.
Note
|
Other common attribute values are defined in the |
You can use ifdef and ifeval statements to control the way content displays in different distributions and assemblies.
Note
|
You can nest conditional statements that involve distribution and assembly context, but you must ensure that you close the if statements correctly. |
Because we maintain separate branches for each OpenShift Container Platform version, do not use if statements that are based on product version to vary content.
Use ifdef and ifndef statements to control content based on distribution, as described in the previous section. For example, the following example renders differently in (openshift-origin
) and OpenShift Container Platform (openshift-enterprise
):
ifdef::openshift-origin[] You can link:https://www.keycloak.org/docs/latest/server_admin/index.html#openshift[configure a Keycloak] server as an OpenID Connect identity provider for {product-title}. endif::[] ifdef::openshift-enterprise[] You can link:https://access.redhat.com/documentation/en-us/red_hat_single_sign-on/[configure Red Hat Single Sign-On] as an OpenID Connect identity provider for {product-title}. endif::[]
In OKD, this section renders as the following text:
You can configure a Keycloak server as an OpenID Connect identity provider for OKD.
In OpenShift Container Platform, this section renders as the following text:
You can configure Red Hat Single Sign-On as an OpenID Connect identity provider for OpenShift Container Platform.
Use a combination of ifdef and ifeval statements to control content that needs to vary between assemblies. These conditional statements rely on a combination of the context attribute for each assembly and specific temporary attributes within each module to control content.
The following sample shows a simple example. In the assembly that contains the context
attribute updating-restricted-network-cluster
, an extra paragraph is displayed.
ifeval::["{context}" == "updating-restricted-network-cluster"] :restricted: endif::[] ... ifdef::restricted[] If you are upgrading a cluster in a restricted network, install the `oc` version that you plan to upgrade to. endif::restricted[] ... ifeval::["{context}" == "updating-restricted-network-cluster"] :!restricted: endif::[]
Note that you must set and unset each temporary attribute that you introduce to an assembly. Use the temporary attributes in the applicable ifdef and ifndef statements to vary text between the assemblies. The preceeding example uses restricted
as the temporary attribute to display an additional paragraph for the assembly with the updating-restricted-network-cluster
context attribute.
Do not use internal company server names in commands or example output. Provide generic OpenShift Container Platform node name examples that are not provider-specific, unless required. Where possible, use the example.com domain name when providing fully qualified domain names (FQDNs).
The following table includes example OpenShift Container Platform 4 node names and their corresponding role types:
Node name | Role type |
---|---|
node-1.example.com |
You can use this format for nodes that do not need role-specific node names. |
node-2.example.com |
|
node-3.example.com |
|
control-plane-1.example.com |
You can use this format if you need to describe the control plane role type within a node name. |
control-plane-2.example.com |
|
control-plane-3.example.com |
|
compute-1.example.com |
You can use this format if you need to describe the compute node role type within a node name. |
compute-2.example.com |
|
bootstrap.example.com |
You can use this format if you need to describe the bootstrap node role type within a node name. |
This example lists the status of cluster nodes that use the node name formatting guidelines:
[source,terminal] ---- $ oc get nodes ---- + .Example output [source,terminal] ---- NAME STATUS ROLES AGE VERSION compute-1.example.com Ready worker 33m v1.19.0+9f84db3 control-plane-1.example.com Ready master 41m v1.19.0+9f84db3 control-plane-2.example.com Ready master 45m v1.19.0+9f84db3 compute-2.example.com Ready worker 38m v1.19.0+9f84db3 compute-3.example.com Ready worker 33m v1.19.0+9f84db3 control-plane-3.example.com Ready master 41m v1.19.0+9f84db3 ----
Note
|
Some provider-formatted hostnames include IPv4 addresses. An OpenShift Container Platform node name typically reflects the hostname of a node. If node names in your output need to be provider-specific and require this format, use private IPv4 addresses. For example, you could use |
You may include IPv4 addresses from test clusters in examples in the documentation, as long as they are private. Private IPv4 addresses fall into one of the following ranges:
-
10.0.0.0 to 10.255.255.255 (class A address block 10.0.0.0/8)
-
172.16.0.0 to 172.31.255.255 (class B address block 172.16.0.0/12)
-
192.168.0.0 to 192.168.255.255 (class C address block 192.168.0.0/16)
Replace all public IP addresses with an address from the following blocks. These address blocks are reserved for documentation:
-
192.0.2.0 to 192.0.2.255 (TEST-NET-1 address block 192.0.2.0/24)
-
198.51.100.0 to 198.51.100.255 (TEST-NET-2 address block 198.51.100.0/24)
-
203.0.113.0 to 203.0.113.255 (TEST-NET-3 address block 203.0.113.0/24)
Note
|
There might be advanced networking examples that require specific IP addresses, or cloud provider-specific examples that require a public IP address. Contact a subject matter expert if you need assistance with replacing IP addresses. |
Links can be used to cross-reference internal assemblies or send readers to external information resources for further reading.
In OpenShift docs:
-
All links to internal content is created using
xref
and must have an anchor ID. -
Only use
xref
in assemblies, not modules. -
All links to external websites are created using
link
.
Important
|
Do not split link paths across lines when wrapping text. This will cause issues with the doc builds. |
To provide an example URL path that you do not want to render as a hyperlink, use this format:
`\https://www.example.com`
Whenever possible the link to another assembly should be part of the actual sentence. Avoid creating links as a separate sentence that begins with "See [this assembly] for more information on x".
Note
|
Use the relative file path (from the file you are editing, to the file you are linking to), even if you are linking to the same directory that you are writing in. This makes search and replace operations to fix broken links much easier. For example, if you are writing in architecture/core_concepts/deployments.adoc and you want to link to architecture/core_concepts/routes.adoc then you must include the path back to the first level of the assembly directory: xref:../../architecture/networking/routes.adoc#architecture-core-concepts-routes |
Rollbacks revert part of an application back to a previous deployment. Rollbacks can be performed using the REST API or the xref:../cli_reference/openshift_cli/get_started_cli.adoc#installing-openshift-cli[OpenShift CLI]. Before you can create a domain, you must first xref:../dev_guide/application_lifecycle/new_app.adoc#dev-guide-new-app[create an application].
Rollbacks revert part of an application back to a previous deployment. Rollbacks can be performed using the REST API or the OpenShift CLI.
Before you can create a domain, you must first create an application.
If you want to link to a different website, use:
link:http://othersite.com/otherpath[friendly reference text]
Important
|
You must use link: before the start of the URL.
|
Important
|
You cannot link to a repository that is hosted on www.github.com. |
Tip
|
If you want to build a link from a URL without changing the text from the actual URL, just print the URL without adding a [friendly text] block at the end; it will automatically be rendered as a link.
|
There are two scenarios for linking to other assemblies:
-
Link to another file that exists in the same directory.
-
Link to another file that exists in a separate directory.
The following examples use the example directory structure shown here:
/ /foo /foo/bar.adoc /baz /baz/zig.adoc /baz/zag.adoc
Link to assembly in same directory
xref:<filename>#anchor-id[friendly title]
You must use the .adoc
file extension. The document processor will correctly link this to the resulting HTML file.
For example, using the above syntax, if you are working on zig.adoc
and want to link to zag.adoc
, do it this way:
xref:../zag.adoc#baz-zag[comment]
where baz-zag
is the anchor ID at the top of the file zag.adoc
.
Link to assembly in different directory
xref:../dir/<filename>.adoc#anchor-id[friendly title]
For example, if you are working on bar.adoc
and you want to link to zig.adoc
, do it this way:
xref:../baz/zig.adoc#baz-zig[see the ZIG manual for more]
Note
|
You must use the .adoc extension in order for the link to work correctly and you must specify an anchor ID. |
You can embed content hosted outside the openshift-docs
GitHub repository by using the include
directive to target the URI of a raw
file. This is helpful for cases where content frequently changes; you embed the raw
file and the content auto-updates based on the changes made to the content on its
host site.
Important
|
You are restricted to only embed files from GitHub repositories managed by the
|
For example, if you want to embed the 01_vnet.json template, include the URI of its raw file version like this:
.`01_vnet.json` ARM template
[source,json]
----
include::https://raw.githubusercontent.com/openshift/installer/release-4.8/upi/azure/01_vnet.json[]
----
Note
|
Embedding external files is restricted for files that change frequently, like templates. You must ensure that embedded files are QE verified before they are updated on their host site. |
Note
|
You must get approval from the Engineering, QE, and Docs teams before embedding an external file. |
To indicate that a feature is in Technology Preview, include the snippets/technology-preview.adoc
file in the feature’s assembly or module to keep the supportability wording consistent across Technology Preview features. Provide a value for the :FeatureName:
variable before you include this module.
:FeatureName: The XYZ plug-in
include::snippets/technology-preview.adoc[]
To indicate that a feature is deprecated, include the modules/deprecated-feature.adoc
file in the feature’s assembly, or to each relevant assembly such as for a deprecated Operator, to keep the supportability wording consistent across deprecated features. Provide a value for the :FeatureName:
variable before you include this module.
See an example of how this is applied.
All documentation changes must be verified by a QE team associate before merging. This includes executing all "Procedure" changes and confirming expected results. There are exceptions for typo-level changes, formatting-only changes, and other negotiated documentation sets and distributions.
If a documentation change is due to a Bugzilla bug or Jira issue, the bug/issue should be put on ON_QA when you have a PR ready. After QE approval is given (either in the bug/issue or in the PR), the QE associate should move the bug/issue status to VERIFIED, at which point the associated PR can be merged. It is also ok for the assigned writer to change the status of the bug/issue to VERIFIED if approval for the changes has been provided in another forum (slack, PR, or email). The writer should indicate that the QE team approved the change as a comment in the bug/issue.
To include a block image (an image on its own line):
-
Put the image file in the
images
folder.Ensure that the folder containing your assembly contains an
images
symbolic link to the top-levelimages/
directory, otherwise the image will not be found when building the docs. -
In the
.adoc
content, use this format to link to the image:image::<image_filename>[<alt_text>]
Note the double
::
instead of a single:
, as seen in inline image usage. You only have to specify<image_filename>
itself and not the full file path; the build mechanism automatically expands this appropriately.
Inline images can be used to indicate graphic items in the web console, such as buttons or menu icons.
To simplify reuse, the following common SVGs (the OpenShift web console uses the
Font Awesome icon set) have already been added to the images
folder with a
user-defined entity added to the common-attributes.adoc
module:
Icon | Entity | Alt text | File name |
---|---|---|---|
Kebab |
|
Options menu |
|
When using inline, include the image after the UI element name. For example:
Click the *Options* menu {kebab}.
If you are inserting an image that is not part of the common-attributes.adoc
module, then include the image using this formatting:
image:<image_filename>[title="<alt_text>"]
Note the single :
instead of a double ::
, as seen in block image usage.
For example:
image:manage-columns.png[title="Manage Columns icon"]
For all of the system blocks including table delimiters, use four characters. For example:
|=== for tables ---- for code blocks
Note
|
You can use backticks or other markup in the title for a block, such as a code block |
Code blocks are generally used to show examples of command syntax, example screen output, and configuration files.
The main distinction between showing command syntax and a command example is that a command syntax shows readers how to use the command without real values. An example command, however, shows the command with actual values with an example output of that command, where applicable.
For example:
In the following example, the `oc get` operation returns a complete list of services that are currently defined: [source,terminal] ---- $ oc get se ---- .Example output [source,terminal] ---- NAME LABELS SELECTOR IP PORT kubernetes component=apiserver,provider=kubernetes <none> 172.30.17.96 443 kubernetes-ro component=apiserver,provider=kubernetes <none> 172.30.17.77 80 docker-registry <none> name=registrypod 172.30.17.158 5001 ----
This renders as:
In the following example, the
oc get
operation returns a complete list of services that are currently defined:$ oc get seExample outputNAME LABELS SELECTOR IP PORT kubernetes component=apiserver,provider=kubernetes <none> 172.30.17.96 443 kubernetes-ro component=apiserver,provider=kubernetes <none> 172.30.17.77 80 docker-registry <none> name=registrypod 172.30.17.158 5001
The following guidelines go into more detail about specific requirements and recommendations when using code blocks:
-
If a step in a procedure is to run a command, make sure that the step text includes an explicit instruction to "run" or "enter" the command. In most cases, use one of the following patterns to introduce the code block:
-
<Step description> by running the following command:
-
<Step description> by entering the following command:
-
<Step description>, run the following command:
-
<Step description>, enter the following command:
-
-
Do NOT use any markup in code blocks; code blocks generally do not accept any markup.
-
For all code blocks, you must include an empty line above a code block (unless that line is introducing block metadata, such as
[source,terminal]
for syntax highlighting).Acceptable:
Lorem ipsum ---- $ lorem.sh ----
Not acceptable:
Lorem ipsum ---- $ lorem.sh ----
Without the line spaces, the content is likely to be not parsed correctly.
-
Use
[source,terminal]
foroc
commands or any terminal commands to enable syntax highlighting. Any[source]
metadata must go on the line directly before the code block. For example:[source,terminal] ---- $ oc get nodes ----
If you are also showing a code block for the output of the command, use
[source,terminal]
for that code block as well. -
Use source tags for the programming language used in the code block to enable syntax highlighting. For example:
-
[source,yaml]
-
[source,go]
-
[source,javascript]
-
-
Do not use more than one command per code block. For example, the following must be split up into three separate code blocks:
To create templates you can modify, run the following commands: [source,terminal] ---- $ oc adm create-login-template > login.html ---- [source,terminal] ---- $ oc adm create-provider-selection-template > providers.html ---- [source,terminal] ---- $ oc adm create-error-template > errors.html ----
-
If your command contains multiple lines and uses callout annotations, you must comment out the callout(s) in the codeblock, as shown in the following example:
To scale based on the percent of CPU utilization, create a `HorizontalPodAutoscaler` object for an existing object: [source,terminal] ---- $ oc autoscale <object_type>/<name> \// (1) --min <number> \// (2) --max <number> \// (3) --cpu-percent=<percent> (4) ---- <1> Specify the type and name of the object to autoscale. <2> Optional: Specify the minimum number of replicas when scaling down. <3> Specify the maximum number of replicas when scaling up. <4> Specify the target average CPU utilization over all the pods, represented as a percent of requested CPU.
-
Separate a command and its related example output into individual code blocks. This allows the command to be easily copied using the button on docs.openshift.com.
In addition, prepend the code block for the output with the title
.Example output
to make it consistently clear across the docs when this is being represented. A lead-in sentence explaining the example output is optional. For example:Use the `oc new-project` command to create a new project: [source,terminal] ---- $ oc new-project my-project ---- The output verifies that a new project was created: .Example output [source,terminal] ---- Now using project "my-project" on server "https://openshift.example.com:6443". ----
-
To mark up command syntax, use the code block and wrap any replaceable values in angle brackets (
<>
) with the required command parameter, using underscores (_
) between words as necessary for legibility. Do not italicize user-replaced values. For example:To view a list of objects for the specified object type, enter the following command: [source,terminal] ---- $ oc get <object_type> <object_id> ----
This renders as:
To view a list of objects for the specified object type, enter the following command:
$ oc get <object_type> <object_id>
NoteAvoid using full command syntax inline with sentences. -
When referring to a path to a location that the user has selected or created, treat the part of the path that the user chose as a replaceable value. For example:
Create a secret that contains the certificate and key in the `openshift-config` namespace: [source,terminal] ---- $ oc create secret tls <certificate> --cert=<path_to_certificate>/cert.crt --key=<path_to_key>/cert.key -n openshift-config ----
This renders as:
Create a secret that contains the certificate and key in the
openshift-config
namespace:$ oc create secret tls <certificate> --cert=<path_to_certificate>/cert.crt --key=<path_to_key>/cert.key -n openshift-config
The following example shows a more complex use of user-chosen elements and prescriptive placement:
<resource_group_name>/providers/Microsoft.Compute/diskEncryptionSets/<disk_encryption_set_name>
-
If you must provide additional information on what a line of a code block represents, use callouts (
<1>
,<2>
, etc.) to provide that information.Use this format when embedding callouts into the code block:
---- code example 1 <1> code example 2 <2> ---- <1> A note about the first example value. <2> A note about the second example value.
-
If you must provide additional information on what a line of a code block represents and the use of callouts is impractical, you can use a description list to provide information about the variables in the code block. Using callouts might be impractical if a code block contains too many conditional statements to easily use numbered callouts or if the same note applies to multiple lines of the codeblock.
---- code <variable_1> code <variable_2> ---- + where: <variable_1>:: Specifies the explanation of the first variable. <variable_2>:: Specifies the explanation of the first variable.
Be sure to introduce the description list with "where:" and start each variable description with "Specifies."
-
For long lines of code that you want to break up among multiple lines, use a backslash to show the line break. For example:
$ oc get endpoints --all-namespaces --template \ '{{ range .items }}{{ .metadata.namespace }}:{{ .metadata.name }} \ {{ range .subsets }}{{ range .addresses }}{{ .ip }} \ {{ end }}{{ end }}{{ "\n" }}{{ end }}' | awk '/ 172\.30\./ { print $1 }'
-
If the user must run a command as root, use a number sign (
#
) at the start of the command instead of a dollar sign ($
). For example:# subscription-manager list
-
For snippets or sections of a file, use an ellipsis (
…
) to show that the file continues before and/or after the quoted block.apiVersion: v1 kind: Pod metadata: labels: test: liveness ...
or
Name: ci-ln-iyhx092-f76d1-nvdfm-worker-b-wln2l Roles: worker ... Taints: node-role.kubernetes.io/infra:NoSchedule ...
Do not use
[…]
,<snip>
, or any other variant. -
Do not use
jq
in commands (unless it is truly required), because this requires users to install thejq
tool. Oftentimes, the same or similar result can be accomplished usingjsonpath
foroc
commands.For example, this command that uses
jq
:$ oc get clusterversion -o json|jq ".items[0].spec"
can be updated to use
jsonpath
instead:$ oc get clusterversion -o jsonpath='{.items[0].spec}{"\n"}'
-
For Bash "here" documents use
[source,terminal]
, such as the following example:[source,terminal] ---- $ cat <<EOF| oc create -f - apiVersion: v1 kind: Pod metadata: name: mlistener labels: app: multicast-verify EOF ----
-
For the output of commands use
[source,text]
, such as with the following example output from theoc describe <pural> <object>
command:[source,text] ---- Name: node1.example.com Roles: worker Labels: beta.kubernetes.io/arch=amd64 ... Annotations: cluster.k8s.io/machine: openshift-machine-api/ahardin-worker-us-east-2a-q5dzc ... CreationTimestamp: Wed, 13 Feb 2019 11:05:57 -0500 ----
The following formatting guidelines apply to YAML manifests, but do not apply to the installation configuration YAML specified by install-config.yaml
.
When possible, ensure that YAML is valid in a running cluster. You can validate YAML with oc apply
with the following invocation:
$ oc apply -f test.yaml --dry-run=client
-
Include the
apiVersion
andkind
so that a user always knows the context of the YAML. -
Include the full hierarchy to a deeply nested key.
-
For objects that are in the global scope, such as for
config.openshift.io
API group, always include themetadata.name
for the object, which is usuallycluster
.
apiVersion: config.openshift.io/v1 kind: Scheduler metadata: name: cluster ... spec: defaultNodeSelector: node-role.kubernetes.io/app= ...
.ports
arrayapiVersion: v1 kind: Pod metadata: name: pod1 namespace: default spec: containers: - name: web image: nginx ports: - name: web containerPort: 80 protocol: TCP
Use the following conventions govern the layout of YAML for API objects.
-
Begin YAML at the beginning of the left margin.
-
Use two-space indentation.
-
Indent arrays at the same depth as the parent field.
-
Include a space immediately after the colon for keys.
-
Use block style for complex strings, such as embedded JSON or text blocks. You can enable block style by specifying
|
or|-
after a field and indenting the field content by two spaces, such as in the following example:fieldName: |- This is a string. And it can be on multiple lines.
-
When truncating YAML, always precede an ellipsis with a pound so that the YAML is valid.
apiVersion: v1 kind: Pod metadata: name: pod1 labels: - key1: val1 - key2: val2 spec: ...
apiVersion: v1 kind: Pod metadata: name: pod1 annotations: k8s.v1.cni.cncf.io/networks: |- [ { "name": "net" } ] spec: ...
Do NOT show full commands or command syntax inline within a sentence. The next section covers how to show commands and command syntax.
Only use case for inline commands would be general commands and operations, without replaceables and command options. In this case an inline command is marked up using the back ticks:
Use the `GET` operation to do x.
This renders as:
Use the
GET
operation to do x.
System messages include error, warning, confirmation, and information messages that are presented to the user in places such as the GUI, CLI, or system logs.
If a message is short enough to include inline, enclose it in back ticks:
Previously, image builds and pushes would fail with the `error reading blob from source` error message because the builder logic would compute the contents of new layers twice.
This renders as:
Previously, image builds and pushes would fail with the
error reading blob from source
error message because the builder logic would compute the contents of new layers twice.
If a message is too long to include inline, put it inside a code block with [source,text]
metadata:
Previously, the AWS Terraform provider that the installation program used occasionally caused a race condition with the S3 bucket, and the cluster installation failed with the following error message: [source,text] ---- When applying changes to module.bootstrap.aws_s3_bucket.ignition, provider level=error msg="\"aws\" produced an unexpected new value for was present, but now absent. ---- Now, the installation program uses different AWS Terraform provider code, which now robustly handles S3 eventual consistency, and the installer-provisioned AWS cluster installation does not fail with that error message.
This renders as:
Previously, the AWS Terraform provider that the installation program used occasionally caused a race condition with the S3 bucket, and the cluster installation failed with the following error message:
When applying changes to module.bootstrap.aws_s3_bucket.ignition, provider level=error msg="\"aws\" produced an unexpected new value for was present, but now absent.Now, the installation program uses different AWS Terraform provider code, which now robustly handles S3 eventual consistency, and the installer-provisioned AWS cluster installation does not fail with that error message.
Note
|
Always refer to a message with the type of message it is, followed by the word "message". For example, refer to an error message as an "error message", and not simply as an "error". |
Lists are created as shown in this example:
. Item 1 (2 spaces between the period and the first character) . Item 2 . Item 3
This renders as:
Item 1
Item 2
Item 3
If you must add any text, admonitions, or code blocks you have to add the continuous +, as shown in the example:
. Item 1 + ---- some code block ---- . Item 2 . Item 3
This renders as:
Item 1
some code blockItem 2
Item 3
Avoid footnotes when possible.
If you reference a footnote from only a single location, use the following syntax:
footnote:[This is the footnote text.]
If you reference a footnote from multiple locations, set an attribute with the footnote text. As a consequence, this will duplicate the footnote text at bottom of the page.
:note-text: This is a footnote. This text has a footnote qualifier attached footnote:[{note-text}]. But this other text uses the same qualifier elsewhere footnote:[{note-text}].
Avoid using footnoteref
.
Important
|
The |
footnoteref:[ref-string, This is the footnote text.]
For footnotes in tables, use the following syntax to mimic Asciidoctor’s styling:
[cols="3",options="header"] |=== |Header 1 |Header 2 |Header 3 |Item A ^[1]^ |Item B |Item C ^[2]^ |Item D |Item E ^[3]^ |Item F ^[3]^ |=== [.small] -- 1. A description. 2. Another description. 3. Two items relate to this description. --
The notes are kept immediately after the table, instead of moved to the bottom of the rendered assembly. This manual method also allows you to reuse the same footnote number for multiple references as needed.
Note the following:
-
Add a space before the superscripted numbers with square brackets.
-
To match the table cell’s font size, start the ordered list with a
[.small]
style and wrap it in a--
block.
You can collapse sections of content by using the collapsible
option, which converts the Asciidoctor markup to HTML details
and summary
sections. The collapsible
option is used at the writer’s discretion and is appropriate for considerably long code blocks, lists, or other such content that significantly increases the length of a module or assembly.
Note
|
You must set a title for the |
Collapsible content is formatted as shown:
.Title of the `summary` dropdown [%collapsible] ==== This is content within the `details` section. ====
This renders as a dropdown with collapsed content:
Title of the summary
dropdown
This is content within the details
section.
If your collapsible content includes an admonition such as a note or warning, the admonition must be nested:
.Collapsible content that includes an admonition [%collapsible] ==== This content includes an admonition. [source,terminal] ---- $ oc whoami ---- [NOTE] ===== Nest admonitions when using the `collapsible` option. ===== ====
This renders as:
Collapsible content that includes an admonition
This content includes an admonition.
$ oc whoami
Note
|
Nest admonitions when using the |
Markup in command syntax | Description | Substitute value in Example block |
---|---|---|
|
Name of user account |
|
|
User password |
password |
Markup in command syntax | Description | Substitute value in Example block |
---|---|---|
|
Name of project |
myproject |
|
Name of an application |
myapp |
The following guidelines apply to all "Additional resources" sections:
-
You must include the
[role="_additional-resources"]
attribute declaration before the section heading. -
You must not include paragraphs in the section. Use an unordered list.
-
The links and xrefs in the unordered list must contain human-readable text between the square brackets.
-
Each item in the unordered list must contain a minimum of text besides the link or xref.
Additionally, in an assembly, use ==
formatting for the section heading (== Additional resources
). Use of this heading syntax at the assembly level indicates that the sections relate to the whole assembly. For example:
[role="_additional-resources"] [id="additional-resources_configuring-alert-notifications"] == Additional resources * link:some-url.com[Human readable label] * xref:some_xref[Human readable label] * xref:some_other_xref[Human readable label]
Only use .
formatting (.Additional resources
) in a module or to follow a module in an assembly. Because you cannot use the xrefs in modules, this functions as a trailing include at the assembly level, where the .
formatting of the include
statement indicates that the resource applies specifically to the module and not to the assembly. For example:
[role="_additional-resources"] .Additional resources * link:some-url.com[Human readable label] * xref:some_xref[Human readable label] * xref:some_other_xref[Human readable label]
Admonitions such as notes and warnings are formatted as shown:
[ADMONITION] ==== Text for admonition ====
For terms that are API objects, the way they are written depends on whether the term is a general reference or an actual reference to the object.
A general reference is any time you are speaking conceptually, or generally, about these components in a cluster.
When referring to API object terms in general usage, use lowercase and separate multi-word API objects. Default to following this guidance unless you are specifically interacting with/referring to the API object (see Object references).
For example:
-
pod
-
node
-
daemon set
-
config map
-
deployment
-
image stream
-
persistent volume claim
Kubernetes runs your workload by placing containers into pods to run on nodes. You must have at least one secret, config map, or service account. The total number of persistent volume claims in a project.
Note that if an object uses an acronym or other special capitalization, then its general reference should honor that. For example, general references to APIService
should be written as "API service", not "api service". Any other exceptions or special guidance are noted in the glossary.
An object reference is when you are referring to the actual instance of an API object, where the object name is important.
When referring to actual instances of API objects, use PascalCase and mark it up as monospace in backticks (``
).
Note
|
Do not use backticks or other markup in assembly or module headings. You can use backticks or other markup in the title for a block, such as a code block |
Be sure to match the proper object type (or kind
in Kubernetes terms); for example, do not add an "s" to make it plural. Only follow this guidance if you are explicitly referring to the API object (for example, when editing an object in the CLI or viewing an object in the web console).
For example:
-
Pod
-
Node
-
DaemonSet
-
ConfigMap
-
Deployment
-
ImageStream
-
PersistentVolumeClaim
After you create a `Node` object, or the kubelet on a node self-registers, the control plane checks whether the new `Node` object is valid. The default amount of CPU that a container can use if not specified in the `Pod` spec. Create a file, `pvc.yaml`, with the `PersistentVolumeClaim` object definition.
Note
|
Use "object", "resource", "custom resource", "spec", etc. as appropriate after the object reference. This helps with clarity and readability. Another situation where this is necessary is when referring to the plural version of objects. Do not add an "s" to the end of an object name reference to make it plural. Use only the official For example, the object |
The term "Operator" is always capitalized. For example:
= Support policy for unmanaged Operators Individual Operators have a `managementState` parameter in their configuration.
An Operator’s full name must be a proper noun, with each word initially capitalized. If it includes a product name, defer the product’s capitalization style guidelines. For example:
-
Red Hat OpenShift Logging Operator
-
Prometheus Operator
-
etcd Operator
-
Node Tuning Operator
-
Cluster Version Operator
Many of our procedures provide imperative oc
commands (which cannot be stored in a Git repo). Due to efforts around improving the experience for GitOps users, we sometimes also want to provide a declarative YAML example that achieves the same configuration. This allows users to store these YAML configurations in a Git repo and follow GitOps practices to configure OpenShift.
Important
|
When adding declarative examples to procedures, do not completely replace the imperative command with the declarative YAML example. Some users might still prefer the imperative option. |
To add a declarative YAML example to a procedure step with an existing imperative command, add it in a "TIP" admonition by following the template in the example below. This example uses an imperative command (oc create configmap
) to create a config map, and then provides the declarative YAML example of the ConfigMap
object afterward.
* Define a `ConfigMap` object containing the certificate authority by using the following command: + [source,terminal] ---- $ oc create configmap ca-config-map --from-file=ca.crt=/path/to/ca -n openshift-config ---- + [TIP] ==== You can alternatively apply the following YAML to create the config map: [source,yaml] ---- apiVersion: v1 kind: ConfigMap metadata: name: ca-config-map namespace: openshift-config type: Opaque data: ca.crt: <base64_encoded_CA_certificate_PEM> ---- ====
This renders as:
Define a
ConfigMap
object containing the certificate authority by using the following command:$ oc create configmap ca-config-map --from-file=ca.crt=/path/to/ca -n openshift-config
TipYou can alternatively apply the following YAML to create the config map:
apiVersion: v1 kind: ConfigMap metadata: name: ca-config-map namespace: openshift-config type: Opaque data: ca.crt: <base64_encoded_CA_certificate_PEM>
Note
|
If you are adding a particularly long YAML block, you can optionally use the |
Convention | Markup | Example rendered output |
---|---|---|
Code blocks |
Use the following syntax for the `oc` command: ---- $ oc <action> <object_type> <object_name_or_id> ---- |
|
Use backticks for all non-GUI "system items", including:
|
`oc get` Set the `upgrade` variable to `true`. Use the `--amend` flag. Answer by typing `Yes` or `No` when prompted. `user_name` `service_name` `package_name` `filename` |
|
System or software variable to be replaced by the user |
`<project>` `<deployment>` `<install_mode_value>` |
|
Use single asterisks for web console / GUI items (menus, buttons, page titles, etc.).
Use two characters to form the arrow in a series of menu items ( |
Choose *Cluster Console* from the list. Navigate to the *Operators* -> *Catalog Sources* page. Click *Create Subscription*. |
|
Use underscores to emphasize the first appearance of a new term. |
An _Operator_ is a method of packaging, deploying, and managing a Kubernetes application. |
|
Use of underscores for general emphasis is allowed but should only be used very sparingly. Let the writing, instead of font usage, create the emphasis wherever possible. |
Do _not_ delete the file. |
|
Footnotes |
A footnote is created with the footnote macro. If you plan to reference a footnote more than once, use the ID footnoteref macro. The Customer Portal does not support spaces in the footnoteref. For example, "dynamic PV" should be "dynamicPV". |
See Footnotes for the footnote and footnoteref syntax. |