Exemple #1
0
 def test_fully_qualified_env(self, mock_create_aws):
     """Does {{ENV_FULL}} resolve correctly"""
     mock_create_aws.return_value = self._clients
     # alpha0
     test_string = "{{ENV_FULL}}"
     resolver = EFTemplateResolver(profile=get_account_alias("alpha0"),
                                   env="alpha0",
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), "alpha0")
     # prod
     resolver = EFTemplateResolver(profile=get_account_alias("test"),
                                   env="test",
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), "test")
     # mgmt.testaccount
     resolver = EFTemplateResolver(
         profile=get_account_alias("mgmt.testaccount"),
         env="mgmt.testaccount",
         region=TEST_REGION,
         service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), "mgmt.testaccount")
Exemple #2
0
 def test_fully_qualified_env(self):
     """Does {{ENV_FULL}} resolve correctly"""
     # proto0
     test_string = "{{ENV_FULL}}"
     resolver = EFTemplateResolver(profile=get_account_alias("proto0"),
                                   env="proto0",
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), "proto0")
     # prod
     resolver = EFTemplateResolver(profile=get_account_alias("prod"),
                                   env="prod",
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), "prod")
     # mgmt.ellationeng
     resolver = EFTemplateResolver(
         profile=get_account_alias("mgmt.ellationeng"),
         env="mgmt.ellationeng",
         region=TEST_REGION,
         service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), "mgmt.ellationeng")
Exemple #3
0
def resolve_policy_document(policy_name):
  policy_filename = "{}{}.json".format(CONTEXT.policy_template_path, policy_name)
  print_if_verbose("Load policy: {} from file: {}".format(policy_name, policy_filename))
  # retrieve policy template
  try:
    policy_file = file(policy_filename, 'r')
    policy_template = policy_file.read()
    policy_file.close()
  except:
    fail("error opening policy file: {}".format(policy_filename))
  print_if_verbose("pre-resolution policy template:\n{}".format(policy_template))
  # If running in EC2, do not set profile and set target_other=True
  if CONTEXT.whereami == "ec2":
    resolver = EFTemplateResolver(target_other=True, env=CONTEXT.env, region=EFConfig.DEFAULT_REGION,
                                  service=CONTEXT.service, verbose=CONTEXT.verbose)
  else:
    resolver = EFTemplateResolver(profile=CONTEXT.account_alias, env=CONTEXT.env, region=EFConfig.DEFAULT_REGION,
                                service=CONTEXT.service, verbose=CONTEXT.verbose)
  resolver.load(policy_template)
  policy_document = resolver.render()
  print_if_verbose("resolved policy document:\n{}".format(policy_document))
  if not resolver.resolved_ok():
    fail("policy template {} has unresolved symbols or extra {{ or }}: {}".format(
      policy_filename, resolver.unresolved_symbols()))
  return policy_document
Exemple #4
0
def merge_files(context):
    """
  Given a context containing path to template, env, and service:
  merge config into template and output the result to stdout
  Args:
    context: a populated context object
  """
    resolver = EFTemplateResolver(profile=context.profile,
                                  region=context.region,
                                  env=context.env,
                                  service=context.service)

    try:
        with open(context.template_path, 'r') as f:
            template_body = f.read()
            f.close()
    except IOError as error:
        raise IOError("Error loading template file: {} {}".format(
            context.template_path, repr(error)))

    try:
        with open(context.param_path, 'r') as f:
            param_body = f.read()
            f.close()
    except IOError as error:
        raise IOError("Error loading param file: {} {}".format(
            context.param_path, repr(error)))

    dest = json.loads(param_body)["dest"]

    # if 'dest' for the current object contains an 'environments' list, check it
    if dest.has_key("environments"):
        if not resolver.resolved["ENV_SHORT"] in dest["environments"]:
            print("Environment: {} not enabled for {}".format(
                resolver.resolved["ENV_SHORT"], context.template_path))
            return

    # Process the template_body - apply context + parameters
    resolver.load(template_body, param_body)
    rendered_body = resolver.render()

    if not resolver.resolved_ok():
        raise RuntimeError(
            "Couldn't resolve all symbols; template has leftover {{ or }}: {}".
            format(resolver.unresolved_symbols()))

    if context.verbose:
        print(context)
        dir_path = normpath(dirname(dest["path"]))
        print("make directories: {} {}".format(dir_path, dest["dir_perm"]))
        print("chmod file to: " + dest["file_perm"])
        user, group = dest["user_group"].split(":")
        print("chown last directory in path to user: {}, group: {}".format(
            user, group))
        print("chown file to user: {}, group: {}\n".format(user, group))

        print("template body:\n{}\nrendered body:\n{}\n".format(
            template_body, rendered_body))
    else:
        print(rendered_body)
