Using HOT instead of molecule.yml


#1

The molecule.yml platforms format needs the create playbook and the vm role to actually create or delete the host and the associated volumes.

Ideally molecule would support that but it does not and there is very little chance it will in the future. It would require the molecule.yml platforms format to be able to describe the orchestration of the test resources in a way that can be interpreted for all supported drivers (OpenStack, Docker, etc.).

The delegated molecule driver could be used as a bridge between molecule and heat. The molecule.yml platform would only select which hosts are to be created and the heat template (HOT) will describe how they are created (volume, flavor, etc.).

The platform part of the molecule.yml file could look like this:

---
driver:
  name: delegated
  options:
    managed: False
platforms:
  - name: bind-host
  - name: bind-client-host

The availability of heat was announced to be beta in June 2018 and it is still gama. I could not find it anywhere else (not in the OVH cloud product description, etc.).


#2

As of April 2019 only the regions GRA5 & SBG5 provide the orchestration service. Although openstack stack list works on all regions, creating a stack with openstack stack create -t /tmp/a otherstack fails with:

  • BHS3 public endpoint for orchestration service in BHS3 region not found
  • DE1 <html>\n\t<head>\n\t\t<meta http-equiv=“Content-Type” content="text/html;…
  • UK1 & WAW1 ERROR: SSL exception connecting to https://auth.cloud.ovh.net:443/: (“bad handshake: Error([(’’, ‘osrandom_rand_bytes’, ‘getrandom() initialization failed.’)],)”,)

#3

For the record, progress is being tracked at https://lab.enough.community/main/infrastructure/issues/60


#4
  • openstack stack create --wait --parameter key=singuliere --parameter port=2222 -t ~/tmp/template.yml otherstack
heat_template_version: 2017-02-24

description: Simple template to deploy a single compute instance

parameters:
  port:
    type: string
    default: "22"

  key:
    type: string

resources:
  my_instance:
    type: OS::Nova::Server
    properties:
      key_name: { get_param: key }
      image: Debian 9
      flavor: s1-2
      user_data:
        str_replace:
          template: |
            #!/bin/bash
            sed -i -e '/^#Port/s/^.*$/Port $port/' /etc/ssh/sshd_config
            systemctl restart ssh
          params:
            $port: { get_param: port }

  my_volume:
    type: OS::Cinder::Volume
    properties:
      name: my_volume
      size: 1

  my_attachment:
    type: OS::Cinder::VolumeAttachment
    properties:
      instance_uuid: { get_resource: my_instance }
      volume_id: { get_resource: my_volume }
openstack stack create --wait --parameter key=singuliere --parameter port=2222 -t ~/tmp/template.yml otherstack1 ; openstack server list
2019-04-28 22:14:09Z [otherstack1]: CREATE_IN_PROGRESS  Stack CREATE started
2019-04-28 22:14:10Z [otherstack1.my_instance]: CREATE_IN_PROGRESS  state changed
2019-04-28 22:14:11Z [otherstack1.my_volume]: CREATE_IN_PROGRESS  state changed
2019-04-28 22:14:13Z [otherstack1.my_volume]: CREATE_COMPLETE  state changed
2019-04-28 22:14:31Z [otherstack1.my_instance]: CREATE_COMPLETE  state changed
2019-04-28 22:14:31Z [otherstack1.my_attachment]: CREATE_IN_PROGRESS  state changed
2019-04-28 22:14:33Z [otherstack1.my_attachment]: CREATE_COMPLETE  state changed
2019-04-28 22:14:33Z [otherstack1]: CREATE_COMPLETE  Stack CREATE completed successfully
+---------------------+-----------------------------------------------------+
| Field               | Value                                               |
+---------------------+-----------------------------------------------------+
| id                  | d3a5432c-7cbf-4a2d-8c0c-3e09e6f559e6                |
| stack_name          | otherstack1                                         |
| description         | Simple template to deploy a single compute instance |
| creation_time       | 2019-04-28T22:13:51Z                                |
| updated_time        | None                                                |
| stack_status        | CREATE_COMPLETE                                     |
| stack_status_reason | Stack CREATE completed successfully                 |
+---------------------+-----------------------------------------------------+
+--------------------------------------+--------------------------------------+--------+---------------------------------------------+----------+--------+
| ID                                   | Name                                 | Status | Networks                                    | Image    | Flavor |
+--------------------------------------+--------------------------------------+--------+---------------------------------------------+----------+--------+
| 837ee600-72da-4533-9c2e-21ad87452493 | otherstack1-my_instance-gk7ryeqk3mlp | ACTIVE | Ext-Net=2001:41d0:404:100::9b1, 51.68.87.89 | Debian 9 | s1-2   |
+--------------------------------------+--------------------------------------+--------+---------------------------------------------+----------+--------+


