示例#1
0
    def test_multi_step_deployment(self):
        msd = MultiStepDeployment()
        self.assertEqual(len(msd.steps), 0)

        msd.add(MockDeployment())
        self.assertEqual(len(msd.steps), 1)

        self.assertEqual(self.node, msd.run(node=self.node, client=None))
示例#2
0
    def test_multi_step_deployment(self):
        msd = MultiStepDeployment()
        self.assertEqual(len(msd.steps), 0)

        msd.add(MockDeployment())
        self.assertEqual(len(msd.steps), 1)

        self.assertEqual(self.node, msd.run(node=self.node, client=None))
示例#3
0
    def deploy_node(self, **kwargs):
        """
        Create a new node, and start deployment.

        @keyword    enable_root: If true, root password will be set to
                                 vnc_password (this will enable SSH access)
                                 and default 'toor' account will be deleted.
        @type       enable_root: C{bool}

        For detailed description and keywords args, see
        L{NodeDriver.deploy_node}.
        """
        image = kwargs['image']
        vnc_password = kwargs.get('vnc_password', None)
        enable_root = kwargs.get('enable_root', False)

        if not vnc_password:
            raise ValueError('You need to provide vnc_password argument '
                             'if you want to use deployment')

        if (image in STANDARD_DRIVES
            and STANDARD_DRIVES[image]['supports_deployment']):
            raise ValueError('Image %s does not support deployment'
                             % (image.id))

        if enable_root:
            script = ("unset HISTFILE;"
                      "echo root:%s | chpasswd;"
                      "sed -i '/^toor.*$/d' /etc/passwd /etc/shadow;"
                      "history -c") % vnc_password
            root_enable_script = ScriptDeployment(script=script,
                                                  delete=True)
            deploy = kwargs.get('deploy', None)
            if deploy:
                if (isinstance(deploy, ScriptDeployment)
                    or isinstance(deploy, SSHKeyDeployment)):
                    deployment = MultiStepDeployment([deploy,
                                                      root_enable_script])
                elif isinstance(deploy, MultiStepDeployment):
                    deployment = deploy
                    deployment.add(root_enable_script)
            else:
                deployment = root_enable_script

            kwargs['deploy'] = deployment

        if not kwargs.get('ssh_username', None):
            kwargs['ssh_username'] = '******'

        return super(ElasticHostsBaseNodeDriver, self).deploy_node(**kwargs)
示例#4
0
    def deploy_node(self, **kwargs):
        """
        Create a new node, and start deployment.

        @keyword    enable_root: If true, root password will be set to
                                 vnc_password (this will enable SSH access)
                                 and default 'toor' account will be deleted.
        @type       enable_root: C{bool}

        For detailed description and keywords args, see
        L{NodeDriver.deploy_node}.
        """
        image = kwargs['image']
        vnc_password = kwargs.get('vnc_password', None)
        enable_root = kwargs.get('enable_root', False)

        if not vnc_password:
            raise ValueError('You need to provide vnc_password argument '
                             'if you want to use deployment')

        if (image in self._standard_drives
            and not self._standard_drives[image]['supports_deployment']):
            raise ValueError('Image %s does not support deployment'
                             % (image.id))

        if enable_root:
            script = ("unset HISTFILE;"
                      "echo root:%s | chpasswd;"
                      "sed -i '/^toor.*$/d' /etc/passwd /etc/shadow;"
                      "history -c") % vnc_password
            root_enable_script = ScriptDeployment(script=script,
                                                  delete=True)
            deploy = kwargs.get('deploy', None)
            if deploy:
                if (isinstance(deploy, ScriptDeployment)
                    or isinstance(deploy, SSHKeyDeployment)):
                    deployment = MultiStepDeployment([deploy,
                                                      root_enable_script])
                elif isinstance(deploy, MultiStepDeployment):
                    deployment = deploy
                    deployment.add(root_enable_script)
            else:
                deployment = root_enable_script

            kwargs['deploy'] = deployment

        if not kwargs.get('ssh_username', None):
            kwargs['ssh_username'] = '******'

        return super(ElasticStackBaseNodeDriver, self).deploy_node(**kwargs)
