Esempio n. 1
0
    def set_healthcheck(self, previous_config):
        data = getattr(previous_config, 'healthcheck', {}).copy()
        new_data = getattr(self, 'healthcheck', {}).copy()
        # update the config data for healthcheck if they are not
        # present for per proctype
        # TODO: This is required for backward compatibility and can be
        # removed in next major version change.
        if 'livenessProbe' in data.keys() or 'readinessProbe' in data.keys():
            data = {'web/cmd': data.copy()}
        if 'livenessProbe' in new_data.keys() or 'readinessProbe' in new_data.keys():  # noqa
            new_data = {'web/cmd': new_data.copy()}

        # remove config keys if a null value is provided
        for key, value in new_data.items():
            if value is None:
                # error if unsetting non-existing key
                if key not in data:
                    raise UnprocessableEntity('{} does not exist under {}'.format(key, 'healthcheck'))  # noqa
                data.pop(key)
            else:
                for probeType, probe in value.items():
                    if probe is None:
                        # error if unsetting non-existing key
                        if key not in data or probeType not in data[key].keys():
                            raise UnprocessableEntity('{} does not exist under {}'.format(key, 'healthcheck'))  # noqa
                        data[key].pop(probeType)
                    else:
                        if key not in data:
                            data[key] = {}
                        data[key][probeType] = probe
        setattr(self, 'healthcheck', data)
Esempio n. 2
0
    def save(self, **kwargs):
        """merge the old config with the new"""
        try:
            # Get config from the latest available release
            try:
                previous_config = self.app.release_set.latest().config
            except Release.DoesNotExist:
                # If that doesn't exist then fallback on app config
                # usually means a totally new app
                previous_config = self.app.config_set.latest()

            for attr in ['cpu', 'memory', 'tags', 'registry', 'values', 'healthcheck']:
                data = getattr(previous_config, attr, {}).copy()
                new_data = getattr(self, attr, {}).copy()

                # remove config keys if a null value is provided
                for key, value in new_data.items():
                    if value is None:
                        # error if unsetting non-existing key
                        if key not in data:
                            raise UnprocessableEntity('{} does not exist under {}'.format(key, attr))  # noqa
                        data.pop(key)
                    else:
                        data[key] = value
                setattr(self, attr, data)

            self._migrate_legacy_healthcheck()
            self.set_registry()
            self.set_tags(previous_config)
        except Config.DoesNotExist:
            pass

        return super(Config, self).save(**kwargs)
Esempio n. 3
0
    def delete(self, request, **kwargs):
        appSettings = self.get_app().appsettings_set.latest()
        addresses = self.get_serializer().validate_allowlist(
            request.data.get('addresses'))

        unfound_addresses = set(addresses) - set(appSettings.allowlist)
        if len(unfound_addresses) != 0:
            raise UnprocessableEntity(
                'addresses {} does not exist in allowlist'.format(
                    unfound_addresses))  # noqa
        addresses = list(set(appSettings.allowlist) - set(addresses))
        appSettings.new(self.request.user, allowlist=addresses)
        return Response(status=status.HTTP_204_NO_CONTENT)
Esempio n. 4
0
    def _update_autoscale(self, previous_settings):
        data = getattr(previous_settings, 'autoscale', {}).copy()
        new = getattr(self, 'autoscale', {}).copy()
        # If no previous settings then do nothing
        if not previous_settings:
            return

        # if nothing changed copy the settings from previous
        if not new and data:
            setattr(self, 'autoscale', data)
        elif data != new:
            for proc, scale in new.items():
                if scale is None:
                    # error if unsetting non-existing key
                    if proc not in data:
                        raise UnprocessableEntity(
                            '{} does not exist under {}'.format(
                                proc, 'autoscale'))  # noqa
                    del data[proc]
                else:
                    data[proc] = scale
            setattr(self, 'autoscale', data)

            # only apply new items
            for proc, scale in new.items():
                self.app.autoscale(proc, scale)

            # if the autoscale information changed, log the dict diff
            changes = []
            old_autoscale = getattr(previous_settings, 'autoscale', {})
            diff = dict_diff(self.autoscale, old_autoscale)
            # try to be as succinct as possible
            added = ', '.join(
                list(
                    map(lambda x: 'default' if x == '' else x,
                        [k for k in diff.get('added', {})])))  # noqa
            added = 'added autoscale for process type ' + added if added else ''
            changed = ', '.join(
                list(
                    map(lambda x: 'default' if x == '' else x,
                        [k for k in diff.get('changed', {})])))  # noqa
            changed = 'changed autoscale for process type ' + changed if changed else ''
            deleted = ', '.join(
                list(
                    map(lambda x: 'default' if x == '' else x,
                        [k for k in diff.get('deleted', {})])))  # noqa
            deleted = 'deleted autoscale for process type ' + deleted if deleted else ''
            changes = ', '.join(i for i in (added, changed, deleted) if i)
            if changes:
                self.summary += ["{} {}".format(self.owner, changes)]
