Exemple #1
0
    def test_delete_action_files_from_pack(self):
        """
        Test that the action files present in the pack and removed
        on the call of delete_action_files_from_pack function.
        """

        entry_point = os.path.join(TEST_PACK_PATH, "actions", "test_entry_point.py")
        metadata_file = os.path.join(TEST_PACK_PATH, "actions", "test_metadata.yaml")

        # creating entry_point file in dummy pack
        with open(entry_point, "w") as f:
            f.write("# entry point file to be removed")

        # creating metadata file in dummy pack
        with open(metadata_file, "w") as f:
            f.write("# metadata file to be removed")

        # asserting both entry_point and metadata files exists
        self.assertTrue(os.path.exists(entry_point))
        self.assertTrue(os.path.exists(metadata_file))

        delete_action_files_from_pack(TEST_PACK, entry_point, metadata_file)

        # asserting both entry_point and metadata files removed and they doesn't exist
        self.assertFalse(os.path.exists(entry_point))
        self.assertFalse(os.path.exists(metadata_file))
Exemple #2
0
    def test_exception_to_remove_resource_metadata_file(self, remove):

        entry_point = os.path.join(TEST_PACK_PATH, "actions",
                                   "test_entry_point.py")
        metadata_file = os.path.join(TEST_PACK_PATH, "actions",
                                     "test_metadata.yaml")

        remove.side_effect = Exception("Another exception occured")

        # asserting metadata file exists
        self.assertTrue(os.path.exists(metadata_file))

        # asserting entry_point file doesn't exist
        self.assertFalse(os.path.exists(entry_point))

        expected_msg = (
            'The action file "%s" could not be removed from disk, please '
            "check the logs or ask your StackStorm administrator to check "
            "and delete the actions files manually" % (metadata_file))

        # asserting exception with message on call of delete_action_files_from_pack
        # to delete metadata file
        with self.assertRaisesRegexp(Exception, expected_msg):
            delete_action_files_from_pack(TEST_PACK, entry_point,
                                          metadata_file)
Exemple #3
0
    def test_permission_error_to_remove_resource_entry_point_file(
            self, remove):

        entry_point = os.path.join(TEST_PACK_PATH, "actions",
                                   "test_entry_point.py")
        metadata_file = os.path.join(TEST_PACK_PATH, "actions",
                                     "test_metadata.yaml")

        remove.side_effect = PermissionError(
            "No permission to delete file from disk")

        # asserting entry_point file exists
        self.assertTrue(os.path.exists(entry_point))

        # asserting metadata file doesn't exist
        self.assertFalse(os.path.exists(metadata_file))

        expected_msg = 'No permission to delete "%s" file from disk' % (
            entry_point)

        # asserting PermissionError with message on call of delete_action_files_from_pack
        # to delete entry_point file
        with self.assertRaisesRegexp(PermissionError, expected_msg):
            delete_action_files_from_pack(TEST_PACK, entry_point,
                                          metadata_file)
Exemple #4
0
    def test_metadata_file_does_not_exists(self):
        """
        Tests that metadata file doesn't exists at the path and if action delete
        api calls delete_action_files_from_pack function, it doesn't affect.
        """

        entry_point = os.path.join(TEST_PACK_PATH, "actions",
                                   "test_entry_point.py")
        metadata_file = os.path.join(TEST_PACK_PATH, "actions",
                                     "test_metadata.yaml")

        # creating only entry_point file in dummy pack
        with open(entry_point, "w") as f:
            f.write("# entry point file to be removed")

        # asserting metadata file doesn't exist
        self.assertFalse(os.path.exists(metadata_file))

        # asserting entry_point file exists
        self.assertTrue(os.path.exists(entry_point))

        delete_action_files_from_pack(TEST_PACK, entry_point, metadata_file)

        # asserting both entry_point and metadata files don't exist
        self.assertFalse(os.path.exists(entry_point))
        self.assertFalse(os.path.exists(metadata_file))
Exemple #5
0
    def delete(self, options, ref_or_id, requester_user):
        """
        Delete an action.

        Handles requests:
            POST /actions/1?_method=delete
            DELETE /actions/1
            DELETE /actions/mypack.myaction
        """
        action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id)
        action_id = action_db.id

        permission_type = PermissionType.ACTION_DELETE
        rbac_utils = get_rbac_backend().get_utils_class()
        rbac_utils.assert_user_has_resource_db_permission(
            user_db=requester_user,
            resource_db=action_db,
            permission_type=permission_type,
        )

        try:
            validate_not_part_of_system_pack(action_db)
        except ValueValidationException as e:
            abort(http_client.BAD_REQUEST, six.text_type(e))

        LOG.debug(
            "DELETE /actions/ lookup with ref_or_id=%s found object: %s",
            ref_or_id,
            action_db,
        )

        pack_name = action_db["pack"]
        entry_point = action_db["entry_point"]
        metadata_file = action_db["metadata_file"]

        try:
            Action.delete(action_db)
        except Exception as e:
            LOG.error(
                'Database delete encountered exception during delete of id="%s". '
                "Exception was %s",
                action_id,
                e,
            )
            abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))
            return

        if options.remove_files:
            try:
                delete_action_files_from_pack(
                    pack_name=pack_name,
                    entry_point=entry_point,
                    metadata_file=metadata_file,
                )
            except PermissionError as e:
                LOG.error("No permission to delete resource files from disk.")
                action_db.id = None
                Action.add_or_update(action_db)
                abort(http_client.FORBIDDEN, six.text_type(e))
                return
            except Exception as e:
                LOG.error(
                    "Exception encountered during deleting resource files from disk. "
                    "Exception was %s",
                    e,
                )
                action_db.id = None
                Action.add_or_update(action_db)
                abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))
                return

        extra = {"action_db": action_db}
        LOG.audit("Action deleted. Action.id=%s" % (action_db.id), extra=extra)
        return Response(status=http_client.NO_CONTENT)
