Best Practice recommendations for Automate

Posted by Christian Jung on Tue, Oct 10, 2017

Purpose of this document

The idea of this document is to collaboratively collect coding style recommendations and best practices to give guidance on how to use Automate in CloudForms and ManageIQ.

The following tips are meant for guidance and should give you some hints and ideas on how to do things “the clean way”. There are always exceptions from those rules. This document does not claim to be complete but should provide some recommendations and guidance. Feedback is, as always, very much appreciated.

Naming Convention

Name spaces

To “overload” existing code from other domains it is necessary to keep the structure of name spaces, classes, methods and instances identical. Custom name spaces should follow the existing structure.

For example integration code into external (third party) software should follow the structure used in the Red Hat/Integration domain.

Proposed structure:

    ├── ConfigurationManagement (Namespace (NS)
    │   ├── Ansible (Class)
    │   │   ├── instance1
    │   │   ├── instance2
    │   │   ├── method1
    │   │   └── method2
    │   └── Foreman (Class)
    │     ├── create (Instance/Method)
    │     ├── delete (Instance/Method)
    │     ├── read (Instance/Method)
    │     ├── Instance/Method
    │     └── update (Instance/Method)
    ├── RedHat (NS)
    │   ├── OpenStack (NS)
    │   │   ├── Cinder (Class)
    │   │   │   ├── create (Instance/Method)
    │   │   │   ├── delete (Instance/Method)
    │   │   │   ├── read (Instance/Method)
    │   │   │   └── update (Instance/Method)
    │   │   ├── LBaaS (Class)
    │   │   │   ├── create (Instance/Method)
    │   │   │   ├── delete (Instance/Method)
    │   │   │   ├── read (Instance/Method)
    │   │   │   └── update (Instance/Method)
    │   │   └── Snapshots (Class)
    │   │     ├── create (Instance/Method)
    │   │     ├── delete (Instance/Method)
    │   │     ├── read (Instance/Method)
    │   │     └── update (Instance/Method)
    │   ├── RHEV (Class)
    │   └── Satellite (Class)
    └── Vendor (NS)
    ├── Application1 (Class)
    ├── Application2 (Class)
    └── Application3 (Class)

More Details

Miscellaneous tips in Peter McGowan’s Automate Book.

Instance names and methods should both be snake case, see also the discussion on the the ManageIQ Forum.

Developer Guides for ManageIQ.

Discussion Convert Automate Methods to new style using classes.

Working with Domains

As a basic setup code and configuration details should be split into two domains. E.g.

    Customer-config
    Customer-code

This will make it easier to reuse the code at other customers or make it available in a source code repository (like git/SVN). Additional domains for staging might be useful in larger deployments.

Example: (sorted by priority)

    Customer-config
    Customer-dev
    Customer-qa
    Customer-prod

Production

Customer-prod contains already “released” code, this means this domain is a 1:1 copy of the one used in production. In the production environment the -dev and -qa domains don’t exist, are empty or disabled.

QA

In the QA or test environment the “customer-prod” domain contains a 1:1 copy of the production domain, but is overloaded by the -qa domain. This allows testing of QA code in combination with existing production code. After all QA tests have been completed, the QA code moves into the production domain (leaving the QA domain empty).

Development

“Development” is following the same approach. It contains a 1:1 copy of -prod and -qa domains but is also overloaded by content from the -dev domain. This allows for development work to be based on current production and QA code, By separating -dev into a dedicated domain, the -dev domain can for example temporarily be disabled for root cause analysis or debugging purposes.

Configuration

Finally the -config domain contains ALL configuration data. E.g. host names to external systems, login credentials, environment specific settings. There are dedicated -config domains for each stage which will never coexist (e.g. the -config domain for QA exclusively contains QA specific settings and never uses settings for production). Consequently there is no configuration information in any of the domains listed above.

Depending on the specific needs more (e.g. Pre-Prod) or less domains (QA might not always be needed) can be used.

Git integration

Automate Domains can be imported from Git (including but not limited to Gitlab and GitHub). The REST API also provides a call to refresh a specific Automate domain. This allows the integration with a CI/CD pipeline like Jenkins or Travis. A simple hook script can be used to trigger a refresh of the Automate Domain whenever new code is committed.

The Role Based Access control can be used to create a specific role which only grants the privilege to trigger a domain refresh:

RBAC role for Automate refresh

Each Automate domain can be imported from a specific Git repository. CloudForms and ManageIQ also detects branches and tags which allows to be even more flexible.

More information can be found in the Continuous Integration with CloudForms or ManageIQ Automate post.

Unit Testing

Automate methods can usually not be used outside of the context of CloudForms or ManageIQ. To increase code quality and use automated unit tests, it is recommended to write every method generic enough, so it can be called in the context of a state machine, a button, from Simulate and the REST API.

Since it is now possible to call any method from REST, it is recommended to follow some coding best practices to accomplish this goal. More information can be found in the chapter Writing Generic Methods of the Automate Book. Examples for using the REST API to call Automate can be found as well.

Limitations

Obviously some methods in Automate will not be able to do any reasonable tests without the appropriate context (e.g. a method which is used during provisioning can probably not provide a reasonable unit test if called without the context of a provisioned VM. )

Code Documentation with RDoc

RDoc is part of Ruby and can automatically create documentation based on existing Ruby code. It analysis the code and tries to build the proper structure and relationships automatically.

The use of RDoc in the context of Automate is somewhat limited though. Although CloudForms and ManageIQ are using Namespaces and Classes, this information is stored in YAML files and can not automatically be used by RDoc when it creates the documentation.

In conclusion RDoc can still be used to create automated documentation, but requires some discipline from the developer and will not be able to automatically detect the namespace and class structure of Automate.

More information about RDoc can be found in the Ruby Documentation