Add designate config for rocky

Change-Id: I3ddc673abe8d23c0b332fac8012d3272f73c0977
Related-Prod: PROD-23724 (PROD:23724)
diff --git a/.kitchen.yml b/.kitchen.yml
index 36ec5b8..2868a31 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -94,67 +94,40 @@
       platform: ubuntu
 
 suites:
-  - name: server_cluster_ocata
+<% for os_version in ['ocata','pike','queens','rocky'] %>
+  - name: server_cluster_<%=os_version%>
     provisioner:
       pillars-from-files:
         designate.sls: tests/pillar/server_cluster.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_ocata.sls
+        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_<%=os_version%>.sls
       pillars:
         release.sls:
           designate:
             server:
-              version: ocata
+              version: <%=os_version%>
     verifier:
       inspec_tests:
-        - tests/integration/ocata/server_cluster
+        - tests/integration/<%=os_version%>/server_cluster
 
-  - name: server_single_ocata
+  - name: server_single_<%=os_version%>
     provisioner:
       pillars-from-files:
         designate.sls: tests/pillar/server_single.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_ocata.sls
+        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_<%=os_version%>.sls
       pillars:
         release.sls:
           designate:
             server:
-              version: ocata
+              version: <%=os_version%>
     verifier:
       inspec_tests:
-        - tests/integration/ocata/server_single
+        - tests/integration/<%=os_version%>/server_single
 
-  - name: server_cluster_pike
+  - name: server_cluster_ssl_<%=os_version%>
     provisioner:
       pillars-from-files:
         designate.sls: tests/pillar/server_cluster.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_pike.sls
-      pillars:
-        release.sls:
-          designate:
-            server:
-              version: pike
-    verifier:
-      inspec_tests:
-        - tests/integration/pike/server_cluster
-
-  - name: server_single_pike
-    provisioner:
-      pillars-from-files:
-        designate.sls: tests/pillar/server_single.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_pike.sls
-      pillars:
-        release.sls:
-          designate:
-            server:
-              version: pike
-    verifier:
-      inspec_tests:
-        - tests/integration/pike/server_single
-
-  - name: server_cluster_ssl
-    provisioner:
-      pillars-from-files:
-        designate.sls: tests/pillar/server_cluster.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_pike.sls
+        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_<%=os_version%>.sls
       pillars:
         top.sls:
           base:
@@ -166,18 +139,18 @@
         release.sls:
           designate:
             server:
-              version: pike
+              version: <%=os_version%>
     verifier:
       inspec_tests:
-        - tests/integration/pike/server_cluster
+        - tests/integration/<%=os_version%>/server_cluster
       attributes:
         ssl: true
 
-  - name: server_single_ssl
+  - name: server_single_ssl_<%=os_version%>
     provisioner:
       pillars-from-files:
         designate.sls: tests/pillar/server_single.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_pike.sls
+        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_<%=os_version%>.sls
       pillars:
         top.sls:
           base:
@@ -189,84 +162,12 @@
         release.sls:
           designate:
             server:
-              version: pike
+              version: <%=os_version%>
     verifier:
       inspec_tests:
-        - tests/integration/pike/server_single
+        - tests/integration/<%=os_version%>/server_single
       attributes:
         ssl: true
 
-  - name: server_cluster_queens
-    provisioner:
-      pillars-from-files:
-        designate.sls: tests/pillar/server_cluster.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_queens.sls
-      pillars:
-        release.sls:
-          designate:
-            server:
-              version: queens
-    verifier:
-      inspec_tests:
-        - tests/integration/queens/server_cluster
-
-  - name: server_single_queens
-    provisioner:
-      pillars-from-files:
-        designate.sls: tests/pillar/server_single.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_queens.sls
-      pillars:
-        release.sls:
-          designate:
-            server:
-              version: queens
-    verifier:
-      inspec_tests:
-        - tests/integration/queens/server_single
-
-  - name: server_cluster_ssl
-    provisioner:
-      pillars-from-files:
-        designate.sls: tests/pillar/server_cluster.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_queens.sls
-      pillars:
-        top.sls:
-          base:
-            "*":
-              - linux_repo_openstack
-              - designate
-              - release
-              - ssl
-        release.sls:
-          designate:
-            server:
-              version: queens
-    verifier:
-      inspec_tests:
-        - tests/integration/queens/server_cluster
-      attributes:
-        ssl: true
-
-  - name: server_single_ssl
-    provisioner:
-      pillars-from-files:
-        designate.sls: tests/pillar/server_single.sls
-        linux_repo_openstack.sls: tests/pillar/repo_mcp_openstack_queens.sls
-      pillars:
-        top.sls:
-          base:
-            "*":
-              - linux_repo_openstack
-              - designate
-              - release
-              - ssl
-        release.sls:
-          designate:
-            server:
-              version: queens
-    verifier:
-      inspec_tests:
-        - tests/integration/queens/server_single
-      attributes:
-        ssl: true
+<% end %>
 # vim: ft=yaml sw=2 ts=2 sts=2 tw=125
