Item Environments List - LiquidAnalytics/ld-api-examples GitHub Wiki

Item Environments List Overrides

We use configuration items to configure various things in our application. Certain configuration settings needed for our applications sometimes differ between environments. The most common case of this is a URL that connects to an outside system, for example a URL a customer might provide for inventory data. Usually there will be different endpoints available for Dev, QA, and Production systems.

Item Environments List is a way to configure different field values to be used on a given configuration item, depending on what environment the item is currently living in.

Schema Configuration

To configure and use an item environments list on a configuration item, a new field must be added to the configuration item schema, and a new block schema must be added.

The new schema field to be added to the configuration schema will be a list of blocks, with the flag "environmentsList" set to true. By convention we give this field the name "environments", but that is not strictly required.

Imagine we had an existing schema called FunctionUrl defined as follows:

{
  "type": "FunctionUrl",
  "fields": [
    {
      "dataType": "refnum",
      "name": "functionUrlId",
      "primary": true
    },
    {
      "name": "functionUrl"
    }
  ],
  "permissionType": "All",
  "category": "system"
}

To add an environments list to this schema, we would add a field like this:

    ...
    },
    {
      "environmentsList": true,
      "listElementType": "block",
      "dataType": "list",
      "name": "environments",
      "blockType": "FunctionUrlOverride"
    }
    ...

Then also create a block schema, matching the blockType specified above. By convention the name of the block schema is identical to the name of the main schema, with "Override" appended:

{
  "type": "FunctionUrlOverride",
  "fields": [
    {
      "name": "environment"
    },
    {
      "name": "functionUrl"
    }
  ],
  "category": "block"
}

The block schema requires a field named "environment", and then all other fields on the schema should match field names that you would want to override from the main schema. In this example, the only field we will override on the configuration item is called "functionUrl".

Defining the Item

Now that we have defined the schemas, we can setup items to make use of the environments list to override values in different environments.

Without any overrides the item might look something like this:

{
  "headers": {
	...
  },
  "data": {
    "functionUrlId": "ExampleFunction",
    "functionUrl": "http://devUrl.com"
  }
}

Currently the function is only applicable for the DEV environment, so if we deployed this item to QA or PRD from a package, it wouldn't contain the proper URL. With overrides applied, the item would look like this:

{
  "headers": {
	...
  },
  "data": {
    "functionUrlId": "ExampleFunction",
    "functionUrl": "http://devUrl.com",
    "environments": [
    	{
    		"environment": "LDCLOUD_DEV",
    		"functionUrl": "http://devUrl.com"
    	},
    	{
    		"environment": "LDCLOUD_QA",
    		"functionUrl": "http://qaUrl.com"
    	},
    	{
    		"environment": "LDCLOUD_PROD",
    		"functionUrl": "http://prodUrl.com"
    	}
    ]
  }
}

In the example above, in the LDCLOUD_DEV environment, the functionUrl would be set to "http://devUrl.com", in LDCLOUD_QA, it would be "http://qaUrl.com" and in LDCLOUD_PROD it would be "http://prodUrl.com"

What the Device Sees

When dealing with items that have environment list overrides, the server automatically does the overriding internally, and so any devices that receive the items will receive it with overrides already applied and without the environments list present. This way, consumers of items, such as devices, do not have to worry about parsing the environments list themselves in order to find the correct data to use, the server takes care of it automatically.

In LDCLOUD_DEV, if the above example item was synced to the device, the device would get:

{
  "headers": {
	...
  },
  "data": {
    "functionUrlId": "ExampleFunction",
    "functionUrl": "http://devUrl.com"
  }
}

In LDCLOUD_QA, if the above example item was synced to the device, the device would get:

{
  "headers": {
	...
  },
  "data": {
    "functionUrlId": "ExampleFunction",
    "functionUrl": "http://qaUrl.com"
  }
}

In LDCLOUD_PROD, if the above example item was synced to the device, the device would get:

{
  "headers": {
	...
  },
  "data": {
    "functionUrlId": "ExampleFunction",
    "functionUrl": "http://prodUrl.com"
  }
}

The device can just use the value on functionUrl, and does not deal with or even see the environments list data

