def __init__(self, object=None, config=None, filters=None):
        self.definition = object
        self.id = definition_id(self.definition)
        self.type = self.definition.get('type')
        self.config = config if config else {}
        self.config['filters'] = []

        if filters and len(filters) > 0:
            for raw_filter in filters:
                self.config['filters'].append(Filter(**raw_filter))
    def discover_objects(self):
        if not self.objects:
            definition = dict(type=self.type, hostname=context.hostname, uuid=context.uuid)

            data = dict(hostname=context.hostname, uuid=context.uuid)

            object_id = definition_id(definition)
            sys_obj = SystemObject(definition=definition, data=data)
            self.objects = {object_id: sys_obj}
            context.top_object = sys_obj
    def talk_with_cloud(self, top_object=None):
        # TODO: receive commands from cloud

        now = int(time.time())
        if now <= self.last_cloud_talk_time + 60:
            return

        # talk to cloud
        try:
            cloud_response = self.client.post('agent/', data=top_object)
        except:
            context.log.error('could not connect to cloud', exc_info=True)
            raise AmplifyCriticalException()

        # update special object configs
        changed_containers = []
        for obj_config in cloud_response['objects']:

            obj = obj_config['object']
            obj_type = obj['type']
            container = self.containers[obj_type]
            obj_id = definition_id(obj)

            if container.object_configs.get(obj_id, {}) != obj_config['config']:
                container.object_configs[obj_id] = obj_config['config']
                changed_containers.append(obj_type)

        for obj_type in changed_containers:
            self.containers[obj_type].stop_objects()

        # TODO work with messages
        messages = cloud_response['messages']

        # global config changes
        config_changed = context.app_config.apply(cloud_response['config'])
        if config_changed and self.containers:
            context.log.info('config has changed. now running with: %s' % pprint.pformat(context.app_config.config))
            for container in self.containers.itervalues():
                container.stop_objects()
            self.init_containers()

        self.last_cloud_talk_time = int(time.time())
    def discover_objects(self):
        # save current ids
        existing_ids = self.objects.keys()

        # discover nginxes
        nginxes = self.find_all()

        # process all founded nginxes
        dicovered_ids = []
        while len(nginxes):
            try:
                definition, data = nginxes.pop()
                object_id = definition_id(definition)
                dicovered_ids.append(object_id)

                if object_id not in self.objects:
                    # new object - push it
                    data.update(self.object_configs.get(object_id, {}))  # push cloud config
                    new_obj = NginxObject(definition=definition, data=data)

                    # Send discover event.
                    new_obj.eventd.event(
                        level=INFO,
                        message='nginx-%s master process found, pid %s' % (new_obj.version, new_obj.pid)
                    )

                    self.objects[object_id] = new_obj
                elif object_id in self.objects:
                    current_obj = self.objects[object_id]

                    if current_obj.need_restart:
                        # restart object if needed
                        context.log.debug('config was changed (pid %s)' % current_obj.pid)
                        data.update(self.object_configs.get(object_id, {}))  # push cloud config
                        new_obj = NginxObject(definition=definition, data=data)

                        # Send nginx config changed event.
                        new_obj.eventd.event(
                            level=INFO,
                            message='nginx-%s config changed, read from %s' % (new_obj.version, new_obj.conf_path)
                        )

                        self.objects[object_id] = new_obj
                        current_obj.stop(unregister=False)  # stop old object
                    elif current_obj.pid != data['pid']:
                        # check that object pids didn't change
                        context.log.debug(
                            'nginx was restarted (pid was %s now %s)' % (
                                current_obj.pid, data['pid']
                            )
                        )
                        data.update(self.object_configs.get(object_id, {}))  # push cloud config
                        new_obj = NginxObject(definition=definition, data=data)

                        # Send nginx master process restart/reload event.
                        new_obj.eventd.event(
                            level=INFO,
                            message='nginx-%s master process restarted/reloaded, new pid %s, old pid %s' % (
                                new_obj.version,
                                new_obj.pid,
                                current_obj.pid
                            )
                        )

                        self.objects[object_id] = new_obj
                        current_obj.stop(unregister=False)  # stop old object
                    elif current_obj.workers != data['workers']:
                        # check workers on reload
                        context.log.debug(
                            'nginx was reloaded (workers were %s now %s)' % (
                                current_obj.workers, data['workers']
                            )
                        )
                        current_obj.workers = data['workers']
            except psutil.NoSuchProcess:
                context.log.debug('nginx is restarting/reloading, pids are changing, we will wait')

        # check if we left something in objects (nginx could be stopped or something)
        dropped_ids = filter(lambda x: x not in dicovered_ids, existing_ids)
        if len(dropped_ids):
            for dropped_id in dropped_ids:
                dropped_object = self.objects[dropped_id]
                context.log.debug('nginx was stopped (pid was %s)' % dropped_object.pid)
                dropped_object.stop()  # this is necessary too!
                del self.objects[dropped_id]  # this is necessary