]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
tests : convert test_template_format to test-local templates
authorSteven Hardy <shardy@redhat.com>
Tue, 7 May 2013 14:59:49 +0000 (15:59 +0100)
committerSteven Hardy <shardy@redhat.com>
Wed, 8 May 2013 11:39:47 +0000 (12:39 +0100)
test_template_format is different from all other tests, in that
we don't want to use the most minimal template possible, we
actually want to test conversion works with maximal/non-trivial
templates, so copy the two templates used by this test into a
local tests/templates directory, with a README caution that
in general inline-minimal templates are preferred.

Change-Id: Ib5421545103728385992625884f86f2667ee2465

heat/tests/templates/Quantum.template [new file with mode: 0644]
heat/tests/templates/Quantum.yaml [new file with mode: 0644]
heat/tests/templates/README [new file with mode: 0644]
heat/tests/templates/WordPress_Single_Instance.template [new file with mode: 0644]
heat/tests/templates/WordPress_Single_Instance.yaml [new file with mode: 0644]
heat/tests/test_template_format.py

diff --git a/heat/tests/templates/Quantum.template b/heat/tests/templates/Quantum.template
new file mode 100644 (file)
index 0000000..1fd3298
--- /dev/null
@@ -0,0 +1,100 @@
+{
+  "AWSTemplateFormatVersion" : "2010-09-09",
+
+  "Description" : "Template to test Quantum resources",
+
+  "Parameters" : {
+
+  },
+
+  "Resources" : {
+    "network": {
+      "Type": "OS::Quantum::Net",
+      "Properties": {
+        "name": "the_network"
+      }
+    },
+    "unnamed_network": {
+      "Type": "OS::Quantum::Net"
+    },
+    "admin_down_network": {
+      "Type": "OS::Quantum::Net",
+      "Properties": {
+        "admin_state_up": false
+      }
+    },
+
+    "subnet": {
+      "Type": "OS::Quantum::Subnet",
+      "Properties": {
+        "network_id": { "Ref" : "network" },
+        "ip_version": 4,
+        "cidr": "10.0.3.0/24",
+        "allocation_pools": [{"start": "10.0.3.20", "end": "10.0.3.150"}]
+      }
+    },
+
+    "port": {
+      "Type": "OS::Quantum::Port",
+      "Properties": {
+        "device_id": "d6b4d3a5-c700-476f-b609-1493dd9dadc0",
+        "name": "port1",
+        "network_id": { "Ref" : "network" },
+        "fixed_ips": [{
+          "subnet_id": { "Ref" : "subnet" },
+          "ip_address": "10.0.3.21"
+        }]
+      }
+    },
+
+    "router": {
+      "Type": "OS::Quantum::Router"
+    },
+
+    "router_interface": {
+      "Type": "OS::Quantum::RouterInterface",
+      "Properties": {
+        "router_id": { "Ref" : "router" },
+        "subnet_id": { "Ref" : "subnet" }
+      }
+    }
+  },
+  "Outputs" : {
+    "the_network_status" : {
+      "Value" : { "Fn::GetAtt" : [ "network", "status" ]},
+      "Description" : "Status of network"
+    },
+    "port_device_owner" : {
+      "Value" : { "Fn::GetAtt" : [ "port", "device_owner" ]},
+      "Description" : "Device owner of the port"
+    },
+    "port_fixed_ips" : {
+      "Value" : { "Fn::GetAtt" : [ "port", "fixed_ips" ]},
+      "Description" : "Fixed IPs of the port"
+    },
+    "port_mac_address" : {
+      "Value" : { "Fn::GetAtt" : [ "port", "mac_address" ]},
+      "Description" : "MAC address of the port"
+    },
+    "port_status" : {
+      "Value" : { "Fn::GetAtt" : [ "port", "status" ]},
+      "Description" : "Status of the port"
+    },
+    "port_show" : {
+      "Value" : { "Fn::GetAtt" : [ "port", "show" ]},
+      "Description" : "All attributes for port"
+    },
+    "subnet_show" : {
+      "Value" : { "Fn::GetAtt" : [ "subnet", "show" ]},
+      "Description" : "All attributes for subnet"
+    },
+    "network_show" : {
+      "Value" : { "Fn::GetAtt" : [ "network", "show" ]},
+      "Description" : "All attributes for network"
+    },
+    "router_show" : {
+      "Value" : { "Fn::GetAtt" : [ "router", "show" ]},
+      "Description" : "All attributes for router"
+    }
+  }
+}
\ No newline at end of file
diff --git a/heat/tests/templates/Quantum.yaml b/heat/tests/templates/Quantum.yaml
new file mode 100644 (file)
index 0000000..3015a4f
--- /dev/null
@@ -0,0 +1,72 @@
+HeatTemplateFormatVersion: '2012-12-12'
+Description: Template to test Quantum resources
+Resources:
+  network:
+    Type: OS::Quantum::Net
+    Properties: {name: the_network}
+  unnamed_network:
+    Type: 'OS::Quantum::Net'
+  admin_down_network:
+    Type: OS::Quantum::Net
+    Properties: {admin_state_up: false}
+  subnet:
+    Type: OS::Quantum::Subnet
+    Properties:
+      network_id: {Ref: network}
+      ip_version: 4
+      cidr: 10.0.3.0/24
+      allocation_pools:
+      - {end: 10.0.3.150, start: 10.0.3.20}
+  port:
+    Type: OS::Quantum::Port
+    Properties:
+      device_id: d6b4d3a5-c700-476f-b609-1493dd9dadc0
+      name: port1
+      network_id: {Ref: network}
+      fixed_ips:
+      - subnet_id: {Ref: subnet}
+        ip_address: 10.0.3.21
+  router:
+    Type: 'OS::Quantum::Router'
+  router_interface:
+    Type: OS::Quantum::RouterInterface
+    Properties:
+      router_id: {Ref: router}
+      subnet_id: {Ref: subnet}
+Outputs:
+  the_network_status:
+    Value:
+      Fn::GetAtt: [network, status]
+    Description: Status of network
+  port_device_owner:
+    Value:
+      Fn::GetAtt: [port, device_owner]
+    Description: Device owner of the port
+  port_fixed_ips:
+    Value:
+      Fn::GetAtt: [port, fixed_ips]
+    Description: Fixed IPs of the port
+  port_mac_address:
+    Value:
+      Fn::GetAtt: [port, mac_address]
+    Description: MAC address of the port
+  port_status:
+    Value:
+      Fn::GetAtt: [port, status]
+    Description: Status of the port
+  port_show:
+    Value:
+      Fn::GetAtt: [port, show]
+    Description: All attributes for port
+  subnet_show:
+    Value:
+      Fn::GetAtt: [subnet, show]
+    Description: All attributes for subnet
+  network_show:
+    Value:
+      Fn::GetAtt: [network, show]
+    Description: All attributes for network
+  router_show:
+    Value:
+      Fn::GetAtt: [router, show]
+    Description: All attributes for router
diff --git a/heat/tests/templates/README b/heat/tests/templates/README
new file mode 100644 (file)
index 0000000..2c2716a
--- /dev/null
@@ -0,0 +1,6 @@
+These templates are required by test_template_format, where we don't want to
+use a minimal template snippet (we want ideally to test the maximum possible
+syntax to prove the format conversion works)
+
+In general, tests should not depend on these templates, inline minimal
+template snippets are preferred.
diff --git a/heat/tests/templates/WordPress_Single_Instance.template b/heat/tests/templates/WordPress_Single_Instance.template
new file mode 100644 (file)
index 0000000..3d79430
--- /dev/null
@@ -0,0 +1,149 @@
+{
+  "AWSTemplateFormatVersion" : "2010-09-09",
+
+  "Description" : "AWS CloudFormation Sample Template WordPress_Single_Instance: WordPress is web software you can use to create a beautiful website or blog. This template installs a single-instance WordPress deployment using a local MySQL database to store the data.",
+
+  "Parameters" : {
+
+    "KeyName" : {
+      "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances",
+      "Type" : "String"
+    },
+
+    "InstanceType" : {
+      "Description" : "WebServer EC2 instance type",
+      "Type" : "String",
+      "Default" : "m1.large",
+      "AllowedValues" : [ "t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "c1.medium", "c1.xlarge", "cc1.4xlarge" ],
+      "ConstraintDescription" : "must be a valid EC2 instance type."
+    },
+
+    "DBName": {
+      "Default": "wordpress",
+      "Description" : "The WordPress database name",
+      "Type": "String",
+      "MinLength": "1",
+      "MaxLength": "64",
+      "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
+      "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
+    },
+
+    "DBUsername": {
+      "Default": "admin",
+      "NoEcho": "true",
+      "Description" : "The WordPress database admin account username",
+      "Type": "String",
+      "MinLength": "1",
+      "MaxLength": "16",
+      "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
+      "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
+    },
+
+    "DBPassword": {
+      "Default": "admin",
+      "NoEcho": "true",
+      "Description" : "The WordPress database admin account password",
+      "Type": "String",
+      "MinLength": "1",
+      "MaxLength": "41",
+      "AllowedPattern" : "[a-zA-Z0-9]*",
+      "ConstraintDescription" : "must contain only alphanumeric characters."
+    },
+
+    "DBRootPassword": {
+      "Default": "admin",
+      "NoEcho": "true",
+      "Description" : "Root password for MySQL",
+      "Type": "String",
+      "MinLength": "1",
+      "MaxLength": "41",
+      "AllowedPattern" : "[a-zA-Z0-9]*",
+      "ConstraintDescription" : "must contain only alphanumeric characters."
+    },
+    "LinuxDistribution": {
+      "Default": "F17",
+      "Description" : "Distribution of choice",
+      "Type": "String",
+      "AllowedValues" : [ "F18", "F17", "U10", "RHEL-6.1", "RHEL-6.2", "RHEL-6.3" ]
+    }
+  },
+
+  "Mappings" : {
+    "AWSInstanceType2Arch" : {
+      "t1.micro"    : { "Arch" : "32" },
+      "m1.small"    : { "Arch" : "32" },
+      "m1.large"    : { "Arch" : "64" },
+      "m1.xlarge"   : { "Arch" : "64" },
+      "m2.xlarge"   : { "Arch" : "64" },
+      "m2.2xlarge"  : { "Arch" : "64" },
+      "m2.4xlarge"  : { "Arch" : "64" },
+      "c1.medium"   : { "Arch" : "32" },
+      "c1.xlarge"   : { "Arch" : "64" },
+      "cc1.4xlarge" : { "Arch" : "64" }
+    },
+    "DistroArch2AMI": {
+      "F18"      : { "32" : "F18-i386-cfntools", "64" : "F18-x86_64-cfntools" },
+      "F17"      : { "32" : "F17-i386-cfntools", "64" : "F17-x86_64-cfntools" },
+      "U10"      : { "32" : "U10-i386-cfntools", "64" : "U10-x86_64-cfntools" },
+      "RHEL-6.1" : { "32" : "rhel61-i386-cfntools", "64" : "rhel61-x86_64-cfntools" },
+      "RHEL-6.2" : { "32" : "rhel62-i386-cfntools", "64" : "rhel62-x86_64-cfntools" },
+      "RHEL-6.3" : { "32" : "rhel63-i386-cfntools", "64" : "rhel63-x86_64-cfntools" }
+    }
+  },
+
+  "Resources" : {
+    "WikiDatabase": {
+      "Type": "AWS::EC2::Instance",
+      "Metadata" : {
+        "AWS::CloudFormation::Init" : {
+          "config" : {
+            "packages" : {
+              "yum" : {
+                "mysql"        : [],
+                "mysql-server" : [],
+                "httpd"        : [],
+                "wordpress"    : []
+              }
+            },
+            "services" : {
+              "systemd" : {
+                "mysqld"   : { "enabled" : "true", "ensureRunning" : "true" },
+                "httpd"    : { "enabled" : "true", "ensureRunning" : "true" }
+              }
+            }
+          }
+        }
+      },
+      "Properties": {
+        "ImageId" : { "Fn::FindInMap" : [ "DistroArch2AMI", { "Ref" : "LinuxDistribution" },
+                          { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
+        "InstanceType"   : { "Ref" : "InstanceType" },
+        "KeyName"        : { "Ref" : "KeyName" },
+        "UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
+          "#!/bin/bash -v\n",
+          "/opt/aws/bin/cfn-init\n",
+          "# Setup MySQL root password and create a user\n",
+          "mysqladmin -u root password '", { "Ref" : "DBRootPassword" }, "'\n",
+          "cat << EOF | mysql -u root --password='", { "Ref" : "DBRootPassword" }, "'\n",
+          "CREATE DATABASE ", { "Ref" : "DBName" }, ";\n",
+          "GRANT ALL PRIVILEGES ON ", { "Ref" : "DBName" }, ".* TO \"", { "Ref" : "DBUsername" }, "\"@\"localhost\"\n",
+          "IDENTIFIED BY \"", { "Ref" : "DBPassword" }, "\";\n",
+          "FLUSH PRIVILEGES;\n",
+          "EXIT\n",
+          "EOF\n",
+          "sed -i \"/Deny from All/d\" /etc/httpd/conf.d/wordpress.conf\n",
+          "sed -i \"s/Require local/Require all granted/\" /etc/httpd/conf.d/wordpress.conf\n",
+          "sed --in-place --e s/database_name_here/", { "Ref" : "DBName" }, "/ --e s/username_here/", { "Ref" : "DBUsername" }, "/ --e s/password_here/", { "Ref" : "DBPassword" }, "/ /usr/share/wordpress/wp-config.php\n",
+          "systemctl restart httpd.service\n"
+        ]]}}
+      }
+    }
+  },
+
+  "Outputs" : {
+    "WebsiteURL" : {
+      "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WikiDatabase", "PublicIp" ]}, "/wordpress"]] },
+      "Description" : "URL for Wordpress wiki"
+    }
+  }
+}
diff --git a/heat/tests/templates/WordPress_Single_Instance.yaml b/heat/tests/templates/WordPress_Single_Instance.yaml
new file mode 100644 (file)
index 0000000..eed4fcf
--- /dev/null
@@ -0,0 +1,161 @@
+HeatTemplateFormatVersion: '2012-12-12'
+Description: 'AWS CloudFormation Sample Template WordPress_Single_Instance:
+  WordPress is web software you can use to create a beautiful website or blog. This
+  template installs a single-instance WordPress deployment using a local MySQL database
+  to store the data.'
+Parameters:
+  KeyName: {Description: Name of an existing EC2 KeyPair
+      to enable SSH access to the instances, Type: String}
+  InstanceType:
+    Description: WebServer EC2 instance type
+    Type: String
+    Default: m1.large
+    AllowedValues: [t1.micro, m1.small, m1.large, m1.xlarge, m2.xlarge,
+      m2.2xlarge, m2.4xlarge, c1.medium, c1.xlarge, cc1.4xlarge]
+    ConstraintDescription: must be a valid EC2 instance type.
+  DBName: {Default: wordpress, Description: The
+      WordPress database name, Type: String, MinLength: '1',
+    MaxLength: '64', AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*',
+    ConstraintDescription: must begin with a letter and contain only
+      alphanumeric characters.}
+  DBUsername: {Default: admin, NoEcho: 'true',
+    Description: The WordPress database admin account username, Type: String,
+    MinLength: '1', MaxLength: '16', AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*',
+    ConstraintDescription: must begin with a letter and contain only
+      alphanumeric characters.}
+  DBPassword: {Default: admin, NoEcho: 'true',
+    Description: The WordPress database admin account password, Type: String,
+    MinLength: '1', MaxLength: '41', AllowedPattern: '[a-zA-Z0-9]*',
+    ConstraintDescription: must contain only alphanumeric characters.}
+  DBRootPassword: {Default: admin, NoEcho: 'true',
+    Description: Root password for MySQL, Type: String,
+    MinLength: '1', MaxLength: '41', AllowedPattern: '[a-zA-Z0-9]*',
+    ConstraintDescription: must contain only alphanumeric characters.}
+  LinuxDistribution:
+    Default: F17
+    Description: Distribution of choice
+    Type: String
+    AllowedValues: [F18, F17, U10, RHEL-6.1, RHEL-6.2, RHEL-6.3]
+Mappings:
+  AWSInstanceType2Arch:
+    t1.micro: {Arch: '32'}
+    m1.small: {Arch: '32'}
+    m1.large: {Arch: '64'}
+    m1.xlarge: {Arch: '64'}
+    m2.xlarge: {Arch: '64'}
+    m2.2xlarge: {Arch: '64'}
+    m2.4xlarge: {Arch: '64'}
+    c1.medium: {Arch: '32'}
+    c1.xlarge: {Arch: '64'}
+    cc1.4xlarge: {Arch: '64'}
+  DistroArch2AMI:
+    F18: {'32': F18-i386-cfntools, '64': F18-x86_64-cfntools}
+    F17: {'32': F17-i386-cfntools, '64': F17-x86_64-cfntools}
+    U10: {'32': U10-i386-cfntools, '64': U10-x86_64-cfntools}
+    RHEL-6.1: {'32': rhel61-i386-cfntools, '64': rhel61-x86_64-cfntools}
+    RHEL-6.2: {'32': rhel62-i386-cfntools, '64': rhel62-x86_64-cfntools}
+    RHEL-6.3: {'32': rhel63-i386-cfntools, '64': rhel63-x86_64-cfntools}
+Resources:
+  WikiDatabase:
+    Type: AWS::EC2::Instance
+    Metadata:
+      AWS::CloudFormation::Init:
+        config:
+          packages:
+            yum:
+              mysql: []
+              mysql-server: []
+              httpd: []
+              wordpress: []
+          services:
+            systemd:
+              mysqld: {enabled: 'true', ensureRunning: 'true'}
+              httpd: {enabled: 'true', ensureRunning: 'true'}
+    Properties:
+      ImageId:
+        Fn::FindInMap:
+        - DistroArch2AMI
+        - {Ref: LinuxDistribution}
+        - Fn::FindInMap:
+          - AWSInstanceType2Arch
+          - {Ref: InstanceType}
+          - Arch
+      InstanceType: {Ref: InstanceType}
+      KeyName: {Ref: KeyName}
+      UserData:
+        Fn::Base64:
+          Fn::Join:
+          - ''
+          - - '#!/bin/bash -v
+
+              '
+            - '/opt/aws/bin/cfn-init
+
+              '
+            - '# Setup MySQL root password and create a user
+
+              '
+            - mysqladmin -u root password '
+            - {Ref: DBRootPassword}
+            - '''
+
+              '
+            - cat << EOF | mysql -u root --password='
+            - {Ref: DBRootPassword}
+            - '''
+
+              '
+            - 'CREATE DATABASE '
+            - {Ref: DBName}
+            - ';
+
+              '
+            - 'GRANT ALL PRIVILEGES ON '
+            - {Ref: DBName}
+            - .* TO "
+            - {Ref: DBUsername}
+            - '"@"localhost"
+
+              '
+            - IDENTIFIED BY "
+            - {Ref: DBPassword}
+            - '";
+
+              '
+            - 'FLUSH PRIVILEGES;
+
+              '
+            - 'EXIT
+
+              '
+            - 'EOF
+
+              '
+            - 'sed -i "/Deny from All/d" /etc/httpd/conf.d/wordpress.conf
+
+              '
+            - 'sed -i "s/Require local/Require all granted/" /etc/httpd/conf.d/wordpress.conf
+
+              '
+            - sed --in-place --e s/database_name_here/
+            - {Ref: DBName}
+            - / --e s/username_here/
+            - {Ref: DBUsername}
+            - / --e s/password_here/
+            - {Ref: DBPassword}
+            - '/ /usr/share/wordpress/wp-config.php
+
+              '
+            - 'systemctl restart httpd.service
+
+              '
+Outputs:
+  WebsiteURL:
+    Value:
+      Fn::Join:
+      - ''
+      - - http://
+        - Fn::GetAtt: [WikiDatabase, PublicIp]
+        - /wordpress
+    Description: URL for Wordpress wiki
+
index 03ae62e9e3ad12d68d9bee97bab8408f212342db..eddbb1be02ee5adde9d370d1704f7e0da71bee3b 100644 (file)
@@ -16,24 +16,23 @@ from testtools import skipIf
 import os
 
 from heat.engine import clients