示例#5
0
    def deploy_node(self, **kwargs):
        """
        Create a new node, and start deployment.

        @inherits: :class:`NodeDriver.deploy_node`

        :keyword    enable_root: If true, root password will be set to
                                 vnc_password (this will enable SSH access)
                                 and default 'toor' account will be deleted.
        :type       enable_root: ``bool``
        """
        image = kwargs["image"]
        vnc_password = kwargs.get("vnc_password", None)
        enable_root = kwargs.get("enable_root", False)

        if not vnc_password:
            raise ValueError("You need to provide vnc_password argument "
                             "if you want to use deployment")

        if (image in self._standard_drives
                and not self._standard_drives[image]["supports_deployment"]):
            raise ValueError("Image %s does not support deployment" %
                             (image.id))

        if enable_root:
            script = ("unset HISTFILE;"
                      "echo root:%s | chpasswd;"
                      "sed -i '/^toor.*$/d' /etc/passwd /etc/shadow;"
                      "history -c") % vnc_password
            root_enable_script = ScriptDeployment(script=script, delete=True)
            deploy = kwargs.get("deploy", None)
            if deploy:
                if isinstance(deploy, ScriptDeployment) or isinstance(
                        deploy, SSHKeyDeployment):
                    deployment = MultiStepDeployment(
                        [deploy, root_enable_script])
                elif isinstance(deploy, MultiStepDeployment):
                    deployment = deploy
                    deployment.add(root_enable_script)
            else:
                deployment = root_enable_script

            kwargs["deploy"] = deployment

        if not kwargs.get("ssh_username", None):
            kwargs["ssh_username"] = "******"

        return super(ElasticStackBaseNodeDriver, self).deploy_node(**kwargs)
 def _eval_deploy_template(self, node_temp, kwargs):
     #deploy_node params
     ssh_username = node_temp.getSshUsername()
     kwargs = get_property(self, ssh_username, 'ssh_username'
                           , kwargs, lambda x : x)
     ssh_alternate_usernames = node_temp.getSshAlternateUsernames()
     kwargs = get_property_list(self, ssh_alternate_usernames, 'ssh_alternate_usernames'
                           , kwargs, lambda x : x)
     ssh_port = node_temp.getSshPort()
     kwargs = get_property(self, ssh_port, 'ssh_port'
                           , kwargs, lambda x : int(x))
     ssh_timeout = node_temp.getSshTimeout()
     kwargs = get_property(self, ssh_timeout, 'ssh_timeout'
                           , kwargs, lambda x : float(x))
     ssh_key = node_temp.getSshKey()
     kwargs = get_property(self, ssh_key, 'ssh_key'
                           , kwargs, lambda x : x)
     timeout = node_temp.getTimeout()
     kwargs = get_property(self, timeout, 'timeout'
                           , kwargs, lambda x : int(x))
     max_tries = node_temp.getMaxTries()
     kwargs = get_property(self, max_tries, 'max_tries'
                           , kwargs, lambda x : int(x))
     ssh_interface = node_temp.getSshInterface()
     kwargs = get_property(self, ssh_interface, 'ssh_interface'
                           , kwargs, lambda x : x)
     #get the deployment classes
     deployments = node_temp.getDeploy()
     if deployments:
         msd = MultiStepDeployment()
         for deploy in deployments:
             if isinstance(deploy, SshKeyDeployment):
                 msd.add(SSHKeyDeployment(str(deploy.getKey())))
             elif isinstance(deploy, FileDeployment):
                 msd.add(FileDeployment(deploy.getSource(), deploy.getTarget()))
             elif isinstance(deploy, ScriptDeployment):
                 args = deploy.getArgs()
                 arg_lst = self._parse_arg_list(args)
                 msd.add(ScriptDeployment(deploy.getScriptContent(), arg_lst, 
                                          deploy.getName(), deploy.getDelete()))
             elif isinstance(deploy, ScriptFileDeployment):
                 args = deploy.getArgs()
                 arg_lst = self._parse_arg_list(args)
                 msd.add(ScriptFileDeployment(deploy.getScriptPath(), arg_lst,
                                               deploy.getName(), deploy.getDelete()))
         kwargs['deploy'] = msd
     return kwargs