Exemple #5
0
def resolve_template(template, profile, env, region, service, verbose):
    # resolve {{SYMBOLS}} in the passed template file
    isfile(template) or fail("Not a file: {}".format(template))
    resolver = EFTemplateResolver(profile=profile,
                                  target_other=True,
                                  env=env,
                                  region=region,
                                  service=service,
                                  verbose=verbose)
    with open(template) as template_file:
        resolver.load(template_file)
        resolver.render()

    if verbose:
        print(resolver.template)

    dangling_left, dangling_right = resolver.count_braces()
    if resolver.unresolved_symbols():
        fail("Unable to resolve symbols: " +
             ",".join(["{{" + s + "}}"
                       for s in resolver.unresolved_symbols()]))
    elif dangling_left > 0 or dangling_right > 0:
        fail("Some {{ or }} were not resolved. left{{: {}, right}}: {}".format(
            dangling_left, dangling_right))
    else:
        return resolver.template
Exemple #6
0
 def test_embedded_symbols(self):
     """Does a symbol built from other symbols resolve correctly"""
     test_string = "{{{{o}}{{ne}}}}"
     resolver = EFTemplateResolver(profile=TEST_PROFILE,
                                   env=TEST_ENV,
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), "testenv one")
Exemple #7
0
 def test_context_vars_protected(self):
     """Context vars like {{ENV}} are not overridden even if present in template"""
     test_string = "{{ENV}}"
     resolver = EFTemplateResolver(profile=TEST_PROFILE,
                                   env=TEST_ENV,
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), TEST_ENV)
Exemple #8
0
 def test_unresolved_symbols(self):
     """Are unresolved symbols stored and reported, and non-symbols ignored"""
     test_string = "{{cannot_resolve}}{{not a symbo}}{{notasymbol?}}{{cannot_resolve}}"
     resolver = EFTemplateResolver(profile=TEST_PROFILE,
                                   env=TEST_ENV,
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.unresolved_symbols(),
                      set(["cannot_resolve"]))
Exemple #9
0
 def test_newline_literal(self, mock_create_aws):
     """Do newline literals get converted to newlines"""
     mock_create_aws.return_value = self._clients
     test_string = "foo\nbar"
     resolver = EFTemplateResolver(profile=TEST_PROFILE,
                                   env=TEST_ENV,
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), "foo\nbar")
Exemple #10
0
 def test_hierarchical_overlays(self):
     """Is the hierarchy of default..env applied correctly"""
     test_string = "{{one}}|{{two}}|{{my-thing}}"
     resolver = EFTemplateResolver(profile=TEST_PROFILE,
                                   env=TEST_ENV,
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(),
                      "testenv one|testenv two|my-hyphen-thing")
