]> Frank Brehm's Git Trees - pixelpark/create-terraform.git/commitdiff
Supporting DNS search domains and options by terraform VM definition.
authorFrank Brehm <frank.brehm@pixelpark.com>
Mon, 16 Dec 2019 17:02:42 +0000 (18:02 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Mon, 16 Dec 2019 17:02:42 +0000 (18:02 +0100)
lib/cr_tf/terraform/vm.py

index 083bb83191689af1d679bbaed416217f597f2b38..9b050f07ce0f706323daa024d6fa40e4445f1d8d 100644 (file)
@@ -37,7 +37,7 @@ from .disk import TerraformDisk, TerraformDiskDict
 
 from .interface import TerraformInterface
 
-__version__ = '1.4.5'
+__version__ = '1.5.1'
 
 LOG = logging.getLogger(__name__)
 
@@ -82,6 +82,8 @@ class TerraformVm(HandlingObject):
         ipaddress.ip_address('217.66.52.10'),
         ipaddress.ip_address('212.91.225.75')
     )
+    default_searchdomains = ('pixelpark.net', 'pixelpark.com')
+    default_dns_options = 'timeout:1 attempts:2'
     default_num_cpus = 1
     default_puppet_contact = '8x5@pixelpark.com'
     default_puppet_customer = 'pixelpark'
@@ -98,6 +100,9 @@ class TerraformVm(HandlingObject):
     min_rootdisk_size = CrTfConfiguration.default_root_min_size
     max_rootdisk_size = CrTfConfiguration.default_root_max_size
 
+    max_nameservers = 4
+    max_searchdomains = 5
+
     re_key_fqdn = re.compile(r'^\s*fqdn|name\s*$', re.IGNORECASE)
     re_key_vm_folder = re.compile(r'^\s*(?:vm[_-]?)folder\s*$', re.IGNORECASE)
     re_key_boot_delay = re.compile(r'^\s*boot[_-]?delay\s*$', re.IGNORECASE)
@@ -111,6 +116,8 @@ class TerraformVm(HandlingObject):
     re_key_puppet_role = re.compile(r'^\s*puppet[_-]?role\s*$', re.IGNORECASE)
     re_key_env = re.compile(r'^\s*env(?:ironment)?\s*$', re.IGNORECASE)
     re_key_ns = re.compile(r'^\s*nameservers?\s*$', re.IGNORECASE)
+    re_key_searchdomain = re.compile(r'^\s*search[_-]*domains?\s*$', re.IGNORECASE)
+    re_key_dnsoptions = re.compile(r'^\s*(dns|resolv)[_-]*options?*$', re.IGNORECASE)
     re_key_root_disk = re.compile(r'^\s*root[_-]?disk\s*$', re.IGNORECASE)
     re_key_root_disk_size = re.compile(r'^\s*root[_-]?disk[_-]?size\s*$', re.IGNORECASE)
     re_key_data_disk = re.compile(r'^\s*data[_-]?disk\s*$', re.IGNORECASE)
@@ -139,8 +146,8 @@ class TerraformVm(HandlingObject):
             cluster=None, boot_delay=None, ds_cluster=None, datastore=None, ds_type=None,
             customer=None, rootdisk_size=None, purpose=None, puppet_contact=None, puppet_role=None,
             puppet_customer=None, puppet_project=None, puppet_tier=None, puppet_env=None,
-            vm_template=None, nameservers=None, has_backup=True, has_puppet=True,
-            already_existing=None, vsphere=None):
+            vm_template=None, nameservers=None, searchdomains=None, dns_options=None,
+            has_backup=True, has_puppet=True, already_existing=None, vsphere=None):
 
         self._vsphere = self.default_vsphere
         self._is_template = bool(is_template)
@@ -172,6 +179,8 @@ class TerraformVm(HandlingObject):
         self.interfaces = []
 
         self.nameservers = copy.copy(self.default_nameservers)
+        self.searchdomains = copy.copy(self.default_searchdomains)
+        self.dns_options = copy.copy(self.default_dns_options)
 
         super(TerraformVm, self).__init__(
             appname=appname, verbose=verbose, version=version, base_dir=base_dir,
@@ -183,13 +192,16 @@ class TerraformVm(HandlingObject):
             name=name, fqdn=fqdn, num_cpus=num_cpus, memory=memory, folder=folder,
             boot_delay=boot_delay, vm_template=vm_template, puppet_contact=puppet_contact,
             puppet_customer=puppet_customer, puppet_tier=puppet_tier, puppet_env=puppet_env,
-            cluster=cluster, rootdisk_size=rootdisk_size, nameservers=nameservers, purpose=purpose,
+            cluster=cluster, rootdisk_size=rootdisk_size, nameservers=nameservers,
+            searchdomains=searchdomains, dns_options=dns_options, purpose=purpose,
             customer=customer, ds_cluster=ds_cluster, datastore=datastore, ds_type=ds_type,
             already_existing=already_existing, initialized=initialized, puppet_role=puppet_role,
             puppet_project=puppet_project, vsphere=vsphere)
 
     # -------------------------------------------------------------------------