#5
$ ansible-playbook -i localhost, -c local ~/software/enough/infrastructure/molecule/infrastructure/stack.yml
ok: [localhost] => {
    "stack_create": {
        "changed": true,
        "failed": false,
        "id": "04df6be9-ba3f-4f38-a357-bd06638865e9",
        "stack": {
            "action": "UPDATE",
            "created_at": "2019-04-29T07:56:54Z",
            "creation_time": "2019-04-29T07:56:54Z",
            "deleted_at": null,
            "deletion_time": null,
            "description": "Simple template to deploy a single compute instance",
            "disable_rollback": true,
            "id": "04df6be9-ba3f-4f38-a357-bd06638865e9",
            "identifier": "otherstack/04df6be9-ba3f-4f38-a357-bd06638865e9",
            "is_rollback_enabled": true,
            "location": {
                "cloud": "envvars",
                "project": {
                    "domain_id": "default",
                    "domain_name": null,
                    "id": "f721c0a2bf624b7ea643f114242c714a",
                    "name": "1212472822801405"
                },
                "region_name": "SBG5",
                "zone": null
            },
            "name": "otherstack",
            "notification_topics": [],
            "outputs": [
                {
                    "description": "No description given",
                    "output_key": "ipv4",
                    "output_value": "51.68.92.237"
                }
            ],
            "owner": null,
            "parameters": {
                "OS::project_id": "f721c0a2bf624b7ea643f114242c714a",
                "OS::stack_id": "04df6be9-ba3f-4f38-a357-bd06638865e9",
                "OS::stack_name": "otherstack",
                "key": "singuliere",
                "port": "2222"
            },
            "parent": null,
            "properties": {
                "capabilities": []
            },
            "stack_name": "otherstack",
            "stack_owner": null,
            "stack_status": "UPDATE_COMPLETE",
            "stack_status_reason": "Stack UPDATE completed successfully",
            "stack_user_project_id": "eaac80d4bab84835b363dbec045dc71e",
            "status": "COMPLETE",
            "status_reason": "Stack UPDATE completed successfully",
            "tags": null,
            "tempate_description": "Simple template to deploy a single compute instance",
            "template_description": "Simple template to deploy a single compute instance",
            "timeout_mins": 60,
            "updated_at": "2019-04-29T08:59:22Z",
            "updated_time": "2019-04-29T08:59:22Z"
        }
    }
}
- name: Create
  hosts: localhost
  connection: local
  gather_facts: False

  tasks:

    - name: instance create
      register: stack_create
      os_stack:
        name: otherstack
        state: present
        template: /home/singuliere/tmp/template.yml
        parameters:
          port: 2222
          key: singuliere

    - debug:
        var: stack_create
# https://docs.openstack.org/heat/stein/template_guide/openstack.html
heat_template_version: 2017-02-24

description: Simple template to deploy a single compute instance

parameters:

  port:
    type: string
    default: "22"

  key:
    type: string

resources:
  my_instance:
    type: OS::Nova::Server
    properties:
      key_name: { get_param: key }
      image: Debian 9
      flavor: s1-2
      security_groups:
        - { get_resource: my_security_group }
      user_data:
        str_replace:
          template: |
            #!/bin/bash
            sed -i -e '/^#Port/s/^.*$/Port $port/' /etc/ssh/sshd_config
            systemctl restart ssh
          params:
            $port: { get_param: port }

  my_volume:
    type: OS::Cinder::Volume
    properties:
      name: my_volume
      size: 1

  my_attachment:
    type: OS::Cinder::VolumeAttachment
    properties:
      instance_uuid: { get_resource: my_instance }
      volume_id: { get_resource: my_volume }

  my_security_group:
    type: OS::Neutron::SecurityGroup
    properties:
      rules:
        - port_range_min: { get_param: port }
          port_range_max: { get_param: port }
          protocol: tcp
          remote_ip_prefix: 0.0.0.0/0

