As a developer, you start with a Cloud Assembly blueprint that contains only minimal WordPress components, such as having only one application server.

During development, you are typically building a blueprint by starting with the essentials, deploying, and testing as the blueprint grows. Gradually, you add more components, redeploy, and retest along the way.

Cloud Assembly is an infrastructure-as-code tool. You drag components to the design canvas to get started. Then, you complete the details using the code editor to the right of the canvas.

Prerequisites

Be familiar with your infrastructure. The examples shown here use the infrastructure values from the first part of the use case, but you would substitute your own.

Procedure

  1. Go to Blueprints, and click New.
  2. Name the blueprint Wordpress-BP.
  3. Select the WordPress project, and click Create.
  4. From the components on the left of the blueprint design page, drag two cloud agnostic machines onto the canvas.

    The machines serve as WordPress application server (WebTier) and MySQL database server (DBTier).

  5. On the right, edit the machine YAML code to add names, images, flavors, and constraint tags:
    resources:
      DBTier:    
        type: Cloud.Machine    
        properties:      
            name: mysql      
            image: 'ubuntu-16'      
            flavor: 'small'      
            constraints:        
                -   tag: env:dev
      WebTier:
        type: Cloud.Machine    
        properties:     
            name: wordpress      
            image: 'ubuntu-16'      
            flavor: 'small'      
            constraints:        
                - tag: env:dev
    
  6. Drag a cloud agnostic network to the canvas, and edit its code:
     WP-Network-Private:
        type: Cloud.Network
        properties:
            name: WP-Network-Private
            networkType: existing
            constraints:
                - tag: 'type:isolated-net'
                - tag: 'env:dev'
  7. Connect the machines to the network:

    Click and hold where the line touches the network block, drag to a machine block, and release.

    Two machines and one network

    In the editor, notice that the network code gets added to the two machines:

    resources:
      DBTier:    
        type: Cloud.Machine    
        properties:      
            name: mysql      
            image: 'ubuntu-16'      
            flavor: 'small'      
            constraints:        
                -   tag: env:dev
            networks:
                - name: '${WP-Network-Private.name}'
      WebTier:
        type: Cloud.Machine    
        properties:     
            name: wordpress      
            image: 'ubuntu-16'      
            flavor: 'small'      
            constraints:        
                - tag: env:dev
            networks:
                - name: '${WP-Network-Private.name}'
      

  8. Add user input prompting.

    In some places, the use case infrastructure was set up for multiple options. For example:

    • Cloud zone environments for development, test, and production

    • Flavor mappings for small, medium, and large machines

    • Storage disk speeds for general and fast usage

    You might set a specific option directly in the blueprint, but a better approach is to let the user select the option at blueprint deployment time. Prompting for user input lets you create one blueprint that can be deployed many ways, instead of having many hard-coded blueprints.

    1. Create an inputs section in the code so that users can select machine size and target environment at deployment time. Define the selectable values:
      inputs:
        env:
          type: string
          enum:
            - 'env:dev'
            - 'env:prod'
            - 'env:test'
          default: 'env:dev'
          title: Environment
          description: Target Environment
        size:
          type: string
          enum:
            - small
            - medium
            - large
          description: Size of Nodes
          title: Tier Machine Size
      
    2. In the resources section of the code, add ${input.input-name} code to prompt for the user selection:
      resources:
        DBTier:    
          type: Cloud.Machine    
          properties:      
              name: mysql      
              image: 'ubuntu-16'      
              flavor: '${input.size}'      
              constraints:        
                  -   tag: '${input.env}'
              networks:
                  - name: '${WP-Network-Private.name}'
        WebTier:
          type: Cloud.Machine    
          properties:     
              name: wordpress      
              image: 'ubuntu-16'      
              flavor: '${input.size}'      
              constraints:        
                  - tag: '${input.env}'
              networks:
                  - name: '${WP-Network-Private.name}'
        WP-Network-Private:
          type: Cloud.Network
          properties:
              name: WP-Network-Private
              networkType: existing
              constraints:
                  - tag: 'type:isolated-net'
                  - tag: '${input.env}'
  9. Finally, enhance the WebTier and DBTier code using the following examples. The WP-Network-Private code does not need additional changes.

    Note that the enhancements include login access to the database server, a database disk, and deployment-time cloudConfig initialization scripts.

    Component

    Example

    DBTier Resource

      DBTier:
        type: Cloud.Machine
        metadata:
          layoutPosition:
            - 0
            - 0
        properties:
          name: mysql
          image: ubuntu-16
          flavor: '${input.size}'
          constraints:
            - tag: '${input.env}'
          networks:
            - name: '${WP-Network-Private.name}'
              assignPublicIpAddress: true
          remoteAccess:
            authentication: usernamePassword
            username: '${input.username}'
            password: '${input.userpassword}'
          cloudConfig: |
            #cloud-config
            repo_update: true
            repo_upgrade: all
    
            packages:
             - mysql-server
    
            runcmd:
             - sed -e '/bind-address/ s/^#*/#/' -i /etc/mysql/mysql.conf.d/mysqld.cnf
             - service mysql restart
             - mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'mysqlpassword';"
             - mysql -e "FLUSH PRIVILEGES;"
          attachedDisks: []
    

    Additional DBTier Inputs

      username:
        type: string
        minLength: 4
        maxLength: 20
        pattern: '[a-z]+'
        title: Database Username
        description: Database Username
      userpassword:
        type: string
        pattern: '[a-z0-9A-Z@#$]+'
        encrypted: true
        title: Database Password
        description: Database Password
      databaseDiskSize:
        type: number
        default: 4
        maximum: 10
        title: MySQL Data Disk Size
        description: Database Disk Size
    

    WebTier Resource

      WebTier:
        type: Cloud.Machine
        metadata:
          layoutPosition:
            - 0
            - 1
        properties:
          name: wordpress
          flavor: '${input.size}'
          image: ubuntu-16
          constraints:
            - tag: '${input.env}'
          networks:
            - name: '${WP-Network-Private.name}'
              assignPublicIpAddress: true
          cloudConfig: |
            #cloud-config
            repo_update: true
            repo_upgrade: all
    
            packages:
             - apache2
             - php
             - php-mysql
             - libapache2-mod-php
             - php-mcrypt
             - mysql-client
    
            runcmd:
             - mkdir -p /var/www/html/mywordpresssite && cd /var/www/html && wget https://wordpress.org/latest.tar.gz && tar -xzf /var/www/html/latest.tar.gz -C /var/www/html/mywordpresssite --strip-components 1
             - i=0; while [ $i -le 5 ]; do mysql --connect-timeout=3 -h ${DBTier.networks[0].address} -u root -pmysqlpassword -e "SHOW STATUS;" && break || sleep 15; i=$((i+1)); done
             - mysql -u root -pmysqlpassword -h ${DBTier.networks[0].address} -e "create database wordpress_blog;"
             - mv /var/www/html/mywordpresssite/wp-config-sample.php /var/www/html/mywordpresssite/wp-config.php
             - sed -i -e s/"define('DB_NAME', 'database_name_here');"/"define('DB_NAME', 'wordpress_blog');"/ /var/www/html/mywordpresssite/wp-config.php && sed -i -e s/"define('DB_USER', 'username_here');"/"define('DB_USER', 'root');"/ /var/www/html/mywordpresssite/wp-config.php && sed -i -e s/"define('DB_PASSWORD', 'password_here');"/"define('DB_PASSWORD', 'mysqlpassword');"/ /var/www/html/mywordpresssite/wp-config.php && sed -i -e s/"define('DB_HOST', 'localhost');"/"define('DB_HOST', '${DBTier.networks[0].address}');"/ /var/www/html/mywordpresssite/wp-config.php
             - service apache2 reload

  10. Test the application by deploying the blueprint. At the lower left, click Deploy.
  11. Select Create a new deployment.
  12. Name the deployment WordPress for OurCo, and click Next.
  13. Select input values, and click Deploy.

    Input variables

  14. To verify that the blueprint successfully deployed, click Deployments.

    If a deployment fails, click its name, and click the History tab to see messages that can help you troubleshoot.

    Failed deployment

  15. To verify that the application is working, open the WordPress web site in a browser.
    1. To locate the site FQDN or IP address, go to Deployments > Topology.
    2. On the canvas, click the WebTier, and find the address in the panel on the right.

    If the application needs more work, make blueprint changes and redeploy using the Update an existing deployment option.

  16. Consider versioning the blueprint. You can revert to a working version if a change causes deployment to fail.
    1. On the blueprint design page, click Version.
    2. On the Creating Version page, enter WP-1.0.

      Do not enter spaces in version names.

    3. Click Create.

    To review or revert to a version, on the design page, click the Version History tab.

  17. With a basic deployment now possible, try your first deployment-time enhancement by increasing CPU and memory on the application and database servers.

    Update to a medium node size for both. Using the same blueprint, select medium at deployment time, redeploy, and verify the application again.

    Note that changing the size removes the previous machines and provisions new ones, rather than updating them.

