text: import logging
  import os
  import traceback
  import jinja2
  import string
  
  import oyaml as yaml
  from Crypto.PublicKey import RSA
  from stat import *
  from collections import OrderedDict
  import filters as jinja_filters
  
  
  def render_template(template_name, template_path, target, context, delete_template=True, overwrite=False):
      """
      Helper function to write out DRY up templating. Accepts template name (string),
      path (string), target directory (string), context (dictionary) and delete_template (boolean)
      Default behavior is to use the key of the dictionary as the template variable names, replace
      them with the value in the tempalate and delete the template if delete_template is
      True
      """
  
      logging.info("Writing {}".format(target))
      logging.debug("Template Context: {}".format(context))
      logging.debug("Overwrite is {}".format(overwrite))
      if os.path.isfile(target) and overwrite is not True:
          logging.warn("Cowardly refusing to overwrite existing file {}".format(target))
          return False
  
      logging.debug("Attempting to write {} from template {}/{}".format(target, template_path, template_name))
  
      template_path = os.path.normpath(template_path)
      template_name = os.path.normpath(template_name)
      template_permissions = os.stat(template_path + '/' + template_name).st_mode
  
      with open(target, 'w+') as vars_file:
          try:
              env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_path))
              for k,v in jinja_filters.get_jinja_filters().items():
                  env.filters[k] = v
  
              template = env.get_template(template_name)
              vars_file.write(template.render(context))
          except Exception, e:
              logging.error("Error writing {}. {}".format(target, traceback.print_exc(e)))
              return False
  
      os.chmod(target, template_permissions)
  
      if delete_template:
          logging.debug("Removing {}/{}".format(template_path, template_name))
          os.remove("{}/{}".format(template_path, template_name))
  
  
  def write_yaml_file(filename, d, overwrite=False):
      """ Accepts  filepath,  dictionary. Writes dictionary in yaml to file path, recursively creating path if necessary """
      if not os.path.exists(os.path.dirname(filename)) and overwrite is False:
          try:
              os.makedirs(os.path.dirname(filename))
          except OSError as exc:
              if exc.errno != errno.EEXIST:
                  raise
      logging.debug("Writing yaml file {}".format(filename))
      logging.debug(d)
      with open(filename, 'w+') as f:
          yaml.safe_dump(d, f, default_flow_style=False)
  
  
  def create_rsa_key(name, path, bits=2048):
      """ creates an ssh key pair. Accepts name, path and bits. Name is the name of the key pair to generate at Path. Bits defaults to 2048 """
  
      key = RSA.generate(bits)
  
      private_key = "{}{}".format(path, name)
      public_key = "{}{}.pub".format(path, name)
  
      with open(private_key, 'w') as content_file:
          os.chmod(private_key, 0600)
          content_file.write(key.exportKey('PEM'))
  
      pubkey = key.publickey()
      with open(public_key, 'w') as content_file:
          content_file.write(pubkey.exportKey('OpenSSH'))
  
  
  def merge_dict(d, new_data, clobber=False):
      """ accepts new_data (dict) and clobbber (boolean). Merges dictionary with dictionary 'd'. If clobber is True, overwrites value. Defaults to false """
      for key, value in new_data.items():
          if d.get(key) is None or clobber:
              logging.debug("Setting component data {}: {}".format(key, value))
              d[key] = value
      return d
  
  
  def allege_aws_availability_zones(region, count):
      """
      Accepts a region (string) and count (int) and returns a list of potential aws availability zones
      It does no verification that the region is correct or that the az actually exists
      Ex: for region 'us-west-1' and count '3' it will return ['us-west-1a', 'us-west-1b', 'us-west-1c']
      """
      azs = []
      logging.info("Guessing at default AWS AZs")
      for i in range(0, count):
          azs += ["{}{}".format(region, list(string.ascii_lowercase)[i])]
  
      return (", ").join(azs)
  