Beispiel #1
0
    def _get_macro(self):
        """Return a buffer to the macro file.

        Will download a remote file in-memory and return a buffer, or
        open the local file and return a buffer to that file.
        """

        remote = ('http://', 'https://')
        if self.option('macro').startswith(remote):
            client = httpclient.HTTPClient()
            try:
                R = client.fetch(self.option('macro'))
            except Exception as e:
                raise exceptions.UnrecoverableActorFailure(e)
            finally:
                client.close()
            buf = io.StringIO()
            # Set buffer representation for debug printing.
            buf.__repr__ = lambda: ('In-memory file from: %s' % self.option(
                'macro'))
            buf.write(R.body)
            buf.seek(0)
            client.close()
            return buf

        try:
            instance = open(self.option('macro'))
        except IOError as e:
            raise exceptions.UnrecoverableActorFailure(e)
        return instance
Beispiel #2
0
 def test_get_exc_type_with_only_unrecoverable(self):
     exc_list = [
         exceptions.UnrecoverableActorFailure(),
         exceptions.UnrecoverableActorFailure(),
         exceptions.UnrecoverableActorFailure()
     ]
     actor = group.Async('Unit Test Action', {'acts': []})
     ret = actor._get_exc_type(exc_list)
     self.assertEquals(ret, exceptions.UnrecoverableActorFailure)
Beispiel #3
0
    def _parse_policy_json(self, policy):
        """Parse a single JSON file into an Amazon policy.

        Validates that the policy document can be parsed, strips out any
        comments, and fills in any environmental tokens. Returns a dictionary
        of the contents.

        Returns None if the input is None.

        args:
            policy: The Policy JSON file to read.

        returns:
            A dictionary of the parsed policy.
        """
        if policy is None:
            return None

        # Run through any supplied Inline IAM Policies and verify that they're
        # not corrupt very early on.
        self.log.debug('Parsing and validating %s' % policy)

        try:
            p_doc = utils.convert_script_to_dict(script_file=policy,
                                                 tokens=self._init_tokens)
        except kingpin_exceptions.InvalidScript as e:
            raise exceptions.UnrecoverableActorFailure('Error parsing %s: %s' %
                                                       (policy, e))

        return p_doc
Beispiel #4
0
    def _find_target_group(self, arn):
        """Returns an ELBv2 Target Group with the matching name.

        Args:
            name: String-name of the Target Group to search for

        Returns:
            A single Target Group reference object

        Raises:
            ELBNotFound
        """
        self.log.info('Searching for Target Group "%s"' % arn)

        try:
            trgts = yield self.api_call(self.elbv2_conn.describe_target_groups,
                                        Names=[arn])
        except botocore_exceptions.ClientError as e:
            raise exceptions.UnrecoverableActorFailure(str(e))

        arns = [t['TargetGroupArn'] for t in trgts['TargetGroups']]

        if len(arns) != 1:
            raise ELBNotFound(
                'Expected to find exactly 1 Target Group. Found %s: %s' %
                (len(arns), arns))

        raise gen.Return(arns[0])
Beispiel #5
0
    def _check_macro(self):
        """For now we are limiting the functionality."""

        prohibited = ('ftp://', )
        if self.option('macro').startswith(prohibited):
            raise exceptions.UnrecoverableActorFailure(
                'Macro actor is cannot handle ftp fetching yet..')
Beispiel #6
0
    def _gather_methods(self):
        """Generates pointers to the Getter and Setter methods.

        Walks through the list of options in self.all_options and discovers the
        pointers to the getter/setter methods. If any are missing, throws an
        exception quickly.
        """
        self.setters = {}
        self.getters = {}
        self.comparers = {}
        for option in self._ensurable_options:
            setter = '_set_%s' % option
            getter = '_get_%s' % option
            comparer = '_compare_%s' % option

            if not self._is_method(getter) or not self._is_method(setter):
                raise exceptions.UnrecoverableActorFailure(
                    'Invalid Actor Code Detected in %s: '
                    'Unable to find required methods: %s, %s' %
                    (self.__class__.__name__, setter, getter))

            if not self._is_method(comparer):

                @gen.coroutine
                def _comparer(option=option):
                    existing = yield self.getters[option]()
                    new = self.option(option)
                    raise gen.Return(existing == new)

                setattr(self, comparer, _comparer)
                # self.log.debug('Creating dynamic method %s' % comparer)

            self.setters[option] = getattr(self, setter)
            self.getters[option] = getattr(self, getter)
            self.comparers[option] = getattr(self, comparer)
Beispiel #7
0
    def _check_results(self, result):
        """Returns True/False if the result was OK from Slack.

        The Slack API avoids using standard error codes, and instead embeds
        error codes in the return results. This method returns True or False
        based on those results.

        Args:
            result: A return dict from Slack

        Raises:
            InvalidCredentials if the creds are bad
            RecoverableActorException on any other value
        """
        try:
            ok = result.get('ok', False)
        except AttributeError:
            raise exceptions.UnrecoverableActorFailure(
                'An unexpected Slack API failure occured: %s' % result)

        if ok:
            return

        # By default, our exception type is a RecoverableActorFailure.
        exc = exceptions.RecoverableActorFailure

        # If we know what kind fo error it is, we'll return a more accurate
        # exception type.
        if result['error'] == 'invalid_auth':
            exc = exceptions.InvalidCredentials

        # Finally, raise our exception
        raise exc('Slack API Error: %s' % result['error'])
