Working with Use Case Templates

Learn how to use NGINX Management Suite App Delivery Manager to create reusable templates that let you easily configure NGINX instances to meet the needs of your applications.

Overview

This document provides an in-depth guide to implementing two specific use cases within a given environment, focusing on extending capabilities and customization.

  • Use Case #1: Adding a Dynamic Module

    The first use case involves making the Headers-More dynamic module available to all instance groups. Detailed steps explain how to add the load_module directive to each NGINX configuration file. The process includes creating the necessary subdirectories, use case templates, and adding directives, then enabling the use case in the desired environment. The detailed instructions ensure users do not modify base templates and instead use a use case template to accomplish the goal.

  • Use Case #2: Expand the Gateway REST API

    In the second use case, the Gateway API is extended to allow adding comments to HTTP server blocks generated by the Gateway. This enhancement can be applied to all server blocks or specific URIs. The steps include creating a use case subdirectory; crafting a use case template that can access gateway details; defining a JSON schema for evaluating the template input fields; enabling the use case in the environment; and adding comments to the gateway.


Use Case #1: Adding a Dynamic Module

Objective

For this scenario, the platform team wants to give all instances groups within an environment access to the Headers-More dynamic module. This involves adding the load_module directive to each instance’s NGINX configuration file. Even though it’s possible to add this command to the f5-v1-instance-group.tmpl template, we don’t recommend changing the basic templates. The best way to accomplish the same goal is to use a use case template. You can find more details on how to do this below.

Create the Use Case Subdirectory

Note:
The following steps require root privileges.

First, create a subdirectory with the use case name headers-more under /etc/nms/modules/adm/templates/usecases:

cd /etc/nms/modules/adm/templates/usecases
mkdir headers-more

Create the Use Case Template

Next, create a use case template called main-instance-group.tmpl. This use case template will be called from the base template f5-v1-instance-group.tmpl, at the injection point in the main context. The base template already defines this injection point {{ $input.ExecUseCaseTemplates "main" }}.

cd headers-more
vi main-instance-group.tmpl

Add the following content to the template file (comments are optional):

{{/* Invoked from Instance Group base template. Directives specified here go in to the "main" context. */}}
load_module modules/ngx_http_headers_more_filter_module.so;

Enable the use case in the Environment

At this point, you have created a use case that enables the Headers-More module, but the environment has not been configured to use it. The last step is to choose the use case for the environment you want to modify. You can do this by creating a new environment object or modifying an existing one, and then enabling the use case template:


Web Interface

Enabling a use case in the web interface

API

POST/api/adm/v1/environments
{
  "metadata": {
    "name": "env1",
    "tags": []
  },
  "useCases": [
    {
      "templateGroupRef": {
        "ref": "headers-more"
      }
    }
  ]
}

Note:
The Headers-More module must be installed on all NGINX instances within the instance groups used by the environment. Otherwise, NGINX reports an error when loading the module. Also, at this stage, we’ve only enabled the module’s use. More changes are required in the use case to give app developers the capability to use the newly accessible directives like more-clear-headers. Refer to the provided f5-headers-v1 use case as a guideline to follow when adding these directives.

Use Case #2: Expand the Gateway REST API

Objective

This use case extends the Gateway API, giving you the ability to add comments into the HTTP server blocks created by the Gateway. You can do this in two distinct ways:

  • By adding comments in the top-level customExtensions, they will be displayed in all server blocks that the Gateway generates.
  • By putting comments in a hostname URI customExtensions, they will only show up in the server block linked to that particular URI.

Create the Use Case Subdirectory

Note:
The following steps will require root privileges

First, create a subdirectory with the use case name gateway-comments under /etc/nms/modules/adm/templates/usecases:

cd /etc/nms/modules/adm/templates/usecases
mkdir gateway-comments

Create the Use Case Template

Next, create a use case template called server-gateway.tmpl. This use case template will be called from the gateway base template f5-v1-gateway.tmpl, at the injection point in the server block context. The base template already defines this injection point {{ $input.ExecUseCaseTemplates "server" $serverIndex}}.


cd gateway-commentsvi server-gateway.tmpl

The use case template can access the input and details of the gateway template. The following example shows how to:

  • Get the input from the gateway template.
  • Get the index of the server block being rendered and retrieve its details.
  • Get the top-level customExtension.
  • Get the customExtension at the hostname level.

{{$input := .}}
{{$gwData := .Data.V1}}
{{$serverIndex := index $input.Args 0}}
{{$server := index $gwData.servers $serverIndex}}

{{$topCe := $gwData.customExtensions}}
{{$uriCe := $server.customExtensions}}

Now you can implement custom logic using this data. In this example, we will add comments using the logic shown below:

{{if and $topCe $topCe.commentsUsecase  $topCe.commentsUsecase.allUriComments}}
    {{range $comment := $topCe.commentsUsecase.allUriComments}}
        # {{$comment}}
    {{end}}
{{end}}

{{if and $uriCe $uriCe.commentsUsecase  $uriCe.commentsUsecase.uriSpecificComments}}
    {{range $comment := $uriCe.commentsUsecase.uriSpecificComments}}
        # {{$comment}}
    {{end}}
{{end}}

Create the Schema

As a final step, a JSON schema needs to be created to evaluate the template input fields that will be added to the Gateway API. These additional fields will be displayed in the web interface as well.

Create file gateway.json in the same use case:

vi gateway.json

Describe the API and validation needed in the JSON schema as shown below:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
        "v1": {
            "type": "object",
            "properties": {
                "customExtensions": {
                    "type": [
                        "object",
                        "null"
                    ],
                    "properties": {
                        "commentsUsecase": {
                            "type": "object",
                            "title": "Gateway Comment Use Case",
                            "description": "Add comments to all server blocks",
                            "properties": {
                                "allUriComments": {
                                    "type": "array",
                                    "title": " All Server Block Comments ",
                                    "items": {
                                        "type": "string",
                                        "maxLength": 40
                                    }
                                }
                            }
                        }
                    }
                },
                "servers": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "customExtensions": {
                                "type": "object",
                                "properties": {
                                    "commentsUsecase": {
                                        "type": "object",
                                        "title": "Gateway Comment Use Case",
                                        "description": "Add comments to the associated server block",
                                        "properties": {
                                            "uriSpecificComments": {
                                                "type": "array",
                                                "title": " Hostname URI Comments ",
                                                "items": {
                                                    "type": "string",
                                                    "maxLength": 40
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "required": []
}

Enable the Use Case in the Environment

Your use case is fully functional, but the environment has not been configured to use it. You need to choose the use case for the environment you want. You can do this by creating a new environment object or modifying an existing one, and then enabling the use case template:


Web Interface

Enabling a use case in the web interface

API

POST/api/adm/v1/environments
{
  "metadata": {
    "name": "env1",
    "tags": []
  },
  "useCases": [
    {
      "templateGroupRef": {
        "ref": "gateway-comments"
      }
    }
  ]
}

Add Comments to the Gateway

The final step involves creating or changing a gateway and adding comments to the Hostname URIs.

In the web interface, you should now see a “Custom Extensions” section that looks like the one below when you create or change a gateway in the environment where the use case template is enabled. Now, you can create various hostnames and include comments that can be applied to all hostnames or specific ones.


Web Interface

Enabling a use case in the web interface

API

Below is an example API call to add several hostname URIs and comments:

POST/api/adm/v1/environments/1816b7a6-ab64-4775-8f8c-4f31f4b9ceef/gateways
{
  "metadata": {
    "name": "gw1",
    "tags": []
  },
  "ingress": {
    "uris": [
      {
        "uri": "http://acme.com:8000",
        "customExtensions": {
          "commentsUsecase": {
            "uriSpecificComments": [
              "Sales"
            ]
          }
        }
      },
      {
        "uri": "http://acme.com:8001",
        "customExtensions": {
          "commentsUsecase": {
            "uriSpecificComments": [
              "Inventory"
            ]
          }
        }
      }
    ]
  },
  "customExtensions": {
    "commentsUsecase": {
      "allUriComments": [
        "This is just an example"
      ]
    }
  }
}

The resulting NGINX configuration would look like the following:

# Created by Gateway: gw1(a45bcad1-a55b-4e94-b7ae-797e522db541)
server {
    server_name acme.com;
    listen 8000 reuseport;
    # This is just an example
    # Sales
    location / {
        return 404;
    }
}
# Created by Gateway: gw1(a45bcad1-a55b-4e94-b7ae-797e522db541)
server {
    server_name acme.com;
    listen 8001 reuseport;
    # This is just an example
    # Inventory
    location / {
        return 404;
    }
}

Final Touches: Documentation

To finalize the use cases mentioned earlier, we suggest creating two optional files in the use case directory related to documentation:

  • README.md – This document should summarize the use case, and you can view it in the web interface when creating or modifying an environment.
  • USAGE.md – This document is aimed at app developers, offering in-depth explanations for each variable that the use case defines.

Starting Point for Custom Use Cases

App Delivery Manager includes example use cases that resemble those discussed above. These examples are named f5-load-modules-v1-example and f5-gateway-comments-v1-example, respectively.

In addition, App Delivery Manager includes a more generic f5-empty-v1-example use case. This particular example contains all the potential templates and schema files that a use case might require and serves as a great starting point for developing and experimenting with your own use cases. Any files that are not needed can be deleted.