def _executeSingle(self, stanza, key, value=''):
        '''
        Commits a write action on a single key/value pair
        '''

        if self.isImportMode: return

        logger.debug('_executeSingle: stanza=%s => %s=%s' %
                     (stanza, key, value))

        # first check if stanza exists; create if necessary
        try:
            uri = self.getEndpointPath(self.name, stanza)
            rest.simpleRequest(uri, sessionKey=self.sessionKey)

        except splunk.ResourceNotFound:
            createUri = self.getEndpointPath(self.name)
            serverResponse, serverContent = rest.simpleRequest(
                createUri, self.sessionKey, postargs={'__stanza': stanza})

        # now write the key
        serverResponse, serverContent = rest.simpleRequest(
            uri,
            self.sessionKey,
            postargs={key: value},
            method=self._getWriteMethod())

        if serverResponse.status != 200:
            logger.error('_executeSingle - HTTP error=%s server returned: %s' %
                         (serverResponse.status, serverContent))
            raise splunk.RESTException, (
                serverResponse.status,
                '_executeSingle - server returned: %s' % serverContent)
    def _executeBatch(self, stanza, kvPairs):
        if self.isImportMode: return
        logger.debug('_executeBatch: stanza=%s => %s' % (stanza, kvPairs))

        # first check if stanza exists; create if necessary
        try:
            uri = self.getEndpointPath(self.name, stanza)
            rest.simpleRequest(uri, sessionKey=self.sessionKey)
        except splunk.ResourceNotFound:
            createUri = self.getEndpointPath(self.name)
            serverResponse, serverContent = rest.simpleRequest(
                createUri, self.sessionKey, postargs={'__stanza': stanza})

        # now write out the keys
        serverResponse, serverContent = rest.simpleRequest(
            uri,
            self.sessionKey,
            postargs=kvPairs,
            method=self._getWriteMethod())

        if serverResponse.status != 200:
            logger.error('_executeBatch - HTTP error=%s server returned: %s' %
                         (serverResponse.status, serverContent))
            raise splunk.RESTException, (
                serverResponse.status,
                '_executeBatch - server returned: %s' % serverContent)
Пример #3
0
def controlEntity(action, entityURI, sessionKey=None):
    if action == 'remove':
        serverResponse, serverContent = rest.simpleRequest(
            entityURI,
            sessionKey=sessionKey,
            method='DELETE',
            raiseAllErrors=True)
    elif action == 'enable':
        serverResponse, serverContent = rest.simpleRequest(
            entityURI,
            sessionKey=sessionKey,
            method='POST',
            raiseAllErrors=True)
    elif action == 'disable':
        serverResponse, serverContent = rest.simpleRequest(
            entityURI,
            sessionKey=sessionKey,
            method='POST',
            raiseAllErrors=True)
    else:
        raise Exception, 'unknown action=%s' % action

    if serverResponse.status == 200:
        return True
    else:
        raise Exception, 'unhandled HTTP status=%s' % serverResponse.status
Пример #4
0
    def _executeBatch(self, stanza, kvPairs):
        if self.isImportMode: return
        logger.debug('_executeBatch: stanza=%s => %s' % (stanza, kvPairs))

        # first check if stanza exists; create if necessary
        try:
            uri = self.getEndpointPath(self.name, stanza)
            rest.simpleRequest(uri, sessionKey=self.sessionKey)
        except splunk.ResourceNotFound:
            createUri = self.getEndpointPath(self.name)
            serverResponse, serverContent = rest.simpleRequest(
                createUri, 
                self.sessionKey,
                postargs={'__stanza': stanza}
                )

        # now write out the keys
        serverResponse, serverContent = rest.simpleRequest(
            uri,
            self.sessionKey,
            postargs=kvPairs,
            method=self._getWriteMethod()
            )
        
        if serverResponse.status != 200:
            logger.error('_executeBatch - HTTP error=%s server returned: %s' % (serverResponse.status, serverContent))
            raise splunk.RESTException, (serverResponse.status, '_executeBatch - server returned: %s' % serverContent)
Пример #5
0
    def _executeSingle(self, stanza, key, value = ''):
        '''
        Commits a write action on a single key/value pair
        '''

        if self.isImportMode: return

        logger.debug('_executeSingle: stanza=%s => %s=%s' % (stanza, key, value))

        # first check if stanza exists; create if necessary
        try:
            uri = self.getEndpointPath(self.name, stanza)
            rest.simpleRequest(uri, sessionKey=self.sessionKey)
            
        except splunk.ResourceNotFound:
            createUri = self.getEndpointPath(self.name)
            serverResponse, serverContent = rest.simpleRequest(
                createUri, 
                self.sessionKey,
                postargs={'__stanza': stanza}
                )
            
        # now write the key
        serverResponse, serverContent = rest.simpleRequest(
            uri,
            self.sessionKey,
            postargs={key: value},
            method=self._getWriteMethod()
            )

        if serverResponse.status != 200:
            logger.error('_executeSingle - HTTP error=%s server returned: %s' % (serverResponse.status, serverContent))
            raise splunk.RESTException, (serverResponse.status, '_executeSingle - server returned: %s' % serverContent)
Пример #6
0
def controlEntity(action, entityURI, sessionKey=None):
    if action == 'remove':
        serverResponse, serverContent = rest.simpleRequest(entityURI, sessionKey=sessionKey, method='DELETE', raiseAllErrors=True)
    elif action == 'enable':
        serverResponse, serverContent = rest.simpleRequest(entityURI, sessionKey=sessionKey, method='POST', raiseAllErrors=True)        
    elif action == 'disable':
        serverResponse, serverContent = rest.simpleRequest(entityURI, sessionKey=sessionKey, method='POST', raiseAllErrors=True)        
    else:
        raise Exception, 'unknown action=%s' % action

    if serverResponse.status == 200:
        return True
    else:
        raise Exception, 'unhandled HTTP status=%s' % serverResponse.status