Viewing environments lists in Mission Control

In order to properly setup an item with the proper environments list, you need to be able to view the item both with and without the overrides applied. This can be done in Mission Control.

When you are on an item blotter for an item that contains an environments list, you will see an additional checkbox called "Expand Environments List":

When this checkbox is checked, it means we want to view the full definition of the item including the environments list. As you can see in the blotter above, the environments list column is populated with data.

When this checkbox is unchecked, it means we want to view the item with the overrides applied for the current environment:

Now with overrides applied, you can see the environments list is no longer present and all overrides are applied on the data of the item.

When you explore an item with environments list in Mission Control, you will also see this checkbox for "Expand Environments List":

By default it is checked and you will see the full definition of the environments list.

When you uncheck it, you see what the item looks like with overrides applied. The item you see here is exactly what you can expect a device to receive when it syncs this item.

If we look at the same item in QA environment, we see the values have been overidden properly for QA:

Editing environments list in Mission Control

The basic flow for setting up environments list for items is, in the course of development, in the dev environment, you should add the environments overrides to your configuration items with all the overrides set for QA and PROD.

When a package is created out of the dev environment, all the environments overrides for applicable items will be saved as part of the package.

When the package is deployed to QA, the items have all the override information available, and so can properly override to the correct values.

What this means for development and deployment is, if an override value for production changes or was found to be incorrect, you must go back to dev environment and update the environments list with proper values for the production override. Once that is done, you can create a new package and deploy that to QA and then eventually to PROD so that the correct overrides make it to production.

Similar to any other configuration changes you might make, the proper way is always to make the change in dev environment, and then create new package so the change can be promoted to other environments.

Additional Examples

When defining an item with an environments override, it is not necessary to define an override for each environment. The rule that is followed for overriding is that the data inside the body of the item (not including the environments list) is the default value for that field. If an applicable environments block is found for the current environment we are in, we will override any fields present in the block, but if no environments block is found, whatever is in the body of the item will remain.

For example above we defined an item as follows:

{
  "headers": {
	...
  },
  "data": {
    "functionUrlId": "ExampleFunction",
    "functionUrl": "http://devUrl.com",
    "environments": [
    	{
    		"environment": "LDCLOUD_DEV",
    		"functionUrl": "http://devUrl.com"
    	},
    	{
    		"environment": "LDCLOUD_QA",
    		"functionUrl": "http://qaUrl.com"
    	},
    	{
    		"environment": "LDCLOUD_PROD",
    		"functionUrl": "http://prodUrl.com"
    	}
    ]
  }
}

The functionUrl in the body of the item is already "http://devUrl.com", so having an environments override block for LDCLOUD_DEV is redundant. If we defined the item as follows, it would behave the same way in DEV:

{
  "headers": {
	...
  },
  "data": {
    "functionUrlId": "ExampleFunction",
    "functionUrl": "http://devUrl.com",
    "environments": [
    	{
    		"environment": "LDCLOUD_QA",
    		"functionUrl": "http://qaUrl.com"
    	},
    	{
    		"environment": "LDCLOUD_PROD",
    		"functionUrl": "http://prodUrl.com"
    	}
    ]
  }
}

Since no environment block is found for LDCLOUD_DEV, if we are in the dev environment, the item wil keep the default functionUrl defined in the body of the item, which is the proper dev url, so it works fine. If we are in QA or PROD, the proper environments block will be found and overridden properly.

Additionally, it is possible that we might want the same values for more than 1 environment, and only a different value for Production. For example, imagine we wanted the same URL for both DEV and QA, but something different for PROD, we could define an item like this:

{
  "headers": {
	...
  },
  "data": {
    "functionUrlId": "ExampleFunction",
    "functionUrl": "http://devAndQAUrl.com",
    "environments": [
    	{
    		"environment": "LDCLOUD_PROD",
    		"functionUrl": "http://prodUrl.com"
    	}
    ]
  }
}

Here we define functionUrl to "http://devAndQAUrl.com", and we setup an override for LDCLOUD_PROD. In this way, the item will keep the default value of "http://devAndQAUrl.com" in every environment other than LDCLOUD_PROD, where it will be overridden.