示例#7
0
def main(
    distro,
    test_type,
    from_version,
    to_version,
    python_package,
    installer_script_url,
    additional_packages=None,
    destroy_node=False,
    verbose=False,
):
    # type: (str, str, str, str, str, str, str, bool, bool) -> None

    # deployment objects for package files will be stored here.
    file_upload_steps = []

    # We always upload all the mock test configs from tests/ami/configs/ directory to a remote
    # server.
    # Those configs are used during various checks and tests. Uploading the configs is much less
    # messy compared to manipulating the configs using sed on the server.
    file_names = os.listdir(MOCK_CONFIGS_DIRECTORY)
    for file_name in file_names:
        config_file_path = os.path.join(MOCK_CONFIGS_DIRECTORY, file_name)
        file_upload_step = _create_config_file_deployment_step(
            config_file_path)
        file_upload_steps.append(file_upload_step)

    # Upload auxiliary files from tests/ami/files/
    file_names = os.listdir(TEST_FILES_DIRECTORY)
    for file_name in file_names:
        file_path = os.path.join(TEST_FILES_DIRECTORY, file_name)
        file_upload_step = _create_file_deployment_step(file_path, "ca_certs")
        file_upload_steps.append(file_upload_step)

    if test_type == "install":
        install_package_source = to_version
    else:
        # install package is specified in from-version in case of upgrade
        install_package_source = from_version

    # prepare data for install_package
    install_package_source_type = _get_source_type(install_package_source)

    if install_package_source_type == "file":
        # create install package file deployment object.
        file_upload_steps.append(
            _create_file_deployment_step(install_package_source,
                                         "install_package"))

    install_package_info = {
        "type": install_package_source_type,
        "source": install_package_source,
    }

    upgrade_package_info = None

    # prepare data for upgrade_package if it is specified.
    if test_type == "upgrade":
        upgrade_package_source = to_version
        upgrade_package_source_type = _get_source_type(upgrade_package_source)

        if upgrade_package_source_type == "file":
            # create install package file deployment object.
            file_upload_steps.append(
                _create_file_deployment_step(to_version, "upgrade_package"))

        upgrade_package_info = {
            "type": upgrade_package_source_type,
            "source": upgrade_package_source,
        }

    distro_details = EC2_DISTRO_DETAILS_MAP[distro]

    if distro.lower().startswith("windows"):
        package_type = "windows"
        script_extension = "ps1"
    else:
        package_type = ("deb" if distro.startswith("ubuntu")
                        or distro.startswith("debian") else "rpm")
        script_extension = "sh"

    script_filename = "test_%s.%s.j2" % (package_type, script_extension)
    script_file_path = os.path.join(SCRIPTS_DIR, script_filename)

    with open(script_file_path, "r") as fp:
        script_content = fp.read()

    cat_logs_script_file_path = os.path.join(
        SCRIPTS_DIR, "cat_logs.%s" % (script_extension))

    with open(cat_logs_script_file_path, "r") as fp:
        cat_logs_script_content = fp.read()

    installer_script_info = {
        "source": installer_script_url or DEFAULT_INSTALLER_SCRIPT_URL
    }
    if os.path.exists(installer_script_url):
        installer_script_info["type"] = "file"
        file_upload_steps.append(
            _create_file_deployment_step(installer_script_url,
                                         "install-scalyr-agent-2"))
    else:
        if not _verify_url_exists(installer_script_url):
            raise ValueError(
                'Failed to retrieve installer script from "%s". Ensure that the URL is correct.'
                % (installer_script_url))
        installer_script_info["type"] = "url"

    rendered_template = render_script_template(
        script_template=script_content,
        distro_name=distro,
        distro_details=distro_details,
        python_package=python_package,
        test_type=test_type,
        install_package=install_package_info,
        upgrade_package=upgrade_package_info,
        installer_script_url=installer_script_info,
        additional_packages=additional_packages,
        verbose=verbose,
    )

    # TODO: Lower those timeouts when upstream yum related issues or similar start to stabilize.
    # All AMI tests should take less than 5 minutes, but in the last days (dec 1, 2020), they
    # started to take 10 minutes with multiple timeouts.
    if "windows" in distro.lower():
        deploy_step_timeout = 440  # 320
        deploy_overall_timeout = 460  # 320
        cat_step_timeout = 10
        max_tries = 3
    else:
        deploy_step_timeout = 320  # 260
        deploy_overall_timeout = 340  # 280
        max_tries = 3
        cat_step_timeout = 5

    remote_script_name = "deploy.{0}".format(script_extension)
    test_package_step = ScriptDeployment(rendered_template,
                                         name=remote_script_name,
                                         timeout=deploy_step_timeout)

    if file_upload_steps:
        # Package files must be uploaded to the instance directly.
        file_upload_steps.append(test_package_step)  # type: ignore
        deployment = MultiStepDeployment(add=file_upload_steps)  # type: ignore
    else:
        deployment = MultiStepDeployment(add=test_package_step)  # type: ignore

    # Add a step which always cats agent.log file at the end. This helps us troubleshoot failures.
    if "windows" not in distro.lower():
        # NOTE: We don't add it on Windows since it tends to time out often
        cat_logs_step = ScriptDeployment(cat_logs_script_content,
                                         timeout=cat_step_timeout)
        deployment.add(cat_logs_step)
    else:
        cat_logs_step = None  # type: ignore

    driver = get_libcloud_driver()

    size = NodeSize(
        distro_details["size_id"],
        distro_details["size_id"],
        0,
        0,
        0,
        0,
        driver,
    )
    image = NodeImage(distro_details["image_id"], distro_details["image_name"],
                      driver, None)

    circle_branch_name = compat.os_environ_unicode.get("CIRCLE_BRANCH",
                                                       "unknown")
    circle_branch_name = circle_branch_name.replace("/", "_").replace("-", "_")
    circle_build_num = compat.os_environ_unicode.get("CIRCLE_BUILD_NUM",
                                                     random.randint(0, 1000))

    name = "%s-automated-agent-tests-%s-branch-%s-build-%s" % (
        distro,
        test_type,
        circle_branch_name,
        circle_build_num,
    )

    print("Starting node provisioning and tests...")

    start_time = int(time.time())

    kwargs = {}
    if destroy_node:
        kwargs["at_exit_func"] = destroy_node_and_cleanup

    try:
        node = driver.deploy_node(name=name,
                                  image=image,
                                  size=size,
                                  ssh_key=PRIVATE_KEY_PATH,
                                  ex_keyname=KEY_NAME,
                                  ex_security_groups=SECURITY_GROUPS,
                                  ssh_username=distro_details["ssh_username"],
                                  ssh_timeout=20,
                                  max_tries=max_tries,
                                  wait_period=15,
                                  timeout=deploy_overall_timeout,
                                  deploy=deployment,
                                  **kwargs)
    except DeploymentError as e:
        print("Deployment failed: %s" % (str(e)))
        node = e.node
        success = False
        test_package_step.exit_status = 1
        stdout = getattr(e.original_error, "stdout", None)
        stderr = getattr(e.original_error, "stderr", None)
    else:
        success = test_package_step.exit_status == 0
        stdout = test_package_step.stdout
        stderr = test_package_step.stderr

        if cat_logs_step and cat_logs_step.stdout:
            stdout += "\n" + cat_logs_step.stdout

        if cat_logs_step and cat_logs_step.stderr:
            stdout += "\n" + cat_logs_step.stderr

    duration = int(time.time()) - start_time

    if success:
        print("Script successfully completed.")
    else:
        print("Script failed.")

    print(("stdout: %s" % (stdout)))
    print(("stderr: %s" % (stderr)))
    print(("exit_code: %s" % (test_package_step.exit_status)))
    print(("succeeded: %s" % (str(success))))
    print(("duration: %s seconds" % (duration)))

    # We don't destroy node if destroy_node is False (e.g. to aid with troubleshooting on failure
    # and similar)
    if node and destroy_node:
        destroy_node_and_cleanup(driver=driver, node=node)

    if not success:
        sys.exit(1)