def getEntity(entityPath, entityName, uri=None, namespace=None, owner=None, sessionKey=None, hostPath=None, **kwargs):
    '''
    Retrieves a generic Splunkd entity from the REST endpoint

    @param entityPath: the class of objects to retrieve
    @param entityName: the specific name of the entity to retrieve
    @param namespace: the namespace within which to look for the entities.  if None, then pull from merged
    @param owner: the owner within which to look for the entity.  defaults to current user

    '''
    
    # get default params
    if not owner: owner = auth.getCurrentUser()['name']

    if not uri:
       if not entityName:
          raise ValueError, "entityName cannot be empty"
       uri = buildEndpoint(entityPath, entityName=entityName, namespace=namespace, owner=owner, hostPath=hostPath)
    
    serverResponse, serverContent = rest.simpleRequest(uri, getargs=kwargs, sessionKey=sessionKey, raiseAllErrors=True)

    if serverResponse.status != 200:
        logger.warn('getEntity - unexpected HTTP status=%s while fetching "%s"' % (serverResponse.status, uri))

    atomEntry = rest.format.parseFeedDocument(serverContent)

    if isinstance(atomEntry, rest.format.AtomFeed):
        try:
            atomEntry = atomEntry[0]
        except IndexError, e:
            # Handle cases where no entry is found
            return None
def dispatchSavedSearch(savedSearchName, sessionKey=None, namespace=None, owner=None, hostPath=None, now=0, triggerActions=0, **kwargs):
    """Initiates a new job based on a saved search."""

    uri = entity.buildEndpoint(['saved', 'searches', savedSearchName, 'dispatch'], namespace=namespace, owner=owner)
    if hostPath:
        uri = splunk.mergeHostPath(hostPath) + uri
        
    args = {
        'now': now,
        'trigger_actions' : triggerActions
    }
    
    for key, val in kwargs.items():
        if key in SAVED_SEARCH_DISPATCH_ARG_MAP:
            args[SAVED_SEARCH_DISPATCH_ARG_MAP[key]] = val
        # Pass through for dispatch.* formated kwargs
        elif key.startswith('dispatch.'):
            args[key] = val

    serverResponse, serverContent = rest.simpleRequest(uri, postargs=args, sessionKey=sessionKey)
    root = et.fromstring(serverContent)

    # normal messages from splunkd are propogated via SplunkdException;
    if not 201 == serverResponse.status:

        extractedMessages = rest.extractMessages(root)
        for msg in extractedMessages:
            raise splunk.SearchException, msg['text']
    
    # get the search ID
    sid = root.findtext('sid').strip()

    # instantiate result object
    return splunk.search.SearchJob(sid, hostPath, sessionKey, namespace, owner)
Пример #9
0
def deleteEntity(entityPath,
                 entityName,
                 namespace,
                 owner,
                 sessionKey=None,
                 hostPath=None):
    '''
    Deletes an entity
    '''

    uri = buildEndpoint(entityPath,
                        entityName,
                        namespace=namespace,
                        owner=owner,
                        hostPath=hostPath)
    serverResponse, serverContent = rest.simpleRequest(uri,
                                                       sessionKey=sessionKey,
                                                       method='DELETE',
                                                       raiseAllErrors=True)

    if serverResponse.status == 200:
        logger.info('deleteEntity - deleted entity=%s' % uri)
        return True
    else:
        raise Exception, 'deleteSearch - unhandled HTTP status=%s' % serverResponse.status
Пример #10
0
def getSessionKey(username, password, hostPath=None):
    '''
    Get a session key from the auth system
    '''

    uri = '/services/auth/login'
    if hostPath:
        uri = splunk.mergeHostPath(hostPath) + uri
    args = {'username': username, 'password': password }
    
    # To prove the theory of timing issue of Splunkd not in running state
    # in Windows Bamboo tests, sleep for 10 seconds

    # An attempt to fix SPL-37413
    # if platform.system() == 'Windows':
    #     time.sleep(10)

    serverResponse, serverContent = rest.simpleRequest(uri, postargs=args)

    if serverResponse.status != 200:
        logger.error('getSessionKey - unable to login; check credentials')
        rest.extractMessages(et.fromstring(serverContent))
        return None
        
    root = et.fromstring(serverContent)
    sessionKey = root.findtext('sessionKey')

    splunk.setDefault('username', username)
    splunk.setDefault('sessionKey', sessionKey)
    
    return sessionKey
Пример #11
0
def dispatchSavedSearch(savedSearchName, sessionKey=None, namespace=None, owner=None, hostPath=None, now=0, triggerActions=0, **kwargs):
    """Initiates a new job based on a saved search."""

    uri = entity.buildEndpoint(['saved', 'searches', savedSearchName, 'dispatch'], namespace=namespace, owner=owner)
    if hostPath:
        uri = splunk.mergeHostPath(hostPath) + uri
        
    args = {
        'now': now,
        'trigger_actions' : triggerActions
    }
    
    for key, val in kwargs.items():
        if key in SAVED_SEARCH_DISPATCH_ARG_MAP:
            args[SAVED_SEARCH_DISPATCH_ARG_MAP[key]] = val
        # Pass through for dispatch.* formated kwargs
        elif key.startswith('dispatch.'):
            args[key] = val

    serverResponse, serverContent = rest.simpleRequest(uri, postargs=args, sessionKey=sessionKey)
    root = et.fromstring(serverContent)

    # normal messages from splunkd are propogated via SplunkdException;
    if not 201 == serverResponse.status:

        extractedMessages = rest.extractMessages(root)
        for msg in extractedMessages:
            raise splunk.SearchException, msg['text']
    
    # get the search ID
    sid = root.findtext('sid').strip()

    # instantiate result object
    return splunk.search.SearchJob(sid, hostPath, sessionKey, namespace, owner)