Exemple #11
0
 def test_leading_dot_context(self, mock_create_aws):
     """Do context symbols with a leading dot render correctly"""
     mock_create_aws.return_value = self._clients
     test_string = "{{.ENV}}"
     resolver = EFTemplateResolver(profile=TEST_PROFILE,
                                   env=TEST_ENV,
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(resolver.render(), TEST_ENV)
Exemple #12
0
 def test_newline_literal_against_raw(self, mock_create_aws):
     """Another check to make sure newline literals are not mistakenly written as r'\n'"""
     mock_create_aws.return_value = self._clients
     test_string = "foo\nbar"
     resolver = EFTemplateResolver(profile=TEST_PROFILE,
                                   env=TEST_ENV,
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertNotEqual(resolver.render(), r'foo\nbar')
Exemple #13
0
 def test_resolution(self):
     """Do context symbols resolve correctly"""
     test_string = "{{one}}|{{two}}|{{/_-.}}|{{ENV}}"
     resolver = EFTemplateResolver(profile=TEST_PROFILE,
                                   env=TEST_ENV,
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     resolver.load(test_string, PARAMS)
     self.assertEqual(
         resolver.render(),
         "testenv one|testenv two|slashunderscoredashdot|proto0")
Exemple #14
0
 def test_render_multiline_string_from_list(self, mock_create_aws):
     """Does {{multi}} resolve correctly as a multiline string from yaml parameters file"""
     mock_create_aws.return_value = self._clients
     test_string = "{{multi2}}"
     resolver = EFTemplateResolver(profile=get_account_alias("test"),
                                   env="test",
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     with open(self.test_params_json) as json_file:
         resolver.load(test_string, json_file)
     self.assertEqual(resolver.render(), "one\ntwo\nthree")
Exemple #15
0
 def test_load_yaml_file(self, mock_create_aws):
     """Does {{one}} resolve correctly from yaml parameters file"""
     mock_create_aws.return_value = self._clients
     test_string = "{{one}}"
     resolver = EFTemplateResolver(profile=get_account_alias("alpha0"),
                                   env="alpha0",
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     with open(self.test_params_yaml) as yaml_file:
         resolver.load(test_string, yaml_file)
     self.assertEqual(resolver.render(), "alpha one")
Exemple #16
0
 def test_render_multiline_string(self, mock_create_aws):
     """Does {{multi}} resolve correctly as a multiline string from yaml parameters file"""
     mock_create_aws.return_value = self._clients
     test_string = "{{multi}}"
     resolver = EFTemplateResolver(profile=get_account_alias("test"),
                                   env="test",
                                   region=TEST_REGION,
                                   service=TEST_SERVICE)
     with open(self.test_params_yaml) as yaml_file:
         resolver.load(test_string, yaml_file)
     self.assertEqual(
         resolver.render(),
         "thisisareallylongstringthatcoversmultiple\nlinesfortestingmultilinestrings"
     )
Exemple #17
0
def merge_files(service, skip_on_user_group_error=False):
    """
  Given a prefix, find all templates below; merge with parameters; write to "dest"
  Args:
    service: "<service>", "all", or "ssh"
    skip_on_user_group_error: True or False

  For S3, full path becomes:
    s3://ellation-cx-global-configs/<service>/templates/<filename>
    s3://ellation-cx-global-configs/<service>/parameters/<filename>.parameters.<yaml|yml|json>
  For filesystem, full path becomes:
    /vagrant/configs/<service>/templates/<filename>
    /vagrant/configs/<service>/parameters/<filename>.parameters.<yaml|yml|json>
  """
    if WHERE == "ec2":
        config_reader = EFInstanceinitConfigReader("s3", service, log_info,
                                                   RESOURCES["s3"])
        resolver = EFTemplateResolver()
    elif WHERE == "virtualbox-kvm":
        config_path = "{}/{}".format(VIRTUALBOX_CONFIG_ROOT, service)
        config_reader = EFInstanceinitConfigReader("file", config_path,
                                                   log_info)
        environment = EFConfig.VAGRANT_ENV
        resolver = EFTemplateResolver(env=environment,
                                      profile=get_account_alias(environment),
                                      region=EFConfig.DEFAULT_REGION,
                                      service=service)

    while config_reader.next():
        log_info("checking: {}".format(config_reader.current_key))

        # if 'dest' for the current object contains an 'environments' list, check it
        dest = config_reader.dest
        if "environments" in dest:
            if not resolver.resolved["ENV_SHORT"] in dest["environments"]:
                log_info("Environment: {} not enabled for {}".format(
                    resolver.resolved["ENV_SHORT"], config_reader.current_key))
                continue

        # If 'dest' for the current object contains a user_group that hasn't been created in the environment yet and the
        # flag is set to True to skip, log the error and move onto the next config file without blowing up.
        if skip_on_user_group_error:
            user, group = get_user_group(dest)
            try:
                getpwnam(user).pw_uid
            except KeyError:
                log_info(
                    "File specifies user {} that doesn't exist in environment. Skipping config file."
                    .format(user))
                continue
            try:
                getgrnam(group).gr_gid
            except KeyError:
                log_info(
                    "File specifies group {} that doesn't exist in environment. Skipping config file."
                    .format(group))
                continue

        # Process the template_body - apply context + parameters
        log_info("Resolving template")
        resolver.load(config_reader.template, config_reader.parameters)
        rendered_body = resolver.render()
        if not resolver.resolved_ok():
            critical(
                "Couldn't resolve all symbols; template has leftover {{ or }}: {}"
                .format(resolver.unresolved_symbols()))

        # Write the rendered file
        dir_path = normpath(dirname(dest["path"]))
        # Resolved OK. try to write the template
        log_info("make directories: {} {}".format(dir_path, dest["dir_perm"]))
        try:
            makedirs(dir_path, int(dest["dir_perm"], 8))
        except OSError as error:
            if error.errno != 17:
                critical("Error making directories {}".format(repr(error)))
        log_info("open: " + dest["path"] + ",w+")
        try:
            outfile = open(dest["path"], 'w+')
            log_info("write")
            outfile.write(rendered_body)
            log_info("close")
            outfile.close()
            log_info("chmod file to: " + dest["file_perm"])
            chmod(dest["path"], int(dest["file_perm"], 8))
            user, group = get_user_group(dest)
            uid = getpwnam(user).pw_uid
            gid = getgrnam(group).gr_gid
            log_info("chown last directory in path to: " + dest["user_group"])
            chown(dir_path, uid, gid)
            log_info("chown file to: " + dest["user_group"])
            chown(dest["path"], uid, gid)
        except Exception as error:
            critical("Error writing file: " + dest["path"] + ": " +
                     repr(error))
WAF Web ACL ID: {{aws:waf:web-acl-id,staging-StaticAcl}}\n\
SSL Certificate ARN us-west-2/cx-proto3.com: {{aws:acm:certificate-arn,us-west-2/cx-proto3.com}}\n\
Elastic network interface (ENI) eni-proto0-dnsproxy-1a: {{aws:ec2:eni/eni-id,eni-proto0-dnsproxy-1a}}\n\
Elastic IP Allocation ID: {{aws:ec2:elasticip/elasticip-id,ElasticIpMgmtCingest1}}\n\
Elastic IP IP Address: {{aws:ec2:elasticip/elasticip-ipaddress,ElasticIpMgmtCingest1}}\n\
EFConfig resolver, accountaliasofenv,prod: {{efconfig:accountaliasofenv,staging}}\n\
AMI lookup: {{version:ami-id,proto0/test-instance}}\n\
Latest AMI for test-instance: {{version:ami-id,proto0/test-instance}}\n\
Custom Data: \"{{efconfig:customdata,office_ips}}\"\
"

GLOBAL_ENV_TEST_STRING = "fully-qualified environment:{{ENV_FULL}}\n"

# Test with proto0
if LOCAL:
  resolver = EFTemplateResolver(profile=get_account_alias("proto0"), env="proto0", region="us-west-2",
                                service="mine", verbose=True)
else:
  resolver = EFTemplateResolver(verbose=True)

resolver.load(TEST_STRING, PARAMS)
resolver.render()

print(resolver.template)
print("unresolved symbol count: "+str(len(resolver.unresolved_symbols())))
print("unresolved symbols: "+repr(resolver.unresolved_symbols()))
print("all template symbols: "+repr(resolver.symbols))
print("all EFTemplateResolver symbols: "+repr(resolver.resolved))


# Demo with the global env 'mgmt.ellationeng' (local only)
if LOCAL:
def merge_files(context):
    """
  Given a context containing path to template, env, and service:
  merge config into template and output the result to stdout
  Args:
    context: a populated context object
  """
    resolver = EFTemplateResolver(profile=context.profile,
                                  region=context.region,
                                  env=context.env,
                                  service=context.service)

    try:
        with open(context.template_path, 'r') as f:
            template_body = f.read()
            f.close()
    except IOError as error:
        raise IOError("Error loading template file: {} {}".format(
            context.template_path, repr(error)))

    if context.no_params is False:
        try:
            with open(context.param_path, 'r') as f:
                param_body = f.read()
                f.close()
        except IOError as error:
            raise IOError("Error loading param file: {} {}".format(
                context.param_path, repr(error)))

        dest = yaml.safe_load(param_body)["dest"]

        # if 'dest' for the current object contains an 'environments' list, check it
        if "environments" in dest:
            if not resolver.resolved["ENV_SHORT"] in dest["environments"]:
                print("Environment: {} not enabled for {}".format(
                    resolver.resolved["ENV_SHORT"], context.template_path))
                return

        # Process the template_body - apply context + parameters
        resolver.load(template_body, param_body)
    else:
        resolver.load(template_body)
    rendered_body = resolver.render()

    if not resolver.resolved_ok():
        raise RuntimeError(
            "Couldn't resolve all symbols; template has leftover {{ or }}: {}".
            format(resolver.unresolved_symbols()))

    if context.lint:
        if context.template_path.endswith(".json"):
            try:
                json.loads(rendered_body, strict=False)
                print("JSON passed linting process.")
            except ValueError as e:
                fail("JSON failed linting process.", e)
        elif context.template_path.endswith((".yml", ".yaml")):
            conf = yamllint_config.YamlLintConfig(content='extends: relaxed')
            lint_output = yamllinter.run(rendered_body, conf)
            lint_level = 'error'
            lint_errors = [
                issue for issue in lint_output if issue.level == lint_level
            ]
            if lint_errors:
                split_body = rendered_body.splitlines()
                for error in lint_errors:
                    print(error)
                    # printing line - 1 because lists start at 0, but files at 1
                    print("\t", split_body[error.line - 1])
                fail("YAML failed linting process.")

    if context.verbose:
        print(context)
        if context.no_params:
            print('no_params flag set to true!')
            print(
                'Inline template resolution based on external symbol lookup only and no destination for file write.\n'
            )
        else:
            dir_path = normpath(dirname(dest["path"]))
            print("make directories: {} {}".format(dir_path, dest["dir_perm"]))
            print("chmod file to: " + dest["file_perm"])
            user, group = dest["user_group"].split(":")
            print("chown last directory in path to user: {}, group: {}".format(
                user, group))
            print("chown file to user: {}, group: {}\n".format(user, group))

        print("template body:\n{}\nrendered body:\n{}\n".format(
            template_body, rendered_body))
    elif context.silent:
        print("Config template rendered successfully.")
    else:
        print(rendered_body)
Exemple #20
0
def merge_files(service):
    """
  Given a prefix, find all templates below; merge with parameters; write to "dest"
  Args:
    service: "<service>" or "all"

  For S3, full path becomes:
    s3://ellation-cx-global-configs/<service>/templates/<filename>
    s3://ellation-cx-global-configs/<service>/parameters/<filename>.parameters.json
  For filesystem, full path becomes:
    /vagrant/configs/<service>/templates/<filename>
    /vagrant/configs/<service>/parameters/<filename>.parameters.json
  """
    if WHERE == "ec2":
        config_reader = EFInstanceinitConfigReader("s3", service, log_info,
                                                   RESOURCES["s3"])
    elif WHERE == "virtualbox-kvm":
        config_path = "{}/{}".format(VIRTUALBOX_CONFIG_ROOT, service)
        config_reader = EFInstanceinitConfigReader("file", config_path,
                                                   log_info)

    while config_reader.next():
        # Make a new TemplateResolver for every file::parameters pair, so cached keys don't carry over
        if WHERE == "ec2":
            resolver = EFTemplateResolver()
        elif WHERE == "virtualbox-kvm":
            resolver = EFTemplateResolver(env="localvm", service=service)

        log_info("checking: {}".format(config_reader.current_key))

        # if 'dest' for the current object contains an 'environments' list, check it
        dest = config_reader.dest
        if dest.has_key("environments"):
            if not resolver.resolved["ENV_SHORT"] in dest["environments"]:
                log_info("Environment: {} not enabled for {}".format(
                    resolver.resolved["ENV_SHORT"], config_reader.current_key))
                continue

        # Process the template_body - apply context + parameters
        log_info("Resolving template")
        resolver.load(config_reader.template, config_reader.parameters)
        rendered_body = resolver.render()
        if not resolver.resolved_ok():
            critical(
                "Couldn't resolve all symbols; template has leftover {{ or }}: {}"
                .format(resolver.unresolved_symbols()))

        # Write the rendered file
        dir_path = normpath(dirname(dest["path"]))
        # Resolved OK. try to write the template
        log_info("make directories: {} {}".format(dir_path, dest["dir_perm"]))
        try:
            makedirs(dir_path, int(dest["dir_perm"], 8))
        except OSError as error:
            if error.errno != 17:
                critical("Error making directories {}".format(repr(error)))
        log_info("open: " + dest["path"] + ",w+")
        try:
            outfile = open(dest["path"], 'w+')
            log_info("write")
            outfile.write(rendered_body)
            log_info("close")
            outfile.close()
            log_info("chmod file to: " + dest["file_perm"])
            chmod(dest["path"], int(dest["file_perm"], 8))
            user, group = dest["user_group"].split(":")
            uid = getpwnam(user).pw_uid
            gid = getgrnam(group).gr_gid
            log_info("chown last directory in path to: " + dest["user_group"])
            chown(dir_path, uid, gid)
            log_info("chown file to: " + dest["user_group"])
            chown(dest["path"], uid, gid)
        except Exception as error:
            critical("Error writing file: " + dest["path"] + ": " +
                     repr(error))