Completed Basic Blueprint Code Example

inputs:
  env:
    type: string
    enum:
      - 'env:dev'
      - 'env:prod'
      - 'env:test'
    default: 'env:dev'
    title: Environment
    description: Target Environment
  size:
    type: string
    enum:
      - small
      - medium
      - large
    description: Size of Nodes
    title: Tier Machine Size
  username:
    type: string
    minLength: 4
    maxLength: 20
    pattern: '[a-z]+'
    title: Database Username
    description: Database Username
  userpassword:
    type: string
    pattern: '[a-z0-9A-Z@#$]+'
    encrypted: true
    title: Database Password
    description: Database Password
  databaseDiskSize:
    type: number
    default: 4
    maximum: 10
    title: MySQL Data Disk Size
    description: Database Disk Size
  archiveDiskSize:
    type: number
    default: 4
    maximum: 10
    title: Wordpress Archive Disk Size
    description: Archive Storage Disk Speed
resources:
  DBTier:
    type: Cloud.Machine
    metadata:
      layoutPosition:
        - 0
        - 0
    properties:
      name: mysql
      image: ubuntu-16
      flavor: '${input.size}'
      constraints:
        - tag: '${input.env}'
      networks:
        - name: '${WP-Network-Private.name}'
          assignPublicIpAddress: true
      remoteAccess:
        authentication: usernamePassword
        username: '${input.username}'
        password: '${input.userpassword}'
      cloudConfig: |
        #cloud-config
        repo_update: true
        repo_upgrade: all

        packages:
         - mysql-server

        runcmd:
         - sed -e '/bind-address/ s/^#*/#/' -i /etc/mysql/mysql.conf.d/mysqld.cnf
         - service mysql restart
         - mysql -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'mysqlpassword';"
         - mysql -e "FLUSH PRIVILEGES;"
      attachedDisks: []
  WebTier:
    type: Cloud.Machine
    metadata:
      layoutPosition:
        - 0
        - 1
    properties:
      name: wordpress
      flavor: '${input.size}'
      image: ubuntu-16
      constraints:
        - tag: '${input.env}'
      networks:
        - name: '${WP-Network-Private.name}'
          assignPublicIpAddress: true
      cloudConfig: |
        #cloud-config
        repo_update: true
        repo_upgrade: all

        packages:
         - apache2
         - php
         - php-mysql
         - libapache2-mod-php
         - php-mcrypt
         - mysql-client

        runcmd:
         - mkdir -p /var/www/html/mywordpresssite && cd /var/www/html && wget https://wordpress.org/latest.tar.gz && tar -xzf /var/www/html/latest.tar.gz -C /var/www/html/mywordpresssite --strip-components 1
         - i=0; while [ $i -le 5 ]; do mysql --connect-timeout=3 -h ${DBTier.networks[0].address} -u root -pmysqlpassword -e "SHOW STATUS;" && break || sleep 15; i=$((i+1)); done
         - mysql -u root -pmysqlpassword -h ${DBTier.networks[0].address} -e "create database wordpress_blog;"
         - mv /var/www/html/mywordpresssite/wp-config-sample.php /var/www/html/mywordpresssite/wp-config.php
         - sed -i -e s/"define('DB_NAME', 'database_name_here');"/"define('DB_NAME', 'wordpress_blog');"/ /var/www/html/mywordpresssite/wp-config.php && sed -i -e s/"define('DB_USER', 'username_here');"/"define('DB_USER', 'root');"/ /var/www/html/mywordpresssite/wp-config.php && sed -i -e s/"define('DB_PASSWORD', 'password_here');"/"define('DB_PASSWORD', 'mysqlpassword');"/ /var/www/html/mywordpresssite/wp-config.php && sed -i -e s/"define('DB_HOST', 'localhost');"/"define('DB_HOST', '${DBTier.networks[0].address}');"/ /var/www/html/mywordpresssite/wp-config.php
         - service apache2 reload
  WP-Network-Private:
    type: Cloud.Network
    metadata:
      layoutPosition:
        - 1
        - 0
    properties:
      name: WP-Network-Private
      networkType: existing
      constraints:
        - tag: 'type:isolated-net'
        - tag: '${input.env}'

What to do next

Expand the blueprint into a production-worthy application by adding more components.