Esempio n. 5
0
    def path(self, request, *args, **kwargs):
        new_path = request.data.get('path')
        if new_path is None:
            raise DryccException("path is a required field")
        obj = self.get_object()
        container_types = [
            _ for _ in new_path.keys()
            if _ not in obj.app.types or _ not in obj.app.structure.keys()
        ]
        if container_types:
            raise DryccException(
                "process type {} is not included in profile".format(
                    ','.join(container_types)))

        if set(new_path.items()).issubset(set(obj.path.items())):
            raise DryccException("mount path not changed")

        other_volumes = self.get_app().volume_set.exclude(name=obj.name)
        type_paths = {}  # {'type1':[path1,path2], tyep2:[path3,path4]}
        for _ in other_volumes:
            for k, v in _.path.items():
                if k not in type_paths:
                    type_paths[k] = [v]
                else:
                    type_paths[k].append(k)
        repeat_path = [
            v for k, v in new_path.items() if v in type_paths.get(k, [])
        ]  # noqa
        if repeat_path:
            raise DryccException("path {} is used by another volume".format(
                ','.join(repeat_path)))
        path = obj.path
        pre_path = deepcopy(path)
        # merge mount path
        # remove path keys if a null value is provided
        for key, value in new_path.items():
            if value is None:
                # error if unsetting non-existing key
                if key not in path:
                    raise UnprocessableEntity(
                        '{} does not exist under {}'.format(key,
                                                            "volume"))  # noqa
                path.pop(key)
            else:
                path[key] = value
        obj.path = path  # after merge path
        obj.save()
        self.deploy(obj, pre_path)
        serializer = self.get_serializer(obj, many=False)
        return Response(serializer.data)
Esempio n. 6
0
    def _update_label(self, previous_settings):
        data = getattr(previous_settings, 'label', {}).copy()
        new = getattr(self, 'label', {}).copy()
        if not previous_settings:
            return

        # if nothing changed copy the settings from previous
        if not new and data:
            setattr(self, 'label', data)
        elif data != new:
            for k, v in new.items():
                if v is not None:
                    data[k] = v
                else:
                    if k not in data:
                        raise UnprocessableEntity(
                            '{} does not exist under {}'.format(
                                k, 'label'))  # noqa
                    del data[k]
            setattr(self, 'label', data)

            diff = dict_diff(self.label, getattr(previous_settings, 'label',
                                                 {}))
            added = ', '.join(
                list(
                    map(lambda x: 'default' if x == '' else x,
                        [k for k in diff.get('added', {})])))  # noqa
            added = 'added label ' + added if added else ''
            changed = ', '.join(
                list(
                    map(lambda x: 'default' if x == '' else x,
                        [k for k in diff.get('changed', {})])))  # noqa
            changed = 'changed label ' + changed if changed else ''
            deleted = ', '.join(
                list(
                    map(lambda x: 'default' if x == '' else x,
                        [k for k in diff.get('deleted', {})])))  # noqa
            deleted = 'deleted label ' + deleted if deleted else ''
            changes = ', '.join(i for i in (added, changed, deleted) if i)
            if changes:
                if self.summary:
                    self.summary += ' and '
                self.summary += ["{} {}".format(self.owner, changes)]