-from heat.common import context
 from heat.common import template_format
-from heat.engine import parser
 from heat.tests.common import HeatTestCase
 from heat.tests.utils import setup_dummy_db
+from heat.tests.utils import parse_stack
 
 
 class JsonToYamlTest(HeatTestCase):
 
     def setUp(self):
         super(JsonToYamlTest, self).setUp()
-        self.expected_test_count = 10
+        self.expected_test_count = 2
         self.longMessage = True
         self.maxDiff = None
 
     def test_convert_all_templates(self):
-        path = os.path.dirname(os.path.realpath(__file__)).\
-            replace('heat/tests', 'templates')
+        path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+                            'templates')
 
         template_test_count = 0
         for (json_str,
@@ -46,8 +45,8 @@ class JsonToYamlTest(HeatTestCase):
                 break
 
         self.assertTrue(template_test_count >= self.expected_test_count,
-                        'Expected at least %d templates to be tested' %
-                        self.expected_test_count)
+                        'Expected at least %d templates to be tested, not %d' %
+                        (self.expected_test_count, template_test_count))
 
     def compare_json_vs_yaml(self, json_str, yml_str, file_name):
         yml = template_format.parse(yml_str)
@@ -101,26 +100,13 @@ class JsonYamlResolvedCompareTest(HeatTestCase):
         setup_dummy_db()
 
     def load_template(self, file_name):