outputs:
  ipv4:
    value:
      # https://yaql.readthedocs.io/
      yaql:
        expression: $.data.select([$.addr]).where('.' in $[0]).first().first()
        #
        # { get_attr: [ my_instance, addresses, Ext-Net ] }
        #
        # looks like this:
        #
        # {
        #          "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:e9:50:e8",
        #          "version": 6,
        #          "addr": "2001:41d0:404:100::beb",
        #          "OS-EXT-IPS:type": "fixed",
        #          "port": "bae0fb68-f1cb-4c20-a1fc-c14e6ccd033a"
        #        },
        #        {
        #          "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:e9:50:e8",
        #          "version": 4,
        #          "addr": "51.68.92.237",
        #          "OS-EXT-IPS:type": "fixed",
        #          "port": null
        #        }
        # }
        #
        data: { get_attr: [ my_instance, addresses, Ext-Net ] }

#6

openstack stack create -f json --wait --parameter key=singuliere -t ~/tmp/template-composed.yml otherstack

# https://docs.openstack.org/heat/stein/template_guide/openstack.html
heat_template_version: 2017-02-24

description: Simple template to deploy a single compute instance

parameters:

  key:
    type: string

resources:
  other-host:
    type: template-server.yaml
    properties:
      port: 2222
      key: { get_param: key }

  bind-host:
    type: template-server.yaml
    properties:
      port: 22
      key: { get_param: key }
      volume_size: 1


outputs:
  ipv4:
    value:
      # https://yaql.readthedocs.io/
      yaql:
        expression: $.data.select([$.addr]).where('.' in $[0]).first().first()
        #
        # { get_attr: [ my_instance, addresses, Ext-Net ] }
        #
        # looks like this:
        #
        # {
        #          "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:e9:50:e8",
        #          "version": 6,
        #          "addr": "2001:41d0:404:100::beb",
        #          "OS-EXT-IPS:type": "fixed",
        #          "port": "bae0fb68-f1cb-4c20-a1fc-c14e6ccd033a"
        #        },
        #        {
        #          "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:e9:50:e8",
        #          "version": 4,
        #          "addr": "51.68.92.237",
        #          "OS-EXT-IPS:type": "fixed",
        #          "port": null
        #        }
        # }
        #
        data: { get_attr: [ bind-host, resource.my_instance, addresses, Ext-Net ] }

template-server.yaml (must be yaml otherwise no game)

# https://docs.openstack.org/heat/stein/template_guide/openstack.html
heat_template_version: 2017-02-24

description: Simple template to deploy a single compute instance

parameters:

  port:
    type: string
    default: "22"

  key:
    type: string

  volume_size:
    type: number
    default: 0


conditions:
  
  need_volume: { not: { equals: [{get_param: volume_size}, 0]}}

resources:
  my_instance:
    type: OS::Nova::Server
    properties:
      key_name: { get_param: key }
      image: Debian 9
      flavor: s1-2
      security_groups:
        - { get_resource: my_security_group }
      user_data:
        str_replace:
          template: |
            #!/bin/bash
            sed -i -e '/^#Port/s/^.*$/Port $port/' /etc/ssh/sshd_config
            systemctl restart ssh
          params:
            $port: { get_param: port }

  my_volume:
    type: OS::Cinder::Volume
    condition: need_volume
    properties:
      name: my_volume
      size: 1

  my_attachment:
    type: OS::Cinder::VolumeAttachment
    condition: need_volume
    properties:
      instance_uuid: { get_resource: my_instance }
      volume_id: { get_resource: my_volume }

  my_security_group:
    type: OS::Neutron::SecurityGroup
    properties:
      rules:
        - port_range_min: { get_param: port }
          port_range_max: { get_param: port }
          protocol: tcp
          remote_ip_prefix: 0.0.0.0/0

#7

For the record, HOT deployment is now implemented & deployed