Exemple #6
0
    def clone(self, dest_data, ref_or_id, requester_user):
        """
        Clone an action from source pack to destination pack.
        Handles requests:
            POST /actions/{ref_or_id}/clone
        """

        source_action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id)
        if not source_action_db:
            msg = "The requested source for cloning operation doesn't exists"
            abort(http_client.BAD_REQUEST, six.text_type(msg))

        extra = {"action_db": source_action_db}
        LOG.audit("Source action found. Action.id=%s" % (source_action_db.id),
                  extra=extra)

        try:
            permission_type = PermissionType.ACTION_VIEW
            rbac_utils = get_rbac_backend().get_utils_class()
            rbac_utils.assert_user_has_resource_db_permission(
                user_db=requester_user,
                resource_db=source_action_db,
                permission_type=permission_type,
            )
        except ResourceAccessDeniedError as e:
            abort(http_client.UNAUTHORIZED, six.text_type(e))

        cloned_dest_action_db = clone_action_db(
            source_action_db=source_action_db,
            dest_pack=dest_data.dest_pack,
            dest_action=dest_data.dest_action,
        )

        cloned_action_api = ActionAPI.from_model(cloned_dest_action_db)

        try:
            permission_type = PermissionType.ACTION_CREATE
            rbac_utils.assert_user_has_resource_api_permission(
                user_db=requester_user,
                resource_api=cloned_action_api,
                permission_type=permission_type,
            )
        except ResourceAccessDeniedError as e:
            abort(http_client.UNAUTHORIZED, six.text_type(e))

        dest_pack_base_path = get_pack_base_path(pack_name=dest_data.dest_pack)

        if not os.path.isdir(dest_pack_base_path):
            msg = "Destination pack '%s' doesn't exist" % (dest_data.dest_pack)
            abort(http_client.BAD_REQUEST, six.text_type(msg))

        dest_pack_base_path = get_pack_base_path(pack_name=dest_data.dest_pack)
        dest_ref = ".".join([dest_data.dest_pack, dest_data.dest_action])
        dest_action_db = self._get_by_ref(resource_ref=dest_ref)

        try:
            validate_not_part_of_system_pack_by_name(dest_data.dest_pack)
        except ValueValidationException as e:
            abort(http_client.BAD_REQUEST, six.text_type(e))

        if dest_action_db:
            if not dest_data.overwrite:
                msg = "The requested destination action already exists"
                abort(http_client.BAD_REQUEST, six.text_type(msg))

            try:
                permission_type = PermissionType.ACTION_DELETE
                rbac_utils.assert_user_has_resource_db_permission(
                    user_db=requester_user,
                    resource_db=dest_action_db,
                    permission_type=permission_type,
                )
                options = GenericRequestParam(remove_files=True)
                dest_metadata_file = dest_action_db["metadata_file"]
                dest_entry_point = dest_action_db["entry_point"]
                temp_sub_dir = str(uuid.uuid4())
                temp_backup_action_files(
                    dest_pack_base_path,
                    dest_metadata_file,
                    dest_entry_point,
                    temp_sub_dir,
                )
                self.delete(options, dest_ref, requester_user)
            except ResourceAccessDeniedError as e:
                abort(http_client.UNAUTHORIZED, six.text_type(e))
            except Exception as e:
                LOG.debug(
                    "Exception encountered during deleting existing destination action. "
                    "Exception was: %s",
                    e,
                )
                abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))

        try:
            post_response = self.post(cloned_action_api, requester_user)
            if post_response.status_code != http_client.CREATED:
                raise Exception("Could not add cloned action to database.")
            cloned_dest_action_db["id"] = post_response.json["id"]
            clone_action_files(
                source_action_db=source_action_db,
                dest_action_db=cloned_dest_action_db,
                dest_pack_base_path=dest_pack_base_path,
            )
            extra = {"cloned_acion_db": cloned_dest_action_db}
            LOG.audit("Action cloned. Action.id=%s" %
                      (cloned_dest_action_db.id),
                      extra=extra)
            if dest_action_db:
                remove_temp_action_files(temp_sub_dir)
            return post_response
        except PermissionError as e:
            LOG.error("No permission to clone the action. Exception was %s", e)
            delete_action_files_from_pack(
                pack_name=cloned_dest_action_db["pack"],
                entry_point=cloned_dest_action_db["entry_point"],
                metadata_file=cloned_dest_action_db["metadata_file"],
            )
            if post_response.status_code == http_client.CREATED:
                Action.delete(cloned_dest_action_db)
            if dest_action_db:
                self._restore_action(dest_action_db, dest_pack_base_path,
                                     temp_sub_dir)
            abort(http_client.FORBIDDEN, six.text_type(e))
        except Exception as e:
            LOG.error(
                "Exception encountered during cloning action. Exception was %s",
                e,
            )
            delete_action_files_from_pack(
                pack_name=cloned_dest_action_db["pack"],
                entry_point=cloned_dest_action_db["entry_point"],
                metadata_file=cloned_dest_action_db["metadata_file"],
            )
            if post_response.status_code == http_client.CREATED:
                Action.delete(cloned_dest_action_db)
            if dest_action_db:
                self._restore_action(dest_action_db, dest_pack_base_path,
                                     temp_sub_dir)

            abort(http_client.INTERNAL_SERVER_ERROR, six.text_type(e))