-    def _post_init(self, name=None, fqdn=None, nameservers=None, initialized=False, **kwargs):
+    def _post_init(
+        self, name=None, fqdn=None, nameservers=None, searchdomains=None,
+            initialized=False, **kwargs):
 
         self.disks = TerraformDiskDict(
             appname=self.appname, verbose=self.verbose, base_dir=self.base_dir)
@@ -208,6 +220,8 @@ class TerraformVm(HandlingObject):
 
         if nameservers is not None:
             self.nameservers = self._get_ns_list(nameservers)
+        if searchdomains is not None:
+            self.searchdomains = self._get_searchdomain_list(searchdomains)
 
         if self.is_template:
             if self.fqdn:
@@ -315,6 +329,27 @@ class TerraformVm(HandlingObject):
                 LOG.error(_("Could not evaluate nameservers from {!r}.").format(value))
             return
 
+        if cls.re_key_searchdomain.search(key):
+            if isinstance(value, Iterable):
+                domains = cls._get_searchdomain_list(value)
+                if domains:
+                    vm.searchdomains = domains
+            elif value is None:
+                vm.searchdomains = []
+            else:
+                LOG.error(_("Could not evaluate search domains from {!r}.").format(value))
+            return
+
+        if cls.re_key_dnsoptions.search(key):
+            if value is None:
+                vm.dns_options = None
+            else:
+                val = value.strip().lower()
+                if val:
+                    vm.dns_options = val
+                else:
+                    vm.dns_options = None
+
         if cls.re_key_interface.search(key):
             if vm.is_template:
                 LOG.error(_("Template definitions may not have interface definitions."))
@@ -571,6 +606,7 @@ class TerraformVm(HandlingObject):
             vm_template=self.vm_template, puppet_contact=self.puppet_contact,
             puppet_customer=self.puppet_customer, puppet_tier=self.puppet_tier,
             puppet_env=self.puppet_env, puppet_role=self.puppet_role, nameservers=self.nameservers,
+            searchdomains=self.searchdomains, dns_options=self.dns_options,
             rootdisk_size=self.rootdisk_size, has_backup=self.has_backup,
             has_puppet=self.has_puppet, puppet_project=self.puppet_project,
             vsphere=self.vsphere,
@@ -589,17 +625,19 @@ class TerraformVm(HandlingObject):
     def _get_ns_list(cls, nameservers):
 
         if not isinstance(nameservers, Iterable):
-            raise ValueError(_("Parameter nameservers {!r} is not iterable.").format(nameservers))
+            raise ValueError(_("Parameter {p} {ns!r} is not iterable.").format(
+                p='nameservers', ns=nameservers))
 
         ns = []
         i = 1
         for val in nameservers:
             try:
                 address = ipaddress.ip_address(val)
-                if i > 3:
+                if i > cls.max_nameservers:
                     LOG.warn(_(
-                        "There are at most three nameservers accepted, {} "
-                        "will not be considered.").format(address))
+                        "There are at most {mx} nameservers accepted, {addr} "
+                        "will not be considered.").format(
+                        mx=cls.max_nameservers, addr=address))
                 elif address not in ns:
                     ns.append(address)
                     i += 1
@@ -609,6 +647,28 @@ class TerraformVm(HandlingObject):
 
         return ns
 
+    # -------------------------------------------------------------------------
+    @classmethod
+    def _get_searchdomain_list(cls, searchdomains):
+
+        if not isinstance(searchdomains, Iterable):
+            raise ValueError(_("Parameter {p} {ns!r} is not iterable.").format(
+                p='searchdomains', ns=searchdomains))
+
+        domains = []
+        i = 1
+        for dom in searchdomains:
+            if i > cls.max_searchdomains:
+                LOG.warn(_(
+                    "There are at most {mx} search domains accepted, {srv} "
+                    "will not be considered.").format(
+                    mx=cls.max_searchdomains, srv=dom))
+            elif dom not in domains:
+                domains.append(dom)
+                i += 1
+
+        return domains
+
     # -----------------------------------------------------------
     @property
     def is_template(self):