def _getEntitiesAtomFeed(entityPath, namespace=None, owner=None, search=None, count=None, offset=0, sort_key=None, sort_dir=None , sessionKey=None, uri=None, hostPath=None, **kwargs):
    # fallback to currently authed user
    if not owner:
        owner = auth.getCurrentUser()['name']

    # construct URI to get entities
    if not uri:
        uri = buildEndpoint(entityPath, namespace=namespace, owner=owner, hostPath=hostPath)
    
    if search:
        kwargs["search"] = search
        
    if count != None:
        kwargs["count"] = count
        
    if offset:
        kwargs["offset"] = offset
        
    if sort_key:
        kwargs["sort_key"] = sort_key
        
    if sort_dir:
        kwargs["sort_dir"] = sort_dir
    
    # fetch list of entities
    serverResponse, serverContent = rest.simpleRequest(uri, getargs=kwargs, sessionKey=sessionKey, raiseAllErrors=True)
    
    if serverResponse.status != 200:
        raise splunk.RESTException, (serverResponse.status, serverResponse.messages)
        
    atomFeed = rest.format.parseFeedDocument(serverContent)
    return atomFeed
Пример #13
0
def getSessionKey(username, password, hostPath=None):
    '''
    Get a session key from the auth system
    '''

    uri = '/services/auth/login'
    if hostPath:
        uri = splunk.mergeHostPath(hostPath) + uri
    args = {'username': username, 'password': password}

    # To prove the theory of timing issue of Splunkd not in running state
    # in Windows Bamboo tests, sleep for 10 seconds

    # An attempt to fix SPL-37413
    # if platform.system() == 'Windows':
    #     time.sleep(10)

    serverResponse, serverContent = rest.simpleRequest(uri, postargs=args)

    if serverResponse.status != 200:
        logger.error('getSessionKey - unable to login; check credentials')
        rest.extractMessages(et.fromstring(serverContent))
        return None

    root = et.fromstring(serverContent)
    sessionKey = root.findtext('sessionKey')

    splunk.setDefault('username', username)
    splunk.setDefault('sessionKey', sessionKey)

    return sessionKey
def createConf(confName,
               namespace=None,
               owner=None,
               sessionKey=None,
               hostPath=None):
    '''
    Creates a new conf file.  Returns a conf instance of the newly created
    .conf file.
    '''

    uri = entity.buildEndpoint('properties',
                               namespace=namespace,
                               owner=owner,
                               hostPath=hostPath)
    postargs = {'__conf': confName}

    status, response = rest.simpleRequest(uri,
                                          postargs=postargs,
                                          sessionKey=sessionKey,
                                          raiseAllErrors=True)

    # Expect 201 on creation or 200 on preexisting file (automatic handling of 303 redirect).
    if not ((status.status == 201) or
            (status.previous is not None and status.status == 200)):
        logger.error(
            'createConf - unexpected server response while creating conf file "%s"; HTTP=%s'
            % (confName, status.status))

    return getConf(confName,
                   namespace=namespace,
                   owner=owner,
                   sessionKey=sessionKey,
                   hostPath=hostPath)
Пример #15
0
def getConf(confName, sessionKey=None, namespace=None, owner=None, overwriteStanzas=False, hostPath=None):
    '''
    Parses a logical bundle file and returns a Conf() object

    If namespace=None, then the behavior is 3.2-style, where all writes are 
    done to conf files in etc/system/local.  All reads will merge every conf
    file that is accessible in etc/system and etc/apps/*.  If a namespace is 
    provided, then writes are done in etc/apps/<namespace>/local/, and reads 
    are restricted to values in etc/apps/<namespace>/(default|local).  If
    overwriteStanzas is true, old keys in edited stanzas will not be preserved.

    For the 3.2-style reading, the endpoint uses the following priority:
        system/local
        apps/<namespace>/local
        apps/<namespace>/default
        system/default
    '''

    # fallback to current user
    if not owner:
        owner = auth.getCurrentUser()['name']
    
    uri = entity.buildEndpoint(entityClass='properties', entityName=confName, namespace=namespace, 
                               owner=owner, hostPath=hostPath)
    
    # the fillcontents arg will push all stanza keys down in 1 request instead
    # of iterating over all stanzas
    serverResponse, serverContent = rest.simpleRequest(uri, getargs={'fillcontents':1}, sessionKey=sessionKey)
    
    if serverResponse.status != 200:
        logger.info('getConf - server returned status=%s when asked for conf=%s' % (serverResponse.status, confName))
        
    # convert the atom feed into dict
    confFeed = rest.format.parseFeedDocument(serverContent)
    stanzas = confFeed.toPrimitive()
    
    # create Conf/Stanzas
    output = Conf(confName, namespace=namespace, owner=owner, overwriteStanzas=overwriteStanzas)
    output.sessionKey = sessionKey
    output.isImportMode = True
    for name in stanzas:
        stanza = output.createStanza(name)
        stanza.needsPopulation = False
        for k in stanzas[name]:
            if stanzas[name][k] == None:
                stanza[k] = ''
            else:
                stanza[k] = stanzas[name][k]
        
    output.isImportMode = False

    return output
def deleteEntity(entityPath, entityName, namespace, owner, sessionKey=None, hostPath=None):
    '''
    Deletes an entity
    '''

    uri = buildEndpoint(entityPath, entityName, namespace=namespace, owner=owner, hostPath=hostPath)
    serverResponse, serverContent = rest.simpleRequest(uri, sessionKey=sessionKey, method='DELETE', raiseAllErrors=True)
    
    if serverResponse.status == 200:
        logger.info('deleteEntity - deleted entity=%s' % uri)
        return True
    else:
        raise Exception, 'deleteSearch - unhandled HTTP status=%s' % serverResponse.status
