Repack binaries based on the configuration.

    We repack all templates in the templates directory. We expect to find only
    functioning templates, all other files should be removed. Each template
    contains a build.yaml that specifies how it was built and how it should be
    repacked.

    Args:
      template_path: template path string
      output_dir: Output files will be put in this directory.
      upload: If specified we also upload the repacked binary into the
      token: Token to use when uploading to the datastore.
      sign: If true, we want to digitally sign the installer.
      context: Array of context strings
      signed_template: If true, the libraries in the template are already
        signed. This is only used for windows when repacking the template
        multiple times.

    Returns:
      A list of output installers generated.

def RepackTemplate(self,
                     template_path,
                     output_dir,
                     upload=False,
                     token=None,
                     sign=False,
                     context=None,
                     signed_template=False):
    """Repack binaries based on the configuration.

    We repack all templates in the templates directory. We expect to find only
    functioning templates, all other files should be removed. Each template
    contains a build.yaml that specifies how it was built and how it should be
    repacked.

    Args:
      template_path: template path string
      output_dir: Output files will be put in this directory.
      upload: If specified we also upload the repacked binary into the
      token: Token to use when uploading to the datastore.
      sign: If true, we want to digitally sign the installer.
      context: Array of context strings
      signed_template: If true, the libraries in the template are already
        signed. This is only used for windows when repacking the template
        multiple times.

    Returns:
      A list of output installers generated.
    """
    orig_config = config.CONFIG
    repack_config = RepackConfig()
    print("Repacking template: %s" % template_path)
    config.CONFIG = repack_config.GetConfigFromTemplate(template_path)

    result_path = None
    try:
      repack_context = config.CONFIG["Template.build_context"]
      if context:
        repack_context.extend(context)

      output_path = os.path.join(
          output_dir,
          config.CONFIG.Get(
              "ClientRepacker.output_filename", context=repack_context))

      print("Using context: %s and labels: %s" %
            (repack_context,
             config.CONFIG.Get("Client.labels", context=repack_context)))
      try:
        signer = None
        if sign:
          signer = self.GetSigner(repack_context)
        builder_obj = self.GetRepacker(context=repack_context, signer=signer)
        builder_obj.signed_template = signed_template
        result_path = builder_obj.MakeDeployableBinary(template_path,
                                                       output_path)
      except Exception:  # pylint: disable=broad-except
        logging.exception("Repacking template %s failed:", template_path)

      if result_path:
        print("Repacked into %s" % result_path)
        if upload:
          # We delay import here so we don't have to import the entire server
          # codebase and do full server init if we're just building and
          # repacking clients. This codepath is used by config_updater
          # initialize
          # pylint: disable=g-import-not-at-top
          from grr_response_server import maintenance_utils
          # pylint: enable=g-import-not-at-top
          client_platform = config.CONFIG.Get(
              "Client.platform", context=repack_context)
          repack_basename = config.CONFIG.Get(
              "ClientRepacker.output_basename", context=repack_context)
          repack_extension = config.CONFIG.Get(
              "ClientBuilder.output_extension", context=repack_context)
          repack_filename = repack_basename + repack_extension
          # TODO(user): Use signed_binary_utils.GetAFF4ExecutablesRoot()
          # here instead of hardcoding the root once repacking logic has been
          # moved to grr-response-server.
          binary_urn = rdfvalue.RDFURN("aff4:/config/executables").Add(
              client_platform).Add("installers").Add(repack_filename)
          maintenance_utils.UploadSignedConfigBlob(
              open(result_path, "rb").read(100 * 1024 * 1024),
              binary_urn,
              client_context=repack_context,
              token=token)
      else:
        print("Failed to repack %s." % template_path)
    finally:
      config.CONFIG = orig_config

    return result_path