Valid since:
XL Deploy 7.1.0

XL Deploy 7.1.0 introduces the environment-as-code feature, which enables you to store information about your infrastructure and environments in a Deployfile, a Groovy file that you can store in source control. This feature allows you to maintain and update environment and infrastructure information outside of the XL Deploy repository, where it can be updated by multiple teams or automatically updated by infrastructure automation tools.

The Deployfile

The Deployfile is a Groovy file that describes the desired state of infrastructure and/or environment configuration items (CIs) in the XL Deploy repository. In the Deployfile, you define the CIs that should exist, their properties, and their relationships with other CIs; when you apply the Deployfile using the REST API or command-line interface (CLI), XL Deploy determines whether CIs need to be created, deleted, or modified to achieve the state described in the Deployfile.

Every CI or set of CIs defined in the Deployfile must have a scope, which is the directory in which CIs should be created or modified, or from which CIs should be deleted. The scope ensures that you do not inadvertently change or delete CIs that are not related to the Deployfile. The Deployfile also supports setting or changing local permissions on the directory or directories that are in scope.

The Deployfile determines whether a CI or set of CIs should be created under the Environments or Infrastructure parent node in the repository, as identified by the forEnvironments and forInfrastructure keywords.

Note that:

  • The scope must be a directory under the Environments or Infrastructure parent node. The scope cannot be a parent node itself.
  • At this time, the Deployfile cannot be used to define CIs under Applications or Configuration.

Sample Deployfile

This is a sample Deployfile that defines a docker.SwarmManager CI, an environment, and a dictionary.

xld {
    scope(
      forInfrastructure: directory('Infrastructure/MyInfra') {
        permissions = [
          'admins': ['read', 'controltask#execute', 'generate#dsl', 'repo#edit'],
          'deployer': ['read', 'controltask#execute', 'repo#edit']
        ]
      }
    ) {
      infrastructure('dkr-prd-mgr', 'docker.SwarmManager') {
        dockerHost = 'tcp://192.168.99.103:2376'
        registries = [
          ref('Configuration/Docker/Docker Hub')
        ]
      }
    }
    scope(
      forEnvironments: 'Environments/Production'
      ) {
       environment('PROD') {
        members = [
           ref('Infrastructure/Docker/dkr-prd-mgr')
         ]
         dictionaries = [dictionary('Production Settings', ['logFilePath': '/tmp', 'HOST_PORT': '8181', 'title': 'Dockerized SampleApp', 'timeout': '8', 'logLevel': 'WARN'])]
      }
    }
}

Define CI properties

These are examples of the Groovy format for CI property kinds:

Property kind Groovy format example
Integer integerProp = 123
String stringProp = 'value1'
Strings stringsProp = [
  'value1',
  'value2'
]
Encrypted strings stringsEncryptedProp = [
  encrypted('value1'),
  encrypted('value2')
]
Map of strings stringsMap = [
  'key1': 'value1',
  'key2': 'value2'
]
Boolean booleanProp = true
Date date('2017-06-28T18:40:35')
Enum FRIDAY or java.time.DayOfWeek.FRIDAY

Set permissions on directories

You can set local permissions on the directories that will be created or modified when a Deployfile is applied. For example, to create an empty directory with permissions set on it:

xld {
  scope(
    forInfrastructure: directory('Infrastructure/Empty') {
      permissions = [
        'admins': ['read', 'controltask#execute', 'generate#dsl', 'repo#edit'],
        'deployer': ['read', 'controltask#execute', 'generate#dsl', 'repo#edit'],
        'developer': ['read', 'generate#dsl', 'repo#edit']
      ]
    }
  ) { }
}

If you do not specify the permissions property, the directory’s local permissions will not be modified.

Refer to another CI

You can refer to a CI that is defined in another part of the Deployfile or to a CI that already exists in the XL Deploy repository. For example:

xld {
  scope(
    forEnvironments: 'Environments/Internal/Testing'
  ) {
    environment('ACC01') {
      members = [
        ref('Infrastructure/Other middleware/apache-22/webserver1'),
        ref('Infrastructure/JBoss/jboss-51/jboss-8080-1'),
        ref('Infrastructure/Other middleware/localhost/Final smoke test station'),
        ref('Infrastructure/Other middleware/ora-10g-express-unix/10gXE')
      ]
      dictionaries = [
        ref('Environments/Dictionaries/Portal settings'),
        ref('Environments/Master dictionaries/JBoss config'),
        ref('Environments/Internal/Testing/Custom settings')
      ]
    }
    dictionary('Custom settings', [
      'LOGO': '/web/images/custom-logo.png',
      'TITLE': 'Custom User Portal Test'
    ])
  }
}

Generate a Deployfile

An easy way to get started with the Deployfile format is to generate Deployfiles from the directories that are already defined in your XL Deploy repository. You can use the XL Deploy REST API, the command-line interface (CLI), or the default graphical user interface to generate Deployfiles. To generate a Deployfile, you must have the export#dsl local permission.

Note that:

  • You can only generate a Deployfile from a directory or directories, not from the Environments or Infrastructure parent node.
  • Nested directories are defined as separate scopes within the Deployfile.
  • When you generate a Deployfile that contains an enum CI property, the property value will contain the full Java name. For example, you can specify the value unix for the os property on an overthere.SshHost CI, but when the Deployfile is generated, the value will be com.xebialabs.overthere.OperatingSystemFamily.UNIX. You can also use the full Java name when applying a Deployfile.

Generate a Deployfile using the REST API

This is an example of generating a Deployfile using cURL:

curl --user "matt:secret01" --request GET 'http://localhost:4516/deployit/dsl/generate?folder=Environments/MyEnvs'

Generate a Deployfile using the CLI

To generate a Deployfile from multiple directories and print the Groovy code in the console, execute:

repository.generateDeployfile(["Infrastructure/MyInfra","/Infrastructure/Experimental"])

To generate a Deployfile from multiple directories and print the Groovy code to a file, execute:

from java.io import File
repository.generateDeployfile(["Infrastructure/MyInfra","Infrastructure/Experimental"],File("/path/to/file.groovy"))

Generate a Deployfile using the user interface

To generate a Deployfile using the default XL Deploy user interface:

  1. Expand Environments or Infrastructure from the left pane.
  2. Hover over a folder, click Explorer action menu, and then select Generate DSL. A .groovy file is generated and saved on your local machine.

Apply a Deployfile

You can use the XL Deploy REST API or the command-line interface (CLI) to apply Deployfiles to the XL Deploy repository. To apply a Deployfile, you must have the repo#edit local permission in the parts of the repository affected by the Deployfile.

Note: For security reasons, Deployfiles are applied in a sandbox that does not have access to XL Deploy APIs.

Apply a Deployfile using the REST API

This is an example of applying a Deployfile using cURL:

curl -v --user "matt:secret01" --request POST -H "Content-Type: text/plain" --data 'xld {scope(forEnvironments: "Environments/MyEnvs"){}}' 'http://localhost:4516/deployit/dsl/apply'

Apply a Deployfile using the CLI

To apply a Deployfile, execute:

from java.io import File
repository.applyDeployfile(File("/path/to/file.groovy"))

Security recommendations when using environment as code

  • Use the export#dsl local permission to limit the users who can export CIs containing sensitive data (encrypted property values such as password properties).
  • Use property placeholders instead of storing sensitive data directly in CIs.