Пример #17
0
 def _refreshStanza(self, stanzaName):
     
     uri = self.getEndpointPath(self.name, stanzaName)
     
     serverResponse, serverContent = rest.simpleRequest(uri, sessionKey=self.sessionKey)
     
     #logger.debug('_refreshStanza - got stanza data back')
     keys = rest.format.parseFeedDocument(serverContent)
     keys = keys.toPrimitive()
     #logger.debug('_refreshStanza - parsed stanza data; got %s keys' % len(keys))
     self.isImportMode = True
     for k in keys:
         self.stanzas[stanzaName][k] = keys[k]
     self.isImportMode = False
Пример #18
0
def _getEntitiesAtomFeed(entityPath,
                         namespace=None,
                         owner=None,
                         search=None,
                         count=None,
                         offset=0,
                         sort_key=None,
                         sort_dir=None,
                         sessionKey=None,
                         uri=None,
                         hostPath=None,
                         **kwargs):
    # fallback to currently authed user
    if not owner:
        owner = auth.getCurrentUser()['name']

    # construct URI to get entities
    if not uri:
        uri = buildEndpoint(entityPath,
                            namespace=namespace,
                            owner=owner,
                            hostPath=hostPath)

    if search:
        kwargs["search"] = search

    if count != None:
        kwargs["count"] = count

    if offset:
        kwargs["offset"] = offset

    if sort_key:
        kwargs["sort_key"] = sort_key

    if sort_dir:
        kwargs["sort_dir"] = sort_dir

    # fetch list of entities
    serverResponse, serverContent = rest.simpleRequest(uri,
                                                       getargs=kwargs,
                                                       sessionKey=sessionKey,
                                                       raiseAllErrors=True)

    if serverResponse.status != 200:
        raise splunk.RESTException, (serverResponse.status,
                                     serverResponse.messages)

    atomFeed = rest.format.parseFeedDocument(serverContent)
    return atomFeed
Пример #19
0
def ping(hostPath=None, sessionKey=None):
    '''
    Pings services server and returns a bool for a users session. This method is useful for
    synchronizing an applications authentication with Splunk's services authentication.
    '''    
    uri = '/services'
    if hostPath:
        uri = splunk.mergeHostPath(hostPath) + uri
    
    try:
        serverResponse, serverContent = rest.simpleRequest(uri, sessionKey=sessionKey)
        return True
    except:
        return False
    def _refreshStanza(self, stanzaName):

        uri = self.getEndpointPath(self.name, stanzaName)

        serverResponse, serverContent = rest.simpleRequest(
            uri, sessionKey=self.sessionKey)

        #logger.debug('_refreshStanza - got stanza data back')
        keys = rest.format.parseFeedDocument(serverContent)
        keys = keys.toPrimitive()
        #logger.debug('_refreshStanza - parsed stanza data; got %s keys' % len(keys))
        self.isImportMode = True
        for k in keys:
            self.stanzas[stanzaName][k] = keys[k]
        self.isImportMode = False
Пример #21
0
def ping(hostPath=None, sessionKey=None):
    '''
    Pings services server and returns a bool for a users session. This method is useful for
    synchronizing an applications authentication with Splunk's services authentication.
    '''
    uri = '/services'
    if hostPath:
        uri = splunk.mergeHostPath(hostPath) + uri

    try:
        serverResponse, serverContent = rest.simpleRequest(
            uri, sessionKey=sessionKey)
        return True
    except:
        return False
Пример #22
0
def getEntity(entityPath,
              entityName,
              uri=None,
              namespace=None,
              owner=None,
              sessionKey=None,
              hostPath=None,
              **kwargs):
    '''
    Retrieves a generic Splunkd entity from the REST endpoint

    @param entityPath: the class of objects to retrieve
    @param entityName: the specific name of the entity to retrieve
    @param namespace: the namespace within which to look for the entities.  if None, then pull from merged
    @param owner: the owner within which to look for the entity.  defaults to current user

    '''

    # get default params
    if not owner: owner = auth.getCurrentUser()['name']

    if not uri:
        if not entityName:
            raise ValueError, "entityName cannot be empty"
        uri = buildEndpoint(entityPath,
                            entityName=entityName,
                            namespace=namespace,
                            owner=owner,
                            hostPath=hostPath)

    serverResponse, serverContent = rest.simpleRequest(uri,
                                                       getargs=kwargs,
                                                       sessionKey=sessionKey,
                                                       raiseAllErrors=True)

    if serverResponse.status != 200:
        logger.warn(
            'getEntity - unexpected HTTP status=%s while fetching "%s"' %
            (serverResponse.status, uri))

    atomEntry = rest.format.parseFeedDocument(serverContent)

    if isinstance(atomEntry, rest.format.AtomFeed):
        try:
            atomEntry = atomEntry[0]
        except IndexError, e:
            # Handle cases where no entry is found
            return None
Пример #23
0
def createConf(confName, namespace=None, owner=None, sessionKey=None, hostPath=None):
    '''
    Creates a new conf file.  Returns a conf instance of the newly created
    .conf file.
    '''
    
    uri = entity.buildEndpoint('properties', namespace=namespace, owner=owner, hostPath=hostPath)
    postargs = {'__conf': confName}
    
    status, response = rest.simpleRequest(uri, postargs=postargs, sessionKey=sessionKey, raiseAllErrors=True)
    
    # Expect 201 on creation or 200 on preexisting file (automatic handling of 303 redirect).
    if not ((status.status == 201) or (status.previous is not None and status.status == 200)):
        logger.error('createConf - unexpected server response while creating conf file "%s"; HTTP=%s' % (confName, status.status))
    
    return getConf(confName, namespace=namespace, owner=owner, sessionKey=sessionKey, hostPath=hostPath)
