# Generated parameter options

> Build a parameter's option list at runtime from a plugin

---

Site [llms.txt](/llms.txt)

---

A parameter's options can be generated by an orchestration action rather than entered by hand. In Cloud Management Platform (CMP) there are two ways to do this: add an orchestration action whose job is to generate the options, or, when the parameter is an action input on a plugin, generate them from inside that plugin.

## Plugins that generate parameter options

Both approaches need a plugin attached to the **Generated Parameter Options** trigger point and associated with the parameter in question. There are two ways for that plugin to return its options:

- **Synchronously**: the plugin returns all options at once, rendered as a dropdown. The plugin must implement `get_options_list(custom_field, **kwargs)`.
- **Asynchronously**: the plugin returns only the options matching what the user has typed. The plugin must implement `suggest_options(custom_field, query, **kwargs)`, where `query` is the string the user has typed. A plugin that implements `suggest_options` must also define `get_options_list(custom_field, **kwargs)`, which can simply `return None`. See [Suggest options as the user types](#suggest-options-as-the-user-types).

`get_options_list` must return a list or a dictionary. Returning anything else raises an error naming the plugin. For what the dictionary form can contain, see [Option return formats](/docs/cmp/configure/order-forms-and-pricing/parameters/generated-options/option-return-formats/).

To create the plugin, see [Set up a generated parameter options action](#set-up-a-generated-parameter-options-action) below.

## Suggest options as the user types

A plugin that defines `suggest_options` turns the parameter into a search field. As the user types, CMP calls `suggest_options` and shows returned options. Define `suggest_options` as a top-level function in the plugin:

```python
def suggest_options(custom_field, query, **kwargs):
```

- `custom_field`: the parameter the options are for.
- `query`: the text the user has typed. Can be empty or `None`. Keep the name `query`; [custom forms](/docs/cmp/configure/order-forms-and-pricing/custom-forms/) pass it by name.

The group, environment, user, and other form values are not available to `suggest_options`. CMP also does not apply the plugin's environment, group, or resource technology constraints when it calls `suggest_options`, so associate only one `suggest_options` plugin with each parameter.

Return a list of `(value, label)` tuples. Unlike `get_options_list`, `suggest_options` cannot return a dictionary or plain strings.

This example filters a fixed list of regions by what the user types:

```python
# Required even when the plugin only suggests options.
def get_options_list(custom_field, **kwargs):
    return None


def suggest_options(custom_field, query, **kwargs):
    regions = [
        ("us-east-1", "US East (N. Virginia)"),
        ("us-east-2", "US East (Ohio)"),
        ("us-west-1", "US West (N. California)"),
        ("us-west-2", "US West (Oregon)"),
        ("eu-west-1", "Europe (Ireland)"),
    ]
    if not query:
        return regions

    query = query.lower()
    return [
        (value, label)
        for value, label in regions
        if query in value.lower() or query in label.lower()
    ]
```

## Plugins that generate action input options {#action-input-options}

When option generation is embedded in a plugin, the method signature is `generate_options_for_<action_input_name>(**kwargs)`. The method name depends on the action input's name, with any `_a<number>` suffix stripped. Learn more about action inputs in [Plugins](/docs/cmp/use/orchestration/plugins/).

When naming these action inputs, consider which inputs already have values supplied in that context. If an action input is already provided, option generation does not apply to it. Several CMP objects may be available as context for template-enabled action attributes, such as environment, group, and profile. See the [Action context table](/docs/cmp/use/orchestration/actions/action-context/).

Generated options are still filtered against any options defined in the UI, and only options present in both are used. To bypass that filtering, return a dictionary with `override` set to `True`, as described in [Option return formats](/docs/cmp/configure/order-forms-and-pricing/parameters/generated-options/option-return-formats/).

For how UI-defined lists combine, see [Static options](/docs/cmp/configure/order-forms-and-pricing/parameters/static-options/).

## Keyword arguments available to these methods

Which keyword arguments a method receives depends on the context in which it is called. These keyword arguments do not apply to `suggest_options`, which receives only the parameter and the typed text.

| Keyword | Available when |
| --- | --- |
| `group` | Setting options on a group; ordering a blueprint; modifying a server; modifying a resource. |
| `environment` | Setting options on an environment; ordering a blueprint — for build items that have an environment, such as server tiers; modifying a server. |
| `blueprint` | Ordering a blueprint; setting options on a blueprint; modifying a resource; modifying a server, if that server was provisioned from a blueprint on the same CMP instance. Discovered servers are not associated with a blueprint. |
| `server` | Modifying a server. |
| `servers` | Modifying more than one server at once. |
| `resource` | Modifying a resource. |
| `resources` | Modifying more than one resource at once. |
| `profile` | All contexts. Represents the currently logged-in user. |
| `recipient` | Any context involving an order, a server, or a resource. A `userprofile` object for the recipient of a blueprint order, either the current order at ordering time or a past one otherwise, such as the order that provisioned the server being modified. |
| `service_item` | Generating options for a blueprint's service item. |

## Set up a generated parameter options action

1. Go to **Admin** > **Orchestration Actions**.
1. In the tree filter on the left, select **Parameters** > **Generated Parameter Options**.
1. Select **Add Generated Parameter Options Action**. The button appears once a single trigger point is selected.
1. Select **CloudBolt Plug-in**, then select **Add a new CloudBolt plug-in**.
1. Complete the form, making sure to select the parameter from the **Custom fields** dropdown.
1. Select **Save**.

## Set up a regenerated options dependency

A dependent parameter's options can be rebuilt whenever a controlling parameter's value changes. All of the configuration happens on the dependent parameter; the controlling parameter needs no changes of its own. For the other kinds of dependency, see [Parameter options](/docs/cmp/configure/order-forms-and-pricing/parameters/parameter-options/).

1. Go to **Admin** > **Parameters**.
1. Create two parameters: one is the controlling field, and the other is the dependent field.
1. Set up the dependency relationship:
    1. Open the detail page of the *dependent* parameter.
    1. In the **Dependencies** section, select **Add a dependency**.
    1. Select the **Controlling field** and set **Dependency type** to **Regenerate Options**.
    1. Select **Create**.
1. On the same page, in the **Programmatically Generated Options** section, select **Add an Action**. CMP either creates a plugin associated with this parameter at the Generated Parameter Options trigger point and opens the plugin's detail page, or opens the detail page for an existing plugin.
1. Write the plugin code. It must define `get_options_list` and accept keyword arguments including `field` (the dependent field) and `control_value` or `control_values` (the controlling field). Options must be a list of values or `(value, label)` tuples, returned either directly or under the `options` key of a dictionary.
1. Select **Save Code**.

## Examples

### Example 1: a simple case

A regenerated options dependency where you select one value for the controlling field and one for the dependent field.

```python
def get_options_list(field, control_value=None, **kwargs):
    """
    A plug-in for regenerating 'Species' options based on the value of the controlling field 'Genus'
    field: This is the dependent field.
    control_value: The value entered on the form for the control field. This value determines what will be displayed in "field"
    """
    options = []

    if control_value == 'Acer':
        options = [
            ('rubrum', 'rubrum'),
            ('saccharinum', 'saccharinum'),
            ('macrophyllum', 'macrophyllum')
        ]
    elif control_value == 'Sequoia':
        options = [
            ('magnifica', 'magnifica'),
            ('langsdorfii', 'langsdorfii'),
            ('giganteum', 'giganteum')
        ]
    return {
        'options': options,
        'override': True
    }
```

### Example 2: using multiple choice fields

A regenerated options dependency where `allow_multiple` is set on the controlling field. Use the `control_values` keyword argument to accept a list of values from it.

```python
def get_options_list(field, control_value=None, control_values=[], **kwargs):
    """
    A plug-in for building a list of options for 'Plants'
    based on the values selected for the controlling field 'Plant Type'
    field: This is the dependent field.
    control_value: Not needed in this case, but still required in the function definition.
    control_values: A list of values selected on the form for the controlling field.
    """
    options = []

    if 'Trees' in control_values:
        options.extend([
            ('red_maple', 'Red Maple'),
            ('coastal_redwood', 'Coastal Redwood'),
            ('douglas_fir', 'Douglas Fir'),
        ])

    if 'Shrubs' in control_values:
        options.extend([
            ('red_twig_dogwood', 'Red Twig Dogwood'),
            ('wild_lilac', 'Wild Lilac'),
            ('summersweet', 'Summersweet'),
        ])

    return options
```

### Example 3: using multiple controlling fields

More than one controlling field can drive a single dependent field. Use the `control_value_dict` keyword argument to fetch the values of all of them.

```python
def get_options_list(field, control_value=None, control_value_dict=None, **kwargs):
    options = []
    if not control_value_dict:
        return options
    monitoring_tool = control_value_dict.get("monitoring_tool", "")
    monitoring_policy = control_value_dict.get("monitoring_policy", "")
    # Add any logic to determine options based on the monitoring tool and policy.
    # Some trivial example logic follows.
    options = [
        f"Severity 1 for {monitoring_tool} {monitoring_policy}",
        f"Severity 2 for {monitoring_tool} {monitoring_policy}",
    ]
    return options
```

### Example 4: using OS Build as a controlling field

You can pick an OS build from a dropdown by name, but the controlling value is the **integer ID** of the OSBuild object, and those IDs may differ between CMP instances. `os_build` is only available on server tiers.

```python
def get_options_list(field, control_value=None, control_value_dict=None, **kwargs):
    options = []
    if not control_value and not control_value_dict:
        return options

    if control_value:
        if control_value.os_family.name == "Red Hat":
            if control_value.name == "RHEL8_9":
                # Use separate keys so the custom form cleans up after it regenerates the options
                options.append(("sat_server_one", "Satellite server ONE for RHEL 8"))
                options.append(("sat_server_two", "Satellite server TWO for RHEL 8"))

    return dict(
        options=options,
        override=True,
        sort=True,
    )
```

## Related

- [Parameter options](/docs/cmp/configure/order-forms-and-pricing/parameters/parameter-options/): How generated options combine with options set elsewhere.
- [Custom forms](/docs/cmp/configure/order-forms-and-pricing/custom-forms/): Use generated options on a custom form.

---

Section pages:

- [Option return formats](/docs/cmp/configure/order-forms-and-pricing/parameters/generated-options/option-return-formats/): Control the labels, initial value, sort order, and filtering of the options a plugin generates