-        self.path = os.path.dirname(os.path.realpath(__file__)).\
-            replace('heat/tests', 'templates')
-        f = open("%s/%s" % (self.path, file_name))
+        filepath = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+                                'templates', file_name)
+        f = open(filepath)
         t = template_format.parse(f.read())
         f.close()
         return t
 
-    def parse_stack(self, t, parameters):
-        ctx = context.RequestContext.from_dict({
-            'tenant': 'test_tenant',
-            'username': 'test_username',
-            'password': 'password',
-            'auth_url': 'http://localhost:5000/v2.0'})
-        stack_name = 'test_stack'
-        template = parser.Template(t)
-        params = parser.Parameters(stack_name, template, parameters)
-        stack = parser.Stack(ctx, stack_name, parser.Template(t), params)
-
-        return stack
-
     def compare_stacks(self, json_file, yaml_file, parameters):
         t1 = self.load_template(json_file)
         template_format.default_for_missing(t1, 'AWSTemplateFormatVersion',
@@ -130,8 +116,8 @@ class JsonYamlResolvedCompareTest(HeatTestCase):
         t2 = self.load_template(yaml_file)
         del(t2[u'HeatTemplateFormatVersion'])
 
-        stack1 = self.parse_stack(t1, parameters)
-        stack2 = self.parse_stack(t2, parameters)
+        stack1 = parse_stack(t1, parameters)
+        stack2 = parse_stack(t2, parameters)
 
         # compare resources separately so that resolved static data
         # is compared