Пример #24
0
def getSessionKeyForTrustedUser(username, hostPath=None):
    '''
    Get a session key from the auth system
    '''

    uri = '/services/auth/trustedlogin'
    if hostPath:
        uri = splunk.mergeHostPath(hostPath) + uri
    args = {'username': username}
    
    serverResponse, serverContent = rest.simpleRequest(uri, postargs=args)

    if serverResponse.status != 200:
        logger.error('getSessionKey - unable to login; check credentials')
        rest.extractMessages(et.fromstring(serverContent))
        return None
        
    root = et.fromstring(serverContent)
    sessionKey = root.findtext('sessionKey')

    splunk.setDefault('username', username)
    splunk.setDefault('sessionKey', sessionKey)
    
    return sessionKey
Пример #25
0
def getSessionKeyForTrustedUser(username, hostPath=None):
    '''
    Get a session key from the auth system
    '''

    uri = '/services/auth/trustedlogin'
    if hostPath:
        uri = splunk.mergeHostPath(hostPath) + uri
    args = {'username': username}

    serverResponse, serverContent = rest.simpleRequest(uri, postargs=args)

    if serverResponse.status != 200:
        logger.error('getSessionKey - unable to login; check credentials')
        rest.extractMessages(et.fromstring(serverContent))
        return None

    root = et.fromstring(serverContent)
    sessionKey = root.findtext('sessionKey')

    splunk.setDefault('username', username)
    splunk.setDefault('sessionKey', sessionKey)

    return sessionKey
Пример #26
0
def getEntities(entityPath, namespace=None, owner=None, search=None, count=None, offset=0, sort_key=None, sort_dir=None , sessionKey=None, uri=None, unique_key='title', hostPath=None, **kwargs):
    '''
    Retrieves generic entities from the Splunkd endpoint, restricted to a namespace and owner context.
    
    @param entityPath: the class of objects to retrieve
    @param namespace: the namespace within which to look for the entities.  default set by splunk.getDefault('namespace')
    @param owner: the owner within which to look for the entity.  defaults to current user
    @param search: simple key=value filter
    @param offset: the starting index of the first item to return.  defaults to 0
    @param count: the maximum number of entities to return.  defaults to -1 (all)
    @param sort_key: the key to sort against
    @param sort_dir: the direction to sort (asc or desc)
    @param uri: force a specific path to the objects
    @param unique_key: specify the uniquifying key
    '''
    
    # fallback to currently authed user
    if not owner:
        owner = auth.getCurrentUser()['name']

    # construct URI to get entities
    if not uri:
        uri = buildEndpoint(entityPath, namespace=namespace, owner=owner, hostPath=hostPath)
    
    if search:
        kwargs["search"] = search
        
    if count != None:
        kwargs["count"] = count
        
    if offset:
        kwargs["offset"] = offset
        
    if sort_key:
        kwargs["sort_key"] = sort_key
        
    if sort_dir:
        kwargs["sort_dir"] = sort_dir
    
    # fetch list of entities
    serverResponse, serverContent = rest.simpleRequest(uri, getargs=kwargs, sessionKey=sessionKey, raiseAllErrors=True)
    
    if serverResponse.status != 200:
        raise splunk.RESTException, (serverResponse.status, serverResponse.messages)
        
    atomFeed = rest.format.parseFeedDocument(serverContent)

    offset = int(atomFeed.os_startIndex or -1)
    totalResults = int(atomFeed.os_totalResults or -1)
    itemsPerPage = int(atomFeed.os_itemsPerPage or -1)

    links = atomFeed.links
    
    messages = atomFeed.messages
    
    # preserves order of returned elements
    # EntityCollection is a new subclass or util.OrderedDict, it still preserves
    # the order, but it allows some additional params to be added on.
    collection = EntityCollection(None, search, count, offset, totalResults, itemsPerPage, sort_key, sort_dir, links, messages)

    for atomEntry in atomFeed:
        contents = atomEntry.toPrimitive()
        entity = Entity(entityPath, atomEntry.title, contents, namespace)
        entity.owner = atomEntry.author
        entity.createTime = atomEntry.published
        entity.updateTime = atomEntry.updated    
        entity.summary = atomEntry.summary
        entity.links = atomEntry.links
        entity.id = atomEntry.id
        entity.hostPath = hostPath
        # use the same semantics as in the C++ code: make the first item in the
        # list win if two stanzas with the same name exist
        attr = getattr(atomEntry, unique_key)
        if attr not in collection:
            collection[attr] = entity

    return collection
Пример #27
0
def setEntity(entity, sessionKey=None, uri=None, msgObj=None):
    '''
    Commits the properties of a generic entity object
    '''
    
    if not entity:
        raise Exception, 'Cannot set entity; no entity provided'
    
    if not entity.path:
        raise Exception, 'Entity does not have path defined'    

    if not entity.name:
        raise Exception, 'Entity does not have name defined'    
        
    if not entity.namespace:
        raise Exception, 'Cannot set entity without a namespace; %s' % entity.name
        
    # if editing entities that were owned by the system name, then convert to
    # to current user
    if not entity.owner:
        entity.owner = auth.getCurrentUser()['name']

    if not uri:
        # This is where we determine edit / create behavior. WoNkY!
        if len(entity.links) > 0:
            for action, link in entity.links:
                if action == 'edit':
                    uri = link
            
        if uri == None:
            uri = entity.getFullPath()
            
    postargs = entity.getCommitProperties()
    
    """
    logger.debug("*" * 25)
    logger.debug("entity: %s." % entity)
    logger.debug("uri: %s." % uri)
    logger.debug("postargs: %s." % postargs)
    logger.debug("*" * 25)
    """
    
    if not postargs:
        logger.warn('setEntity - tried to commit empty entity')
        raise Exception, 'setEntity - tried to commit empty entity'
        
    # if exists, then update by POST to own endpoint
    if rest.checkResourceExists(uri, sessionKey=sessionKey):
        
        # EAI sets entity.name to new for the new template...
        # so it will exist and not fall into the else case
        # do any of the endpoints used by Entity post back to
        # a nonexistent name for the create action?
        # EAI posts to the basePath.
        if entity.name == '_new':
            logger.debug("setting properties to create a new guy.")
            uri = entity.getBasePath()
            createName = entity.properties['name']
            logger.debug("creating %s on %s." % (createName,uri))
            entity.name = createName
                
        serverResponse, serverContent = rest.simpleRequest(uri, sessionKey=sessionKey, postargs=postargs, raiseAllErrors=True)
        if (serverResponse.status == 201):
            if msgObj:
                msgObj['messages'] = serverResponse.messages
        
        if serverResponse.status not in [200, 201]:
            logger.warn("Server did not return status 200 or 201.")
        else:
            try:
                atomFeed = rest.format.parseFeedDocument(serverContent)
                entity.id = atomFeed[0].id
            except Exception, e:
                pass
            
        return True