Beispiel #8
0
 def _check_schema(self, config):
     # Run the dict through our schema validator quickly
     self.log.debug('Validating schema for %s' % self.option('macro'))
     try:
         schema.validate(config)
     except kingpin_exceptions.InvalidScript as e:
         self.log.critical('Invalid Schema.')
         raise exceptions.UnrecoverableActorFailure(e)
Beispiel #9
0
    def _find_cert(self, name):
        """Find a cert by name."""

        self.log.debug('Searching for cert "%s"...' % name)
        try:
            yield self.api_call(self.iam_conn.get_server_certificate, name)
        except BotoServerError as e:
            raise exceptions.UnrecoverableActorFailure(
                'Could not find cert %s. Reason: %s' % (name, e))
Beispiel #10
0
    def _execute(self):
        """Executes an actor and yields the results when its finished.

        Raises:
            gen.Return()
        """
        q = yield self._create_queue(name=self.option('name'))

        if q.__class__ == boto.sqs.queue.Queue:
            self.log.info('Queue Created: %s' % q.url)
        elif self._dry:
            self.log.info('Fake Queue: %s' % q)
        else:
            raise exceptions.UnrecoverableActorFailure(
                'All hell broke loose: %s' % q)

        raise gen.Return()
Beispiel #11
0
    def _remove(self, arn, targets):
        """Deregisters the supplied Targets with the Target Group ARN.

        http://boto3.readthedocs.io/en/latest/reference/services/
        elbv2.html#ElasticLoadBalancingv2.Client.deregister_targets

        Args:
            arn: ELBv2 Target ARN
            targets: A list of Instance IDs or Target IP Addresses.
        """
        #  TODO: In the future, add support for the optional Port and
        #  AvailabilityZone parameters. For now, keeping this dead simple.
        targets = [{'Id': t} for t in targets]

        try:
            yield self.api_call(self.elbv2_conn.deregister_targets,
                                TargetGroupArn=arn,
                                Targets=targets)
        except botocore.exceptions.ClientError as e:
            raise exceptions.UnrecoverableActorFailure(e.message)
Beispiel #12
0
    def _get_config_from_script(self, script_file):
        """Convert a script into a dict() with inserted ENV vars.

        Run the JSON dictionary through our environment parser and return
        back a dictionary with all of the %XX% keys swapped out with
        environment variables.

        Args:
            script_file: A path string to a file, or an open() file stream.

        Returns:
            Dictionary adhering to our schema.

        Raises:
            UnrecoverableActorFailure -
                if parsing script or inserting env vars fails.
        """
        self.log.debug('Parsing %s' % script_file)
        try:
            return utils.convert_script_to_dict(script_file=script_file,
                                                tokens=self._init_tokens)
        except (kingpin_exceptions.InvalidScript, LookupError) as e:
            raise exceptions.UnrecoverableActorFailure(e)
Beispiel #13
0
    def _find_server_arrays(self, array_name,
                            raise_on='notfound',
                            allow_mock=True,
                            exact=True):
        """Find a ServerArray by name and return it.

        Args:
            array_name: String name of the ServerArray to find.
            raise_on: Either None, 'notfound' or 'found'
            allow_mock: Boolean whether or not to allow a Mock object to be
                        returned instead.
            exact: Boolean whether or not to allow multiple arrays to be
                   returned.

        Raises:
            gen.Return(<rightscale.Resource of Server Array>)
            ArrayNotFound()
            ArrayAlreadyExists()
        """
        if raise_on == 'notfound':
            msg = 'Verifying that array "%s" exists' % array_name
        elif raise_on == 'found':
            msg = 'Verifying that array "%s" does not exist' % array_name
        elif not raise_on:
            msg = 'Searching for array named "%s"' % array_name
        else:
            raise exceptions.UnrecoverableActorFailure(
                'Invalid "raise_on" setting in actor code.')

        self.log.debug(msg)
        array = yield self._client.find_server_arrays(array_name, exact=exact)

        if not array and self._dry and allow_mock:
            # Create a fake ServerArray object thats mocked up to help with
            # execution of the rest of the code.
            self.log.info('Array "%s" not found -- creating a mock.' %
                          array_name)
            array = mock.MagicMock(name=array_name)
            # Give the mock a real identity and give it valid elasticity
            # parameters so the Launch() actor can behave properly.
            array.soul = {
                # Used elsewhere to know whether we're working on a mock
                'fake': True,

                # Fake out common server array object properties
                'name': '<mocked array %s>' % array_name,
                'elasticity_params': {'bounds': {'min_count': 4,
                                                 'max_count': 4}}
            }
            array.self.path = '/fake/array/%s' % randint(10000, 20000)
            array.self.show.return_value = array

        if array and raise_on == 'found':
            raise ArrayAlreadyExists('Array "%s" already exists!' % array_name)

        if not array and raise_on == 'notfound':
            raise ArrayNotFound('Array "%s" not found!' % array_name)

        # Quick note. If many arrays were returned, lets make sure we throw a
        # note to the user so they know whats going on.
        if isinstance(array, list):
            for a in array:
                self.log.info('Matching array found: %s' % a.soul['name'])

        raise gen.Return(array)