diff --git a/designate/files/rocky/api-paste.ini b/designate/files/rocky/api-paste.ini
new file mode 100644
index 0000000..41e840d
--- /dev/null
+++ b/designate/files/rocky/api-paste.ini
@@ -0,0 +1,61 @@
+[composite:osapi_dns]
+use = egg:Paste#urlmap
+/: osapi_dns_versions
+/v2: osapi_dns_v2
+/admin: osapi_dns_admin
+
+[composite:osapi_dns_versions]
+use = call:designate.api.middleware:auth_pipeline_factory
+noauth = http_proxy_to_wsgi cors maintenance faultwrapper osapi_dns_app_versions
+keystone = http_proxy_to_wsgi cors maintenance faultwrapper osapi_dns_app_versions
+
+[app:osapi_dns_app_versions]
+paste.app_factory = designate.api.versions:factory
+
+
+[composite:osapi_dns_v2]
+use = call:designate.api.middleware:auth_pipeline_factory
+noauth = http_proxy_to_wsgi cors request_id faultwrapper validation_API_v2 noauthcontext maintenance normalizeuri osapi_dns_app_v2
+keystone = http_proxy_to_wsgi cors request_id faultwrapper validation_API_v2 authtoken keystonecontext maintenance normalizeuri osapi_dns_app_v2
+
+[app:osapi_dns_app_v2]
+paste.app_factory = designate.api.v2:factory
+
+[composite:osapi_dns_admin]
+use = call:designate.api.middleware:auth_pipeline_factory
+noauth = http_proxy_to_wsgi cors request_id faultwrapper noauthcontext maintenance normalizeuri osapi_dns_app_admin
+keystone = http_proxy_to_wsgi cors request_id faultwrapper authtoken keystonecontext maintenance normalizeuri osapi_dns_app_admin
+
+[app:osapi_dns_app_admin]
+paste.app_factory = designate.api.admin:factory
+
+[filter:cors]
+paste.filter_factory = oslo_middleware.cors:filter_factory
+oslo_config_project = designate
+
+[filter:request_id]
+paste.filter_factory = oslo_middleware:RequestId.factory
+
+[filter:http_proxy_to_wsgi]
+paste.filter_factory = oslo_middleware:HTTPProxyToWSGI.factory
+
+[filter:noauthcontext]
+paste.filter_factory = designate.api.middleware:NoAuthContextMiddleware.factory
+
+[filter:authtoken]
+paste.filter_factory = keystonemiddleware.auth_token:filter_factory
+
+[filter:keystonecontext]
+paste.filter_factory = designate.api.middleware:KeystoneContextMiddleware.factory
+
+[filter:maintenance]
+paste.filter_factory = designate.api.middleware:MaintenanceMiddleware.factory
+
+[filter:normalizeuri]
+paste.filter_factory = designate.api.middleware:NormalizeURIMiddleware.factory
+
+[filter:faultwrapper]
+paste.filter_factory = designate.api.middleware:FaultWrapperMiddleware.factory
+
+[filter:validation_API_v2]
+paste.filter_factory = designate.api.middleware:APIv2ValidationErrorMiddleware.factory
diff --git a/designate/files/rocky/designate.conf.Debian b/designate/files/rocky/designate.conf.Debian
new file mode 100644
index 0000000..bce6609
--- /dev/null
+++ b/designate/files/rocky/designate.conf.Debian
@@ -0,0 +1,1090 @@
+{%- from "designate/map.jinja" import server, pool_manager with context %}
+
+[DEFAULT]
+
+#
+# From designate.opts
+#
+
+# Name of this node (string value)
+#host = current_hostname
+
+# Directory where the designate python module is installed (string value)
+#pybasedir = /usr/lib/python3/dist-packages
+
+# Top-level directory for maintaining designate's state (string value)
+#state_path = /var/lib/designate
+
+# Central Topic (string value)
+#central_topic = central
+
+# mDNS Topic (string value)
+#mdns_topic = mdns
+
+# Pool Manager Topic (string value)
+#pool_manager_topic = pool_manager
+
+# Worker Topic (string value)
+#worker_topic = worker
+
+# TTL Value (integer value)
+#default_ttl = 3600
+
+# SOA refresh-min value (integer value)
+# Deprecated group/name - [DEFAULT]/default_soa_refresh
+#default_soa_refresh_min = 3500
+
+# SOA max value (integer value)
+#default_soa_refresh_max = 3600
+
+# SOA retry (integer value)
+#default_soa_retry = 600
+
+# SOA expire (integer value)
+#default_soa_expire = 86400
+
+# SOA minimum value (integer value)
+#default_soa_minimum = 3600
+
+# Supported record types (list value)
+#supported_record_type = A,AAAA,CNAME,MX,SRV,TXT,SPF,NS,PTR,SSHFP,SOA
+
+# Which API to use. (string value)
+#network_api = neutron
+
+# Send notifications if there's a failure in the API. (boolean value)
+#notify_api_faults = false
+
+# The notification plugin to use (string value)
+#notification_plugin = default
+
+# Quota driver to use (string value)
+#quota_driver = storage
+
+# Number of zones allowed per tenant (integer value)
+#quota_zones = 10
+{%- if server.get('quota', {}).zones is defined %}
+quota_zones = {{ server.quota.zones }}
+{%- endif %}
+
+# Number of recordsets allowed per zone (integer value)
+#quota_zone_recordsets = 500
+
+# Number of records allowed per zone (integer value)
+#quota_zone_records = 500
+
+# Number of records allowed per recordset (integer value)
+#quota_recordset_records = 20
+
+# Number of recordsets allowed in a zone export (integer value)
+#quota_api_export_size = 1000
+
+# Timeout in seconds for XFR's. (integer value)
+#xfr_timeout = 10
+
+# designate-rootwrap configuration (string value)
+#root_helper = sudo designate-rootwrap /etc/designate/rootwrap.conf
+
+# Number of backlog requests to configure the socket with (integer value)
+#backlog = 4096
+
+# Sets the value of TCP_KEEPIDLE in seconds for each server socket. Not supported on OS X. (integer value)
+#tcp_keepidle = 600
+
+{%- if server.logging is defined %}
+{%- set _data = server.logging %}
+{%- include "oslo_templates/files/queens/oslo/_log.conf" %}
+{%- endif %}
+
+{%- set _data = server.message_queue %}
+{%- include "oslo_templates/files/queens/oslo/messaging/_default.conf" %}
+
+#
+# From oslo.service.periodic_task
+#
+
+# Some periodic tasks can be run in a separate process. Should we run them here? (boolean value)
+#run_external_periodic_tasks = true
+
+#
+# From oslo.service.service
+#
+
+# Enable eventlet backdoor.  Acceptable values are 0, <port>, and <start>:<end>, where 0 results in listening on a random tcp port number;
+# <port> results in listening on the specified port number (and not enabling backdoor if that port is in use); and <start>:<end> results in
+# listening on the smallest unused port number within the specified range of port numbers.  The chosen port is displayed in the service's
+# log file. (string value)
+#backdoor_port = <None>
+
+# Enable eventlet backdoor, using the provided path as a unix socket that can receive connections. This option is mutually exclusive with
+# 'backdoor_port' in that only one should be provided. If both are provided then the existence of this option overrides the usage of that
+# option. (string value)
+#backdoor_socket = <None>
+
+# Enables or disables logging values of all registered options when starting a service (at DEBUG level). (boolean value)
+#log_options = true
+
+# Specify a timeout after which a gracefully shutdown server will exit. Zero value means endless wait. (integer value)
+#graceful_shutdown_timeout = 60
+
+
+[backend:agent:bind9]
+
+#
+# From designate.agent
+#
+
+# RNDC Host (string value)
+#rndc_host = 127.0.0.1
+
+# RNDC Port (integer value)
+#rndc_port = 953
+
+# RNDC Config File (string value)
+#rndc_config_file = <None>
+
+# RNDC Key File (string value)
+#rndc_key_file = <None>
+
+# Path where zone files are stored (string value)
+#zone_file_path = $state_path/zones
+
+# Host to query when finding zones (string value)
+#query_destination = 127.0.0.1
+
+
+[backend:agent:denominator]
+
+#
+# From designate.agent
+#
+
+# Name of the affected provider (string value)
+#name = fake
+
+# Path to Denominator configuration file (string value)
+#config_file = /etc/denominator.conf
+
+
+[backend:agent:djbdns]
+
+#
+# From designate.agent
+#
+
+# tcpclient executable path or rootwrap command name (string value)
+#tcpclient_cmd_name = tcpclient
+
+# axfr-get executable path or rootwrap command name (string value)
+#axfr_get_cmd_name = axfr-get
+
+# tinydns-data executable path or rootwrap command name (string value)
+#tinydns_data_cmd_name = tinydns-data
+
+# TinyDNS data directory (string value)
+#tinydns_datadir = /var/lib/djbdns
+
+# Host to query when finding zones (string value)
+#query_destination = 127.0.0.1
+
+
+[backend:agent:gdnsd]
+
+#
+# From designate.agent
+#
+
+# gdnsd executable path or rootwrap command name (string value)
+#gdnsd_cmd_name = gdnsd
+
+# gdnsd configuration directory path (string value)
+#confdir_path = /etc/gdnsd
+
+# Host to query when finding zones (string value)
+#query_destination = 127.0.0.1
+
+
+[backend:agent:knot2]
+
+#
+# From designate.agent
+#
+
+# knotc executable path or rootwrap command name (string value)
+#knotc_cmd_name = knotc
+
+# Host to query when finding zones (string value)
+#query_destination = 127.0.0.1
+
+
+[coordination]
+
+#
+# From designate.opts
+#
+
+# The backend URL to use for distributed coordination. If unset services that need coordination will function as a standalone service. This
+# is a `tooz` url - see https://docs.openstack.org/tooz/latest/user/compatibility.html (string value)
+#backend_url = <None>
+
+# Number of seconds between heartbeats for distributed coordination. (floating point value)
+#heartbeat_interval = 1.0
+
+# Number of seconds between checks to see if group membership has changed (floating point value)
+#run_watchers_interval = 10.0
+
+
+[cors]
+{%- if server.cors is defined %}
+{%- set _data = server.cors %}
+{%- include "oslo_templates/files/queens/oslo/_cors.conf" %}
+{%- endif %}
+
+
+{%- for name, _data in server.notification_handlers.iteritems() %}
+{%- if not _data.get('zone_id') %}
+  {%- do _data.update({'zone_id': server.domain_id}) %}
+{%- endif %}
+
+{% include "designate/files/" + server.version|string + "/notification_handlers/_" + name + ".conf" %}
+{%- endfor %}
+
+[healthcheck]
+{%- if server.healthcheck is defined %}
+{%- set _data = server.healthcheck %}
+{%- include "oslo_templates/files/queens/oslo/_healthcheck.conf" %}
+{%- endif %}
+
+[heartbeat_emitter]
+
+#
+# From designate.opts
+#
+
+# Number of seconds between heartbeats for reporting state (floating point value)
+#heartbeat_interval = 5.0
+
+# Emitter to use (string value)
+#emitter_type = rpc
+
+
+[keystone]
+
+#
+# From designate.opts
+#
+
+# The default service_type for endpoint URL discovery. (string value)
+#service_type = <None>
+
+# The default service_name for endpoint URL discovery. (string value)
+#service_name = <None>
+
+# List of interfaces, in order of preference, for endpoint URL. (list value)
+#valid_interfaces = <None>
+
+# The default region_name for endpoint URL discovery. (string value)
+#region_name = <None>
+
+# Always use this endpoint URL for requests for this client. NOTE: The unversioned endpoint should be specified here; to request a
+# particular API version, use the `version`, `min-version`, and/or `max-version` options. (string value)
+#endpoint_override = <None>
+
+# Minimum Major API version within a given Major API version for endpoint URL discovery. Mutually exclusive with min_version and max_version
+# (string value)
+#version = <None>
+
+# The minimum major version of a given API, intended to be used as the lower bound of a range with max_version. Mutually exclusive with
+# version. If min_version is given with no max_version it is as if max version is "latest". (string value)
+#min_version = <None>
+
+# The maximum major version of a given API, intended to be used as the upper bound of a range with min_version. Mutually exclusive with
+# version. (string value)
+#max_version = <None>
+
+# DEPRECATED: The default interface for endpoint URL discovery. (string value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Using valid-interfaces is preferrable because it is capable of accepting a list of possible interfaces.
+#interface = <None>
+
+# PEM encoded Certificate Authority to use when verifying HTTPs connections. (string value)
+#cafile = <None>
+
+# PEM encoded client certificate cert file (string value)
+#certfile = <None>
+
+# PEM encoded client certificate key file (string value)
+#keyfile = <None>
+
+# Verify HTTPS connections. (boolean value)
+#insecure = false
+
+# Timeout value for http requests (integer value)
+#timeout = <None>
+
+# Collect per-API call timing information. (boolean value)
+#collect_timing = false
+
+# Log requests to multiple loggers. (boolean value)
+#split_loggers = false
+
+
+[keystone_authtoken]
+{%- set _data = server.identity %}
+{%- if 'cacert_file' not in _data.keys() %}{% do _data.update({'cacert_file': server.cacert_file}) %}{% endif %}
+{%- set auth_type = _data.get('auth_type', 'password') %}
+{%- include "oslo_templates/files/queens/keystonemiddleware/_auth_token.conf" %}
+{%- include "oslo_templates/files/queens/keystoneauth/_type_" + auth_type + ".conf" %}
+
+
+[matchmaker_redis]
+
+#
+# From oslo.messaging
+#
+
+# DEPRECATED: Host to locate redis. (string value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by [DEFAULT]/transport_url
+#host = 127.0.0.1
+
+# DEPRECATED: Use this port to connect to redis host. (port value)
+# Minimum value: 0
+# Maximum value: 65535
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by [DEFAULT]/transport_url
+#port = 6379
+
+# DEPRECATED: Password for Redis server (optional). (string value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by [DEFAULT]/transport_url
+#password =
+
+# DEPRECATED: List of Redis Sentinel hosts (fault tolerance mode), e.g., [host:port, host1:port ... ] (list value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by [DEFAULT]/transport_url
+#sentinel_hosts =
+
+# Redis replica set name. (string value)
+#sentinel_group_name = oslo-messaging-zeromq
+
+# Time in ms to wait between connection attempts. (integer value)
+#wait_timeout = 2000
+
+# Time in ms to wait before the transaction is killed. (integer value)
+#check_timeout = 20000
+
+# Timeout in ms on blocking socket operations. (integer value)
+#socket_timeout = 10000
+
+
+[monasca:statsd]
+
+#
+# From designate.opts
+#
+
+# enable (boolean value)
+#enabled = false
+
+# UDP port (integer value)
+#port = 8125
+
+# hostname (string value)
+#hostname = 127.0.0.1
+
+
+[network_api:neutron]
+
+#
+# From designate.opts
+#
+
+# URL to use if None in the ServiceCatalog that is passed by the request context. Format: <region>|<url> (list value)
+#endpoints = <None>
+
+# Endpoint type to use (string value)
+#endpoint_type = publicURL
+
+# timeout value for connecting to neutron in seconds (integer value)
+#timeout = 30
+
+# username for connecting to neutron in admin context (string value)
+#admin_username = <None>
+
+# password for connecting to neutron in admin context (string value)
+#admin_password = <None>
+
+# tenant name for connecting to neutron in admin context (string value)
+#admin_tenant_name = <None>
+
+# auth url for connecting to neutron in admin context (string value)
+#auth_url = <None>
+
+# if set, ignore any SSL validation issues (boolean value)
+#insecure = false
+
+# auth strategy for connecting to neutron in admin context (string value)
+#auth_strategy = keystone
+
+# Location of ca certificates file to use for neutron client requests. (string value)
+#ca_certificates_file = <None>
+
+
+[oslo_concurrency]
+{%- set _data = server.get('concurrency', {}) %}
+{%- include "oslo_templates/files/queens/oslo/_concurrency.conf" %}
+
+
+[oslo_messaging_notifications]
+{%- set _data = server.get('notification', {}) %}
+{%- include "oslo_templates/files/queens/oslo/messaging/_notifications.conf" %}
+
+
+{%- if server.message_queue is defined %}
+{%- set _data = server.message_queue %}
+{%- if _data.engine == 'rabbitmq' %}
+    {%- set messaging_engine = 'rabbit' %}
+{%- else %}
+    {%- set messaging_engine = _data.engine %}
+{%- endif %}
+[oslo_messaging_{{ messaging_engine }}]
+{%- include "oslo_templates/files/queens/oslo/messaging/_" + messaging_engine + ".conf" %}
+{%- endif %}
+
+
+[oslo_middleware]
+{%- set _data = server %}
+{%- include "oslo_templates/files/queens/oslo/_middleware.conf" %}
+
+[oslo_policy]
+{%- include "oslo_templates/files/queens/oslo/_policy.conf" %}
+
+[pool_manager_cache:memcache]
+
+#
+# From designate.opts
+#
+
+# Time in seconds to expire cache. (integer value)
+#expiration = 3600
+
+# Memcached servers or None for in process cache. (list value)
+#memcached_servers = <None>
+
+
+[pool_manager_cache:sqlalchemy]
+{%- set _data = {} %}
+{%- do _data.update({'engine': server.database.engine, 'user': server.database.user, 'password': server.database.password, 'host': server.database.host, 'name': server.database.name.pool_manager})%}
+{%- if server.database.x509 is defined %}
+{%- do _data.update({'x509': server.database.x509}) %}
+{%- endif %}
+{%- if server.database.ssl is defined %}
+{%- do _data.update({'ssl': server.database.ssl}) %}
+{%- if 'cacert_file' not in server.database.ssl.keys() %}{% do _data['ssl'].update({'cacert_file': server.cacert_file}) %}{% endif %}
+{%- endif %}
+{%- include "oslo_templates/files/queens/oslo/_database.conf" %}
+
+[producer_task:delayed_notify]
+
+#
+# From designate.producer
+#
+
+# Run interval in seconds (integer value)
+#interval = 5
+
+# Default amount of results returned per page (integer value)
+#per_page = 100
+
+# How many zones to receive NOTIFY on each run (integer value)
+#batch_size = 100
+
+
+[producer_task:periodic_exists]
+
+#
+# From designate.producer
+#
+
+# Run interval in seconds (integer value)
+#interval = 3600
+
+# Default amount of results returned per page (integer value)
+#per_page = 100
+
+
+[producer_task:periodic_secondary_refresh]
+
+#
+# From designate.producer
+#
+
+# Run interval in seconds (integer value)
+#interval = 3600
+
+# Default amount of results returned per page (integer value)
+#per_page = 100
+
+
+[producer_task:worker_periodic_recovery]
+
+#
+# From designate.producer
+#
+
+# Run interval in seconds (integer value)
+#interval = 120
+
+# Default amount of results returned per page (integer value)
+#per_page = 100
+
+
+[producer_task:zone_purge]
+
+#
+# From designate.producer
+#
+
+# Run interval in seconds (integer value)
+#interval = 3600
+
+# Default amount of results returned per page (integer value)
+#per_page = 100
+
+# How old deleted zones should be (deleted_at) to be purged, in seconds (integer value)
+#time_threshold = 604800
+
+# How many zones to be purged on each run (integer value)
+#batch_size = 100
+
+
+[proxy]
+
+#
+# From designate.opts
+#
+
+# Proxy HTTP requests via this proxy. (string value)
+#http_proxy = <None>
+
+# Proxy HTTPS requests via this proxy (string value)
+#https_proxy = <None>
+
+# These addresses should not be proxied (list value)
+#no_proxy =
+
+
+[service:agent]
+
+#
+# From designate.agent
+#
+
+# Number of agent worker processes to spawn (integer value)
+#workers = <None>
+
+# Number of agent greenthreads to spawn (integer value)
+#threads = 1000
+
+# DEPRECATED: Agent Bind Host (IP address value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by 'listen' option
+#host = <None>
+
+# DEPRECATED: Agent Port Number (port value)
+# Minimum value: 0
+# Maximum value: 65535
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by 'listen' option
+#port = <None>
+
+# Agent host:port pairs to listen on (list value)
+#listen = 0.0.0.0:5358
+
+# The Agent TCP Backlog (integer value)
+#tcp_backlog = 100
+
+# Agent TCP Receive Timeout (floating point value)
+#tcp_recv_timeout = 0.5
+
+# List of IP addresses allowed to NOTIFY The Agent (list value)
+#allow_notify =
+
+# List of masters for the Agent, format ip:port (list value)
+#masters =
+
+# The backend driver to use, e.g. bind9, djbdns, knot2 (string value)
+#backend_driver = bind9
+
+# An IP address to be used to fetch zones transferred in (string value)
+#transfer_source = <None>
+
+# Delay after a NOTIFY arrives for a zone that the Agent will pause and drop subsequent NOTIFYs for that zone (floating point value)
+#notify_delay = 0.0
+
+
+[service:api]
+
+#
+# From designate.api
+#
+
+# Number of api worker processes to spawn (integer value)
+#workers = <None>
+
+# Number of api greenthreads to spawn (integer value)
+#threads = 1000
+
+# Enable host request headers (boolean value)
+#enable_host_header = false
+
+# the url used as the base for all API responses,This should consist of the scheme (http/https),the hostname, port, and any paths that are
+# addedto the base of Designate is URLs,For example http://dns.openstack.example.com/dns (string value)
+#api_base_uri = http://127.0.0.1:9001/
+api_base_uri = {{ server.api.base_uri }}
+
+# DEPRECATED: API Bind Host (IP address value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by 'listen' option
+#api_host = <None>
+
+# DEPRECATED: API Port Number (port value)
+# Minimum value: 0
+# Maximum value: 65535
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by 'listen' option
+#api_port = <None>
+
+# API host:port pairs to listen on (list value)
+#listen = 0.0.0.0:9001
+listen = {{ server.bind.api.address }}:9001
+
+# File name for the paste.deploy config for designate-api (string value)
+#api_paste_config = api-paste.ini
+
+# The strategy to use for auth. Supports noauth or keystone (string value)
+#auth_strategy = keystone
+
+# enable-api-v2 which enable in a future (boolean value)
+#enable_api_v2 = true
+
+# enable-api-admin (boolean value)
+#enable_api_admin = false
+enable_api_admin = {{ server.get('admin_api', {}).get('enabled', False) }}
+
+# Maximum line size of message headers to be accepted. max_header_line may need to be increased when using large tokens (typically those
+# generated by the Keystone v3 API with big service catalogs). (integer value)
+#max_header_line = 16384
+
+# Enabled API Extensions for the V2 API (list value)
+#enabled_extensions_v2 =
+enabled_extensions_v2 = quotas,reports
+
+# Default per-page limit for the V2 API, a value of None means show all results by default (integer value)
+#default_limit_v2 = 20
+
+# Max per-page limit for the V2 API (integer value)
+#max_limit_v2 = 1000
+
+# Verify that the requested Project ID for quota target is a valid project in Keystone. (boolean value)
+#quotas_verify_project_id = false
+
+# Enabled Admin API Extensions (list value)
+#enabled_extensions_admin =
+{%- if server.get('admin_api', {}).get('enabled_extensions_admin', False) %}
+enabled_extensions_admin = {{ server.admin_api.enabled_extensions_admin }}
+{%- endif %}
+
+# Default per-page limit for the Admin API, a value of None means show all results by default (integer value)
+#default_limit_admin = 20
+
+# Max per-page limit for the Admin API (integer value)
+#max_limit_admin = 1000
+
+# Enable API Maintenance Mode (boolean value)
+#maintenance_mode = false
+
+# Role allowed to bypass maintaince mode (string value)
+#maintenance_mode_role = admin
+
+# The HTTP Header that will be used to determine which the original request protocol scheme was, even if it was removed by an SSL
+# terminating proxy. (string value)
+#secure_proxy_ssl_header = X-Forwarded-Proto
+
+# A scheme that will be used to override the request protocol scheme, even if it was set by an SSL terminating proxy. (string value)
+#override_proto = <None>
+
+# Verify that the requested Project ID for quota target
+# is a valid project in Keystone.
+quotas_verify_project_id = {{ server.api.get('quotas_verify_project_id', False) }}
+
+[service:central]
+
+#
+# From designate.central
+#
+
+# Number of central worker processes to spawn (integer value)
+#workers = <None>
+
+# Number of central greenthreads to spawn (integer value)
+#threads = 1000
+
+# The storage driver to use (string value)
+#storage_driver = sqlalchemy
+
+# Enabled Notification Handlers (list value)
+#enabled_notification_handlers =
+
+# Maximum zone name length (integer value)
+#max_zone_name_len = 255
+
+# Maximum recordset name length (integer value)
+# Deprecated group/name - [service:central]/max_record_name_len
+#max_recordset_name_len = 255
+
+# E-Mail for Managed resources (string value)
+#managed_resource_email = hostmaster@example.com
+
+# The Tenant ID that will own any managed resources. (string value)
+#managed_resource_tenant_id = 00000000-0000-0000-0000-000000000000
+
+# Minimum TTL allowed (integer value)
+#min_ttl = <None>
+
+# The name of the default pool (string value)
+#default_pool_id = 794ccc2c-d751-44fe-b57f-8894c9f5c842
+
+# RPC topic name of central service. (string value)
+#central_topic = central
+
+#
+# From designate.opts
+#
+
+# Enabled Pool Scheduling filters (list value)
+#scheduler_filters = default_pool
+
+
+[service:mdns]
+
+#
+# From designate.mdns
+#
+
+# Number of mdns worker processes to spawn (integer value)
+#workers = <None>
+
+# Number of mdns greenthreads to spawn (integer value)
+#threads = 1000
+
+# DEPRECATED: mDNS Bind Host (IP address value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by 'listen' option
+#host = <None>
+
+# DEPRECATED: mDNS Port Number (port value)
+# Minimum value: 0
+# Maximum value: 65535
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Replaced by 'listen' option
+#port = <None>
+
+# mDNS host:port pairs to listen on (list value)
+#listen = 0.0.0.0:5354
+listen = {{ server.mdns.address }}:{{ server.mdns.port }}
+
+# mDNS TCP Backlog (integer value)
+#tcp_backlog = 100
+
+# mDNS TCP Receive Timeout (floating point value)
+#tcp_recv_timeout = 0.5
+
+# Send all traffic over TCP (boolean value)
+#all_tcp = false
+
+# Enforce all incoming queries (including AXFR) are TSIG signed (boolean value)
+#query_enforce_tsig = false
+
+# The storage driver to use (string value)
+#storage_driver = sqlalchemy
+
+# Maximum message size to emit (integer value)
+#max_message_size = 65535
+
+# RPC topic name for mini-DNS (string value)
+#mdns_topic = mdns
+
+
+[service:pool_manager]
+
+#
+# From designate.pool_manager
+#
+
+# Number of Pool Manager worker processes to spawn (integer value)
+#workers = <None>
+{%- if pool_manager.workers is defined %}
+workers = {{ pool_manager.workers }}
+{%- endif %}
+
+# Number of Pool Manager greenthreads to spawn (integer value)
+#threads = 1000
+
+# The ID of the pool managed by this instance of the Pool Manager (string value)
+#pool_id = 794ccc2c-d751-44fe-b57f-8894c9f5c842
+{%- if pool_manager.pool_id is defined %}
+pool_id = {{ pool_manager.pool_id }}
+{%- endif %}
+
+# DEPRECATED: The percentage of servers requiring a successful update for a zone change to be considered active (integer value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#threshold_percentage = 100
+
+# DEPRECATED: The time to wait for a response from a server (integer value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#poll_timeout = 30
+
+# DEPRECATED: The time between retrying to send a request and waiting for a response from a server (integer value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#poll_retry_interval = 15
+
+# DEPRECATED: The maximum number of times to retry sending a request and wait for a response from a server (integer value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#poll_max_retries = 10
+
+# DEPRECATED: The time to wait before sending the first request to a server (integer value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#poll_delay = 5
+
+# The flag for the recovery timer (boolean value)
+#enable_recovery_timer = true
+
+# The time between recovering from failures (integer value)
+#periodic_recovery_interval = 120
+
+# The flag for the sync timer (boolean value)
+#enable_sync_timer = true
+{%- if pool_manager.enable_sync_timer is defined %}
+enable_sync_timer = {{ pool_manager.enable_sync_timer }}
+{%- endif %}
+
+# The time between synchronizing the servers with storage (integer value)
+#periodic_sync_interval = 1800
+{%- if pool_manager.periodic_sync_interval is defined %}
+periodic_sync_interval = {{ pool_manager.periodic_sync_interval }}
+{%- endif %}
+
+# Zones Updated within last N seconds will be syncd.Use an empty value to sync all zones. (integer value)
+#periodic_sync_seconds = 21600
+{%- if pool_manager.periodic_sync_seconds is defined %}
+periodic_sync_seconds = {{ pool_manager.periodic_sync_seconds }}
+{%- endif %}
+
+# Number of attempts to update a zone during sync (integer value)
+#periodic_sync_max_attempts = 3
+{%- if pool_manager.periodic_sync_max_attempts is defined %}
+periodic_sync_max_attempts = {{ pool_manager.periodic_sync_max_attempts }}
+{%- endif %}
+
+# Interval between zone update attempts during sync (integer value)
+#periodic_sync_retry_interval = 30
+{%- if pool_manager.periodic_sync_retry_interval is defined %}
+periodic_sync_retry_interval = {{ pool_manager.periodic_sync_retry_interval }}
+{%- endif %}
+
+# The cache driver to use (string value)
+#cache_driver = memcache
+
+# RPC topic name for pool-manager (string value)
+#pool_manager_topic = pool_manager
+
+
+[service:producer]
+
+#
+# From designate.producer
+#
+
+# Number of Producer worker processes to spawn (integer value)
+#workers = <None>
+
+# Number of Producer greenthreads to spawn (integer value)
+#threads = 1000
+
+# Enabled tasks to run (list value)
+#enabled_tasks = <None>
+
+# The storage driver to use (string value)
+#storage_driver = sqlalchemy
+
+# DEPRECATED: Whether to allow synchronous zone exports (boolean value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#export_synchronous = true
+
+
+[service:sink]
+
+#
+# From designate.sink
+#
+
+# Number of sink worker processes to spawn (integer value)
+#workers = <None>
+
+# Number of sink greenthreads to spawn (integer value)
+#threads = 1000
+
+# Enabled Notification Handlers (list value)
+#enabled_notification_handlers =
+{%- set handlers = [] %}
+{%- for name, handler in server.notification_handlers.iteritems() %}
+  {%- if handler.get('enabled', False) %}
+    {%- do handlers.append(name) %}
+  {%- endif %}
+{%- endfor %}
+{%- if handlers %}
+enabled_notification_handlers = {{ handlers|sort|join(', ') }}
+{%- endif %}
+
+# pool name to use for oslo.messaging notification listener. Note that listener pooling is not supported by all oslo.messaging drivers.
+# (string value)
+#listener_pool_name = <None>
+listener_pool_name = {{ server.get('sink', {}).get('listener_pool_name', 'designate-sink') }}
+
+
+[service:worker]
+
+#
+# From designate.worker
+#
+
+# DEPRECATED: Whether to send events to worker instead of Pool Manager (boolean value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: In Rocky, this option will disappear because worker will be enabled by default
+#enabled = false
+{# TODO: remove enabled option when https://bugs.launchpad.net/designate/+bug/1676827 is fixed #}
+# Whether to send events to worker instead of Pool Manager
+{%- if pool_manager.enabled is defined and pool_manager.enabled == true %}
+enabled = False
+{%- else %}
+enabled = True
+{%- endif %}
+
+
+# Number of Worker worker processes to spawn (integer value)
+#workers = <None>
+
+# Number of Worker threads to spawn per process (integer value)
+#threads = 200
+
+# The storage driver to use (string value)
+#storage_driver = sqlalchemy
+
+# The percentage of servers requiring a successful update for a domain change to be considered active (integer value)
+#threshold_percentage = 100
+
+# The time to wait for a response from a server (integer value)
+#poll_timeout = 30
+
+# The time between retrying to send a request and waiting for a response from a server (integer value)
+#poll_retry_interval = 15
+
+# The maximum number of times to retry sending a request and wait for a response from a server (integer value)
+#poll_max_retries = 10
+
+# The time to wait before sending the first request to a server (integer value)
+#poll_delay = 5
+
+# Whether to allow worker to send NOTIFYs, this will noop NOTIFYs in mdns if true (boolean value)
+#notify = true
+
+# Whether to allow synchronous zone exports (boolean value)
+#export_synchronous = true
+
+# RPC topic for worker component (string value)
+#worker_topic = worker
+
+
+[service:zone_manager]
+
+#
+# From designate.producer
+#
+
+# DEPRECATED: Number of Zone Manager worker processes to spawn (integer value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#workers = <None>
+
+# DEPRECATED: Number of Zone Manager greenthreads to spawn (integer value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#threads = 1000
+
+# DEPRECATED: Enabled tasks to run (list value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#enabled_tasks = <None>
+
+# DEPRECATED: The storage driver to use (string value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#storage_driver = sqlalchemy
+
+# DEPRECATED: Whether to allow synchronous zone exports (boolean value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
+# Reason: Migrated to designate-worker
+#export_synchronous = true
+
+[keystone]
+valid_interfaces = {{ server.identity.get('endpoint_type', 'internal') }}
+region_name = {{ server.region }}
+{%- if server.identity.get('protocol', 'http') == 'https' %}
+cafile = {{ server.identity.get('cacert_file', server.cacert_file)  }}
+{%- endif %}
+
+[ssl]
+{%- include "oslo_templates/files/queens/oslo/service/_ssl.conf" %}
+
+[storage:sqlalchemy]
+{%- set _data = {} %}
+{%- do _data.update({'engine': server.database.engine, 'user': server.database.user, 'password': server.database.password, 'host': server.database.host, 'name': server.database.name.main_database})%}
+{%- if server.database.x509 is defined %}
+{%- do _data.update({'x509': server.database.x509}) %}
+{%- endif %}
+{%- if server.database.ssl is defined %}
+{%- do _data.update({'ssl': server.database.ssl}) %}
+{%- if 'cacert_file' not in server.database.ssl.keys() %}{% do _data['ssl'].update({'cacert_file': server.cacert_file}) %}{% endif %}
+{%- endif %}
+{%- include "oslo_templates/files/queens/oslo/_database.conf" %}
diff --git a/designate/files/rocky/notification_handlers/_neutron_floatingip.conf b/designate/files/rocky/notification_handlers/_neutron_floatingip.conf
new file mode 100644
index 0000000..eb6927f
--- /dev/null
+++ b/designate/files/rocky/notification_handlers/_neutron_floatingip.conf
@@ -0,0 +1,35 @@
+[handler:neutron_floatingip]
+
+#
+# From designate.opts
+#
+
+# notification any events from neutron (list value)
+#notification_topics = notifications
+{%- if _data.notification_topics is defined %}
+notification_topics = {{ _data.notification_topics }}
+{%- endif %}
+
+# control-exchange for neutron notification (string value)
+#control_exchange = neutron
+{%- if _data.control_exchange is defined %}
+control_exchange = {{ _data.control_exchange }}
+{%- endif %}
+
+# Zone ID with each notification (string value)
+#zone_id = <None>
+{%- if _data.zone_id is defined %}
+zone_id = {{ _data.zone_id }}
+{%- endif %}
+
+# IPv4 format (multi valued)
+#formatv4 =
+{%- if _data.formatv4 is defined %}
+formatv4 = {{ _data.formatv4 | yaml_squote }}
+{%- endif %}
+
+# IPv6 format (multi valued)
+#formatv6 =
+{%- if _data.formatv6 is defined %}
+formatv6 = {{ _data.formatv6 | yaml_squote }}
+{%- endif %}
\ No newline at end of file
diff --git a/designate/files/rocky/notification_handlers/_nova_fixed.conf b/designate/files/rocky/notification_handlers/_nova_fixed.conf
new file mode 100644
index 0000000..6a4b4b1
--- /dev/null
+++ b/designate/files/rocky/notification_handlers/_nova_fixed.conf
@@ -0,0 +1,35 @@
+[handler:nova_fixed]
+
+#
+# From designate.opts
+#
+
+# notification any events from nova (list value)
+#notification_topics = notifications
+{%- if _data.notification_topics is defined %}
+notification_topics = {{ _data.notification_topics }}
+{%- endif %}
+
+# control-exchange for nova notification (string value)
+#control_exchange = nova
+{%- if _data.control_exchange is defined %}
+control_exchange = {{ _data.control_exchange }}
+{%- endif %}
+
+# Zone ID with each notification (string value)
+#zone_id = <None>
+{%- if _data.zone_id is defined %}
+zone_id = {{ _data.zone_id }}
+{%- endif %}
+
+# IPv4 format (multi valued)
+#formatv4 =
+{%- if _data.formatv4 is defined %}
+formatv4 = {{ _data.formatv4 | yaml_squote }}
+{%- endif %}
+
+# IPv6 format (multi valued)
+#formatv6 =
+{%- if _data.formatv6 is defined %}
+formatv6 = {{ _data.formatv6 | yaml_squote }}
+{%- endif %}
\ No newline at end of file
diff --git a/designate/files/rocky/pools.yaml b/designate/files/rocky/pools.yaml
new file mode 100644
index 0000000..c911e9a
--- /dev/null
+++ b/designate/files/rocky/pools.yaml
@@ -0,0 +1,73 @@
+{%- from "designate/map.jinja" import server with context %}
+{% for pool_name, pool in server.pools.iteritems() -%}
+- name: {{ pool_name }}
+  # The name is immutable. There will be no option to change the name after
+  # creation and the only way will to change it will be to delete it
+  # (and all zones associated with it) and recreate it.
+  description: {{ pool.description }}
+
+  {%- if pool.attributes is defined %}
+  # Attributes are Key:Value pairs that describe the pool. for example the level
+  # of service (i.e. service_tier:GOLD), capabilities (i.e. anycast: true) or
+  # other metadata. Users can use this information to point their zones to the
+  # correct pool
+  attributes:
+    {%- for k,v in pool.attributes.items() %}
+    {{ k }}: {{ v }}
+    {%- endfor %}
+  {%- endif %}
+
+  # List out the NS records for zones hosted within this pool
+  ns_records:
+    {% for rec in pool.ns_records -%}
+    - hostname: {{ rec.hostname }}
+      priority: {{ rec.priority }}
+    {% endfor -%}
+
+  # List out the nameservers for this pool. These are the actual DNS servers.
+  # We use these to verify changes have propagated to all nameservers.
+  nameservers:
+    {% for nameserver in pool.nameservers -%}
+    - host: {{ nameserver.host }}
+      port: {{ nameserver.port }}
+    {% endfor -%}
+
+  # List out the targets for this pool. For DNS there will be one
+  # entry for each DNS server, as we have to run rndc command on each server
+  targets:
+    {% for target_name, target in pool.targets.iteritems() -%}
+    - type: {{ target.type }}
+      description: {{ target.description }}
+
+      # List out the designate-mdns servers from which DNS servers should
+      # request zone transfers (AXFRs) from.
+      masters:
+        {% for master in target.masters -%}
+        - host: {{ master.host }}
+          port: {{ master.port }}
+        {% endfor -%}
+
+      # DNS server Configuration options
+      options:
+        host: {{ target.options.host }}
+        port: {{ target.options.port }}
+        {%- if target.type == 'bind9' %}
+        rndc_host: {{ target.options.rndc_host }}
+        rndc_port: {{ target.options.rndc_port }}
+        rndc_key_file: {{ target.options.rndc_key_file }}
+        {%- elif target.type == 'pdns4' %}
+        api_endpoint: {{ target.options.api_endpoint }}
+        api_token: {{ target.options.api_token }}
+        {%- endif %}
+    {% endfor -%}
+
+  {%- if pool.also_notifies is defined %}
+  # Optional list of additional IP/Port's for which designate-mdns will send
+  # DNS NOTIFY packets to
+  also_notifies:
+    {%- for notify in pool.also_notifies %}
+    - host: {{ notify.host }}
+      port: {{ notify.port }}
+    {%- endfor %}
+  {%- endif %}
+{%- endfor %}
diff --git a/tests/integration/rocky/server_cluster/config_spec.rb b/tests/integration/rocky/server_cluster/config_spec.rb
new file mode 100644
index 0000000..6c5a738
--- /dev/null
+++ b/tests/integration/rocky/server_cluster/config_spec.rb
@@ -0,0 +1,77 @@
+ssl_enabled = attribute("ssl", default: false)
+
+oslo_messaging_default_ssl = {
+  'transport_url' => 'rabbit://openstack:password@127.0.0.1:5671,openstack:password@127.0.0.2:5671,openstack:password@127.0.0.3:5671//openstack'
+}
+
+oslo_messaging_rabbit_ssl = {
+  'ssl'         => 'true',
+  'ssl_version' => 'TLSv1_2',
+  'ssl_ca_file' => '/etc/designate/ssl/mysql/ca-cert.pem',
+}
+
+oslo_messaging_default = {
+  'transport_url' => 'rabbit://openstack:password@127.0.0.1:5672,openstack:password@127.0.0.2:5672,openstack:password@127.0.0.3:5672//openstack'
+}
+
+oslo_messaging_rabbit = {}
+
+service_sink = {
+  'enabled_notification_handlers' => 'neutron_floatingip, nova_fixed'
+}
+
+handler_nova_fixed = {
+  'zone_id'  => '5186883b-91fb-4891-bd49-e6769234a8fc',
+  'formatv4' => "'%(hostname)s.%(zone)s'",
+  'formatv6' => "'%(hostname)s.%(zone)s'",
+}
+
+handler_neutron_floatingip = {
+  'zone_id'  => '5186883b-91fb-4891-bd49-e6769234a8fc',
+  'formatv4' => "'%(octet0)s-%(octet1)s-%(octet2)s-%(octet3)s.%(zone)s'",
+}
+
+control 'Designate' do
+
+  describe parse_config_file('/etc/designate/designate.conf') do
+
+    describe 'Designate messaging' do
+
+      if ssl_enabled
+        oslo_messaging_default.merge!(oslo_messaging_default_ssl)
+        oslo_messaging_rabbit.merge!(oslo_messaging_rabbit_ssl)
+        describe 'SSL' do
+          its('DEFAULT') {
+            should include(oslo_messaging_default)
+          }
+          its('oslo_messaging_rabbit') {
+            should include(oslo_messaging_rabbit)
+          }
+        end
+      else
+        describe 'non SSL' do
+          its('DEFAULT') do
+            should include(oslo_messaging_default)
+          end
+        end
+      end
+
+    end
+
+    describe 'Designate notification handlers' do
+
+      its('service:sink') do
+        should include(service_sink)
+      end
+
+      its('handler:nova_fixed') do
+        should include(handler_nova_fixed)
+      end
+
+      its('handler:neutron_floatingip') do
+        should include(handler_neutron_floatingip)
+      end
+
+    end
+  end
+end
\ No newline at end of file
diff --git a/tests/integration/rocky/server_single/config_spec.rb b/tests/integration/rocky/server_single/config_spec.rb
new file mode 100644
index 0000000..ee8ca13
--- /dev/null
+++ b/tests/integration/rocky/server_single/config_spec.rb
@@ -0,0 +1,77 @@
+ssl_enabled = attribute("ssl", default: false)
+
+oslo_messaging_default_ssl = {
+  'transport_url' => 'rabbit://openstack:password@127.0.0.1:5671//openstack'
+}
+
+oslo_messaging_rabbit_ssl = {
+  'ssl'         => 'true',
+  'ssl_version' => 'TLSv1_2',
+  'ssl_ca_file' => '/etc/designate/ssl/mysql/ca-cert.pem',
+}
+
+oslo_messaging_default = {
+  'transport_url' => 'rabbit://openstack:password@127.0.0.1:5672//openstack'
+}
+
+oslo_messaging_rabbit = {}
+
+service_sink = {
+  'enabled_notification_handlers' => 'neutron_floatingip, nova_fixed'
+}
+
+handler_nova_fixed = {
+  'zone_id'  => '5186883b-91fb-4891-bd49-e6769234a8fc',
+  'formatv4' => "'%(hostname)s.%(zone)s'",
+  'formatv6' => "'%(hostname)s.%(zone)s'",
+}
+
+handler_neutron_floatingip = {
+  'zone_id'  => '5186883b-91fb-4891-bd49-e6769234a8fc',
+  'formatv4' => "'%(octet0)s-%(octet1)s-%(octet2)s-%(octet3)s.%(zone)s'",
+}
+
+control 'Designate' do
+
+  describe parse_config_file('/etc/designate/designate.conf') do
+
+    describe 'Designate messaging' do
+
+      if ssl_enabled
+        oslo_messaging_default.merge!(oslo_messaging_default_ssl)
+        oslo_messaging_rabbit.merge!(oslo_messaging_rabbit_ssl)
+        describe 'SSL' do
+          its('DEFAULT') {
+            should include(oslo_messaging_default)
+          }
+          its('oslo_messaging_rabbit') {
+            should include(oslo_messaging_rabbit)
+          }
+        end
+      else
+        describe 'non SSL' do
+          its('DEFAULT') do
+            should include(oslo_messaging_default)
+          end
+        end
+      end
+
+    end
+
+    describe 'Designate notification handlers' do
+
+      its('service:sink') do
+        should include(service_sink)
+      end
+
+      its('handler:nova_fixed') do
+        should include(handler_nova_fixed)
+      end
+
+      its('handler:neutron_floatingip') do
+        should include(handler_neutron_floatingip)
+      end
+
+    end
+  end
+end
\ No newline at end of file
diff --git a/tests/pillar/repo_mcp_openstack_rocky.sls b/tests/pillar/repo_mcp_openstack_rocky.sls
new file mode 100644
index 0000000..cb1c5b1
--- /dev/null
+++ b/tests/pillar/repo_mcp_openstack_rocky.sls
@@ -0,0 +1,12 @@
+linux:
+  system:
+    enabled: true
+    repo:
+      mirantis_openstack_repo:
+        source: "deb http://mirror.mirantis.com/nightly/openstack-rocky/{{ grains.get('oscodename') }} {{ grains.get('oscodename') }} main"
+        architectures: amd64
+        key_url: "http://mirror.mirantis.com/nightly/openstack-rocky/{{ grains.get('oscodename') }}/archive-openstack-rocky.key"
+        pin:
+        - pin: 'release l=rocky'
+          priority: 1050
+          package: '*'