Пример #28
0
def setEntity(entity, sessionKey=None, uri=None, msgObj=None):
    '''
    Commits the properties of a generic entity object
    '''

    if not entity:
        raise Exception, 'Cannot set entity; no entity provided'

    if not entity.path:
        raise Exception, 'Entity does not have path defined'

    if not entity.name:
        raise Exception, 'Entity does not have name defined'

    if not entity.namespace:
        raise Exception, 'Cannot set entity without a namespace; %s' % entity.name

    # if editing entities that were owned by the system name, then convert to
    # to current user
    if not entity.owner:
        entity.owner = auth.getCurrentUser()['name']

    if not uri:
        # This is where we determine edit / create behavior. WoNkY!
        if len(entity.links) > 0:
            for action, link in entity.links:
                if action == 'edit':
                    uri = link

        if uri == None:
            uri = entity.getFullPath()

    postargs = entity.getCommitProperties()
    """
    logger.debug("*" * 25)
    logger.debug("entity: %s." % entity)
    logger.debug("uri: %s." % uri)
    logger.debug("postargs: %s." % postargs)
    logger.debug("*" * 25)
    """

    if not postargs:
        logger.warn('setEntity - tried to commit empty entity')
        raise Exception, 'setEntity - tried to commit empty entity'

    # if exists, then update by POST to own endpoint
    if rest.checkResourceExists(uri, sessionKey=sessionKey):

        # EAI sets entity.name to new for the new template...
        # so it will exist and not fall into the else case
        # do any of the endpoints used by Entity post back to
        # a nonexistent name for the create action?
        # EAI posts to the basePath.
        if entity.name == '_new':
            logger.debug("setting properties to create a new guy.")
            uri = entity.getBasePath()
            createName = entity.properties['name']
            logger.debug("creating %s on %s." % (createName, uri))
            entity.name = createName

        serverResponse, serverContent = rest.simpleRequest(
            uri, sessionKey=sessionKey, postargs=postargs, raiseAllErrors=True)
        if (serverResponse.status == 201):
            if msgObj:
                msgObj['messages'] = serverResponse.messages

        if serverResponse.status not in [200, 201]:
            logger.warn("Server did not return status 200 or 201.")
        else:
            try:
                atomFeed = rest.format.parseFeedDocument(serverContent)
                entity.id = atomFeed[0].id
            except Exception, e:
                pass

        return True
Пример #29
0
def getEntities(entityPath,
                namespace=None,
                owner=None,
                search=None,
                count=None,
                offset=0,
                sort_key=None,
                sort_dir=None,
                sessionKey=None,
                uri=None,
                unique_key='title',
                hostPath=None,
                **kwargs):
    '''
    Retrieves generic entities from the Splunkd endpoint, restricted to a namespace and owner context.
    
    @param entityPath: the class of objects to retrieve
    @param namespace: the namespace within which to look for the entities.  default set by splunk.getDefault('namespace')
    @param owner: the owner within which to look for the entity.  defaults to current user
    @param search: simple key=value filter
    @param offset: the starting index of the first item to return.  defaults to 0
    @param count: the maximum number of entities to return.  defaults to -1 (all)
    @param sort_key: the key to sort against
    @param sort_dir: the direction to sort (asc or desc)
    @param uri: force a specific path to the objects
    @param unique_key: specify the uniquifying key
    '''

    # fallback to currently authed user
    if not owner:
        owner = auth.getCurrentUser()['name']

    # construct URI to get entities
    if not uri:
        uri = buildEndpoint(entityPath,
                            namespace=namespace,
                            owner=owner,
                            hostPath=hostPath)

    if search:
        kwargs["search"] = search

    if count != None:
        kwargs["count"] = count

    if offset:
        kwargs["offset"] = offset

    if sort_key:
        kwargs["sort_key"] = sort_key

    if sort_dir:
        kwargs["sort_dir"] = sort_dir

    # fetch list of entities
    serverResponse, serverContent = rest.simpleRequest(uri,
                                                       getargs=kwargs,
                                                       sessionKey=sessionKey,
                                                       raiseAllErrors=True)

    if serverResponse.status != 200:
        raise splunk.RESTException, (serverResponse.status,
                                     serverResponse.messages)

    atomFeed = rest.format.parseFeedDocument(serverContent)

    offset = int(atomFeed.os_startIndex or -1)
    totalResults = int(atomFeed.os_totalResults or -1)
    itemsPerPage = int(atomFeed.os_itemsPerPage or -1)

    links = atomFeed.links

    messages = atomFeed.messages

    # preserves order of returned elements
    # EntityCollection is a new subclass or util.OrderedDict, it still preserves
    # the order, but it allows some additional params to be added on.
    collection = EntityCollection(None, search, count, offset, totalResults,
                                  itemsPerPage, sort_key, sort_dir, links,
                                  messages)

    for atomEntry in atomFeed:
        contents = atomEntry.toPrimitive()
        entity = Entity(entityPath, atomEntry.title, contents, namespace)
        entity.owner = atomEntry.author
        entity.createTime = atomEntry.published
        entity.updateTime = atomEntry.updated
        entity.summary = atomEntry.summary
        entity.links = atomEntry.links
        entity.id = atomEntry.id
        entity.hostPath = hostPath
        # use the same semantics as in the C++ code: make the first item in the
        # list win if two stanzas with the same name exist
        attr = getattr(atomEntry, unique_key)
        if attr not in collection:
            collection[attr] = entity

    return collection
Пример #30
0
                atomFeed = rest.format.parseFeedDocument(serverContent)
                entity.id = atomFeed[0].id
            except Exception, e:
                pass

        return True

    # otherwise, create new by POST to parent endpoint
    else:

        # ensure that a name is included in the args
        if entity.name and 'name' not in postargs:
            postargs['name'] = entity.name

        uri = entity.getBasePath()
        serverResponse, serverContent = rest.simpleRequest(
            uri, sessionKey=sessionKey, postargs=postargs, raiseAllErrors=True)

        if serverResponse.status == 201:
            if msgObj:
                msgObj['messages'] = serverResponse.messages

            try:
                atomFeed = rest.format.parseFeedDocument(serverContent)
                entity.id = atomFeed[0].id
            except Exception, e:
                pass

            return True

    # if we haven't existed, then raise
    raise splunk.RESTException, (serverResponse.status,
                entity.id = atomFeed[0].id
            except Exception, e:
                pass
            
        return True
        
        
    # otherwise, create new by POST to parent endpoint
    else:

        # ensure that a name is included in the args
        if entity.name and 'name' not in postargs:
            postargs['name'] = entity.name

        uri = entity.getBasePath()
        serverResponse, serverContent = rest.simpleRequest(uri, sessionKey=sessionKey, postargs=postargs, raiseAllErrors=True)
        
        if serverResponse.status == 201:
            if msgObj:
                msgObj['messages'] = serverResponse.messages

            try:
                atomFeed = rest.format.parseFeedDocument(serverContent)
                entity.id = atomFeed[0].id
            except Exception, e:
                pass
            
            return True
        
    # if we haven't existed, then raise
    raise splunk.RESTException, (serverResponse.status, serverResponse.messages)
def setEntity(entity, sessionKey=None, uri=None, msgObj=None, strictCreate=False, filterArguments=None):
    '''
    Commits the properties of a generic entity object
    '''
    
    logger.debug("entity.setEntity() is deprecated")
 
    if not entity:
        raise Exception, 'Cannot set entity; no entity provided'
    
    if not entity.path:
        raise Exception, 'Entity does not have path defined'    

    if not entity.name:
        raise Exception, 'Entity does not have name defined'    
        
    if not entity.namespace:
        raise Exception, 'Cannot set entity without a namespace; %s' % entity.name
        
    # if editing entities that were owned by the system name, then convert to
    # to current user
    if not entity.owner:
        entity.owner = auth.getCurrentUser()['name']

    #check if we should filter arguments based on optional/required/wildcardFields
    #only enabled for datamodel and data/ui/views for now
    if filterArguments is None:
        filterArguments = False
        if entity.path.startswith("data/models") or re.match("^\/?data\/ui\/views(\/|$)", entity.path) or re.match("^\/?saved\/searches(\/|$)", entity.path):
            filterArguments = True

    tmpEntity = None
    if not uri:
        # This is where we determine edit / create behavior. WoNkY!
        if len(entity.links) > 0:
            for action, link in entity.links:
                if action == 'edit':
                    uri = link
                    
        if uri == None:
            uri = entity.getFullPath()
            if filterArguments:
                tmpEntity = getEntity(entity.path, None, uri=uri + "/_new", sessionKey=sessionKey)

    if filterArguments and tmpEntity == None:
        tmpEntity = getEntity(entity.path, entity.name, uri=uri, sessionKey=sessionKey)

    if filterArguments:
        postargs = entity.getCommitProperties(optionalFields=tmpEntity.optionalFields, requiredFields=tmpEntity.requiredFields, wildcardFields=tmpEntity.wildcardFields, isACL=uri.endswith('/acl'), filterArguments=filterArguments)  
    else:
        postargs = entity.getCommitProperties()


    """
    logger.debug("*" * 25)
    logger.debug("entity: %s." % entity)
    logger.debug("uri: %s." % uri)
    logger.debug("postargs: %s." % postargs)
    logger.debug("*" * 25)
    """
    
    if not postargs:
        logger.warn('setEntity - tried to commit empty entity')
        raise Exception, 'setEntity - tried to commit empty entity'
        
    # if exists, then update by POST to own endpoint
    if rest.checkResourceExists(uri, sessionKey=sessionKey) and not strictCreate:
        
        # EAI sets entity.name to new for the new template...
        # so it will exist and not fall into the else case
        # do any of the endpoints used by Entity post back to
        # a nonexistent name for the create action?
        # EAI posts to the basePath.
        if entity.name == '_new':
            logger.debug("setting properties to create a new guy.")
            uri = entity.getBasePath()
            createName = entity.properties['name']
            logger.debug("creating %s on %s." % (createName,uri))
            entity.name = createName
                
        serverResponse, serverContent = rest.simpleRequest(uri, sessionKey=sessionKey, postargs=postargs, raiseAllErrors=True)
        if (serverResponse.status == 201):
            if msgObj:
                msgObj['messages'] = serverResponse.messages
        
        if serverResponse.status not in [200, 201]:
            logger.warn("Server did not return status 200 or 201.")
        else:
            try:
                atomFeed = rest.format.parseFeedDocument(serverContent)
                entity.id = atomFeed[0].id
            except Exception, e:
                pass
            
        return True
Пример #33
0
def setEntity(entity,
              sessionKey=None,
              uri=None,
              msgObj=None,
              strictCreate=False,
              filterArguments=None):
    '''
    Commits the properties of a generic entity object
    '''

    logger.debug("entity.setEntity() is deprecated")

    if not entity:
        raise Exception, 'Cannot set entity; no entity provided'

    if not entity.path:
        raise Exception, 'Entity does not have path defined'

    if not entity.name:
        raise Exception, 'Entity does not have name defined'

    if not entity.namespace:
        raise Exception, 'Cannot set entity without a namespace; %s' % entity.name

    # if editing entities that were owned by the system name, then convert to
    # to current user
    if not entity.owner:
        entity.owner = auth.getCurrentUser()['name']

    #check if we should filter arguments based on optional/required/wildcardFields
    #only enabled for datamodel and data/ui/views for now
    if filterArguments is None:
        filterArguments = False
        if entity.path.startswith("data/models") or re.match(
                "^\/?data\/ui\/views(\/|$)", entity.path) or re.match(
                    "^\/?saved\/searches(\/|$)", entity.path):
            filterArguments = True

    tmpEntity = None
    if not uri:
        # This is where we determine edit / create behavior. WoNkY!
        if len(entity.links) > 0:
            for action, link in entity.links:
                if action == 'edit':
                    uri = link

        if uri == None:
            uri = entity.getFullPath()
            if filterArguments:
                tmpEntity = getEntity(entity.path,
                                      None,
                                      uri=uri + "/_new",
                                      sessionKey=sessionKey)

    if filterArguments and tmpEntity == None:
        tmpEntity = getEntity(entity.path,
                              entity.name,
                              uri=uri,
                              sessionKey=sessionKey)

    if filterArguments:
        postargs = entity.getCommitProperties(
            optionalFields=tmpEntity.optionalFields,
            requiredFields=tmpEntity.requiredFields,
            wildcardFields=tmpEntity.wildcardFields,
            isACL=uri.endswith('/acl'),
            filterArguments=filterArguments)
    else:
        postargs = entity.getCommitProperties()
    """
    logger.debug("*" * 25)
    logger.debug("entity: %s." % entity)
    logger.debug("uri: %s." % uri)
    logger.debug("postargs: %s." % postargs)
    logger.debug("*" * 25)
    """

    if not postargs:
        logger.warn('setEntity - tried to commit empty entity')
        raise Exception, 'setEntity - tried to commit empty entity'

    # if exists, then update by POST to own endpoint
    if rest.checkResourceExists(uri,
                                sessionKey=sessionKey) and not strictCreate:

        # EAI sets entity.name to new for the new template...
        # so it will exist and not fall into the else case
        # do any of the endpoints used by Entity post back to
        # a nonexistent name for the create action?
        # EAI posts to the basePath.
        if entity.name == '_new':
            logger.debug("setting properties to create a new guy.")
            uri = entity.getBasePath()
            createName = entity.properties['name']
            logger.debug("creating %s on %s." % (createName, uri))
            entity.name = createName

        serverResponse, serverContent = rest.simpleRequest(
            uri, sessionKey=sessionKey, postargs=postargs, raiseAllErrors=True)
        if (serverResponse.status == 201):
            if msgObj:
                msgObj['messages'] = serverResponse.messages

        if serverResponse.status not in [200, 201]:
            logger.warn("Server did not return status 200 or 201.")
        else:
            try:
                atomFeed = rest.format.parseFeedDocument(serverContent)
                entity.id = atomFeed[0].id
            except Exception, e:
                pass

        return True
def getConf(confName,
            sessionKey=None,
            namespace=None,
            owner=None,
            overwriteStanzas=False,
            hostPath=None):
    '''
    Parses a logical bundle file and returns a Conf() object

    If namespace=None, then the behavior is 3.2-style, where all writes are 
    done to conf files in etc/system/local.  All reads will merge every conf
    file that is accessible in etc/system and etc/apps/*.  If a namespace is 
    provided, then writes are done in etc/apps/<namespace>/local/, and reads 
    are restricted to values in etc/apps/<namespace>/(default|local).  If
    overwriteStanzas is true, old keys in edited stanzas will not be preserved.

    For the 3.2-style reading, the endpoint uses the following priority:
        system/local
        apps/<namespace>/local
        apps/<namespace>/default
        system/default
    '''

    # fallback to current user
    if not owner:
        owner = auth.getCurrentUser()['name']

    uri = entity.buildEndpoint(entityClass='properties',
                               entityName=confName,
                               namespace=namespace,
                               owner=owner,
                               hostPath=hostPath)

    # the fillcontents arg will push all stanza keys down in 1 request instead
    # of iterating over all stanzas
    serverResponse, serverContent = rest.simpleRequest(
        uri, getargs={'fillcontents': 1}, sessionKey=sessionKey)

    if serverResponse.status != 200:
        logger.info(
            'getConf - server returned status=%s when asked for conf=%s' %
            (serverResponse.status, confName))

    # convert the atom feed into dict
    confFeed = rest.format.parseFeedDocument(serverContent)
    stanzas = confFeed.toPrimitive()

    # create Conf/Stanzas
    output = Conf(confName,
                  namespace=namespace,
                  owner=owner,
                  overwriteStanzas=overwriteStanzas)
    output.sessionKey = sessionKey
    output.isImportMode = True
    for name in stanzas:
        stanza = output.createStanza(name)
        stanza.needsPopulation = False
        for k in stanzas[name]:
            if stanzas[name][k] == None:
                stanza[k] = ''
            else:
                stanza[k] = stanzas[name][k]

    output.isImportMode = False

    return output