The sample configuration program uses the Admin APIs to construct a MarkLogic Server configuration that supports the Oscars Explorer application described in Using the Oscars Sample Application in the Application Builder Developer's Guide.
The sample configuration program is located in MarkLogic/Samples/admin
. The objective of this sample program is to educate users on the use of the Admin APIs. Though many parts of the code can be reused, the modules in this example are structured to highlight the use of the Admin API functions. You, however, may want to structure your program to hide the complexities of the APIs and define all of your configuration variables in a separate module or XML file, so that all changes to the configuration can be made in one place.
The topics in this section are:
Before you can run the Sample Configuration Program, you must create an HTTP App Server that has a root path to the location of the program files.
To create an App Server for the Sample Configuration Program, do the following:
Samples/admin
and assign it a unique port number, such as port 8055
in this example:install.xqy
file at the App Server URL. For example: http://localhost:8055/install.xqy
Server is Configured Done loading XML data into Sample-Database Done loading application data into Sample-Modules Role IDs are: 1067450794701390527 10780693773632192097 8870937581372109438 User IDs are: 3884989588766400714 Users and Roles are Configured
http://localhost:8016
. You should see the Oscars Explorer screen:The sample configuration program consists of the modules illustrated below:
load-data.xqy
modules to create the sample configuration and load the data into the databases.The install.xqy
module is the main module that calls the functions in the configure-server.xqy, configure-security.xqy, and loadData.xqy
modules to configure the MarkLogic Server and load the data needed to support the Oscars Explorer application. The functions in the configure-security.xqy and loadData.xqy
modules are executed against their respective databases by calling them within xdmp:eval functions with the <database>
option. For more detail on executing queries in a database other than that assigned to the App Server, see Executing Queries in Select Databases.
The loadData.xqy
module is needed to load the application and content data into the databases, but its implementation is not within the scope of this guide.
xquery version "1.0-ml"; import module namespace conf-server = "http://marklogic.com/sampleConfig/conf-server" at "configure-server.xqy"; import module namespace grp="http://marklogic.com/sampleConfig/groups" at "groups.xqy"; import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy"; (: Get the cluster configuration :) let $config := admin:get-configuration() (: Get the Security database used by the Admin AppServer :) let $securityDB := grp:get-security-db($config, "Default", "Admin") (: Create and configure the databases and server :) let $config := conf-server:create-forests($config) let $config := conf-server:create-databases($config) let $config := conf-server:create-server($config) (: These variables define the functions that create new roles and users and load the data into the databases. Each function is then executed by xdmp:eval against a specific database :) let $create-roles:= ' xquery version "1.0-ml"; import module namespace conf-security= "http://marklogic.com/sampleConfig/conf-security" at "configure-security.xqy"; conf-security:configure-roles()' let $create-users := ' xquery version "1.0-ml"; import module namespace conf-security= "http://marklogic.com/sampleConfig/conf-security" at "configure-security.xqy"; conf-security:configure-users()' let $load-XML := ' xquery version "1.0-ml"; import module namespace load-data = "http://marklogic.com/sampleConfig/load-data" at "loadData.xqy"; load-data:load-sample-XML( "C:/Program Files/MarkLogic/Assets/appbuilder/templates/oscars/data")' let $load-modules := ' xquery version "1.0-ml"; import module namespace setup = "http://marklogic.com/sampleConfig/setup-lib" at "setup-library.xqy"; import module namespace load-data = "http://marklogic.com/sampleConfig/load-data" at "loadData.xqy"; load-data:load-sample-module($setup:LOADDATA)' return ( admin:save-configuration($config), "Server is Configured", (: Call the above functions in their respective databases :) xdmp:eval( $load-XML, (), <options xmlns="xdmp:eval"> <database>{xdmp:database("Sample-Database")}</database> </options>), xdmp:eval( $load-modules, (), <options xmlns="xdmp:eval"> <database>{xdmp:database("Sample-Modules")}</database> </options>), "Role IDs are:", xdmp:eval( $create-roles, (), <options xmlns="xdmp:eval"> <database>{$securityDB}</database> </options>), "User IDs are:", xdmp:eval( $create-users, (), <options xmlns="xdmp:eval"> <database>{$securityDB}</database> </options>), "Users and Roles are Configured" )
The uninstall.xqy
module is the main module that calls the functions in the configure-server.xqy and configure-security.xqy modules to remove the MarkLogic Server objects created by the install.xqy module. The functions in the configure-security.xqy module are executed against their respective databases by calling them within xdmp:eval functions with the <database>
option.
xquery version "1.0-ml"; import module namespace conf-server = "http://marklogic.com/sampleConfig/conf-server" at "configure-server.xqy"; import module namespace grp="http://marklogic.com/sampleConfig/groups" at "groups.xqy"; import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy"; let $remove-users := ' xquery version "1.0-ml"; import module namespace conf-security = "http://marklogic.com/sampleConfig/conf-security" at "configure-security.xqy"; conf-security:remove-users()' let $remove-roles := ' xquery version "1.0-ml"; import module namespace conf-security = "http://marklogic.com/sampleConfig/conf-security" at "configure-security.xqy"; conf-security:remove-roles()' let $config := admin:get-configuration() let $securityDB := grp:get-security-db($config, "Default", "Admin") return ( xdmp:eval($remove-roles, (), <options xmlns="xdmp:eval"> <database>{$securityDB}</database> </options>), xdmp:eval($remove-users, (), <options xmlns="xdmp:eval"> <database>{$securityDB}</database> </options>), "Removed Users and Roles", conf-server:remove-config(), "Removed Server Configuration" )
The configure-server.xqy
module defines the high-level, configuration-specific functions that call the more 'generic' functions in the groups.xqy and databases.xqy modules to create, configure, and delete the forests, databases and app server used by the Oscars Explorer application.
The functions in this module are:
Before defining the functions, we define this module's namespace as conf-server
and import the following modules:
xquery version "1.0-ml"; (: Create/Remove Server/Database Configuration :) module namespace conf-server = "http://marklogic.com/sampleConfig/conf-server"; import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy"; import module namespace db= "http://marklogic.com/sampleConfig/database" at "databases.xqy"; import module namespace grp= "http://marklogic.com/sampleConfig/groups" at "groups.xqy"; import module namespace setup= "http://marklogic.com/sampleConfig/setup-lib" at "setup-library.xqy";
The create-forests
function calls the functions in the databases.xqy module to create the forests:
declare function create-forests($config as element(configuration)) { try { (: Create forests :) let $config := db:create-forest( $config, "SampleDB-Forest") let $config := db:create-forest( $config, "SampleModules-Forest") (: Save and return the configuration :) return ( admin:save-configuration($config), $config ) } catch($e) { setup:log($e) } };
The create-databases
function calls the functions in the databases.xqy module to create and configure the databases to hold the application and content data for the Oscars Explorer application.
declare function create-databases($config as element(configuration)) { try { (: Create databases :) let $config := db:create-database( $config, "Sample-Database") let $config := db:create-database( $config, "Sample-Modules") (: Attach forests to databases :) let $config := db:attach-forests( $config, "Sample-Database", "SampleDB-Forest") let $config :=db:attach-forests( $config, "Sample-Modules", "SampleModules-Forest") (: Add a 'wiki-suggest' field to the Sample-Database :) let $config := db:add-field( $config, "Sample-Database", "wiki-suggest") (: Add included elements to 'wiki-suggest' field :) let $config := db:add-field-included( $config, "Sample-Database", "wiki-suggest", "name") let $config := db:add-field-included( $config, "Sample-Database", "wiki-suggest", "film-title") (: Add indexes to the Sample-Database :) let $config := db:add-range-element-index( $config, "Sample-Database", "string", "http://marklogic.com/wikipedia", "name") let $config := db:add-range-element-index( $config, "Sample-Database", "string", "http://marklogic.com/wikipedia", "film-title") let $config := db:add-range-element-attribute-index( $config, "Sample-Database", "gYear", "http://marklogic.com/wikipedia", "nominee", "", "year", "") let $config := db:add-range-element-attribute-index( $config, "Sample-Database", "string", "http://marklogic.com/wikipedia", "nominee", "", "award", "http://marklogic.com/collation/") let $config := db:add-range-element-attribute-index( $config, "Sample-Database", "string", "http://marklogic.com/wikipedia", "nominee", "", "winner", "http://marklogic.com/collation/") (: Save and return the configuration :) return ( admin:save-configuration($config), $config ) } catch($e) { setup:log($e) } };
The create-server
function calls the functions in the groups.xqy module to create and configure an HTTP App Server to support the Oscars Explorer application. Note that, rather than define the app server settings as parameters, the create-server
function in the groups.xqy module parses the settings from the $server-config
XML node defined in this function.
declare function create-server($config as element(configuration)) { try { (: Create a node containing the basic server settings :) let $server-config := <http-server> <name>Sample-Server</name> <port>8016</port> <root>application/</root> <modules>Sample-Modules</modules> <database>Sample-Database</database> </http-server> (: Create the server :) let $config := grp:create-server( $config, $server-config, "Default") (: Set server error handler and url rewriter :) let $config := grp:set-error-handler( $config, "Default", "Sample-Server", "error.xqy") let $config := grp:set-url-rewriter( $config, "Default", "Sample-Server", "rewrite.xqy") (: Save and return the configuration :) return ( admin:save-configuration($config), $config ) } catch($e) { setup:log($e) } };
The remove-config
function calls functions in the groups.xqy and databases.xqy modules to remove the forests, databases, and app server created by the create-server
and create-databases
functions.
declare function remove-config() { try { (: Remove the app server :) let $config := admin:get-configuration() let $config := grp:delete-server( $config, "Sample-Server", "Default") let $hosts1 := admin:save-configuration-without-restart($config) (: Remove the databases :) let $config := db:delete-database($config, "Sample-Database") let $config := db:delete-database($config, "Sample-Modules") let $hosts2 := admin:save-configuration-without-restart($config) (: Remove the forests :) let $config := db:delete-forest($config, "SampleDB-Forest") let $config := db:delete-forest($config, "SampleModules-Forest") (: Save the configuration and restart MarkLogic server :) return (admin:save-configuration($config), if ($hosts1, $hosts2) then ( "Restarting Hosts -- wait until restart has completed before accessing MarkLogic Server", admin:restart-hosts(($hosts1, $hosts2)) ) else () ) } catch($e) { setup:log($e) } };
The groups.xqy
module defines functions that call the admin
functions that create, configure, and remove groups and app servers. The functions in this module are more 'generic' than the configuration-specific functions in the configure-server.xqy module that call them. Consequently, the functions in this module could be applied to a variety of configurations.
Each function in this module first checks for the presence of the object it is to create or remove before taking any action. This is done to enable partial changes to be made to the configuration without the entire transaction failing, as described in Making Transactions Idempotent.
Before defining the functions, we define this module's namespace as grp
and import the following modules:
xquery version "1.0-ml"; module namespace grp = "http://marklogic.com/sampleConfig/groups"; declare namespace error = "http://marklogic.com/xdmp/error"; import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy"; import module namespace setup = "http://marklogic.com/sampleConfig/setup-lib" at "setup-library.xqy";
The create-group
function first checks to see whether the specified groups exists. If not, it calls the admin:group-create function to create the new group. This function is not called any function in the configure-server.xqy module, but could be used by other high-level modules to create another configuration.
declare function create-group( $config as element(configuration), $NewGroup as xs:string) { try { let $log := setup:log(fn:concat("creating group :", $NewGroup)) (: Get all of the existing groups :) let $ExistingGroups := for $id in admin:get-group-ids($config) return admin:group-get-name($config, $id) (: Check to see if group already exists. If not, create new group :) let $config := if ($NewGroup = $ExistingGroups) then $config else admin:group-create($config, $NewGroup) return $config } catch($e) { setup:log($e) } };
The create-server
function first checks to see whether the specified app server exists. If not, it calls the admin
functions to create and configure the new app server. The app server type (HTTP, WebDAV, XDBC) is specified by the root element of the $server-config
node passed from the configure-server.xqy module.
declare function create-server( $config as element(configuration), $server as node(), $group-name as xs:string) { try { let $group-id := admin:group-get-id($config, $group-name) let $NewServer := fn:data($server/name) let $root := fn:data($server/root) let $port := xs:integer(fn:data($server/port)) let $modules := fn:data($server/modules) let $module-id := if($modules eq "filesystem") then 0 else xdmp:database($modules) let $database-id := xdmp:database(fn:data($server/database)) (: Get all of the existing servers :) let $ExistingServers := for $id in admin:get-appserver-ids($config) return admin:appserver-get-name($config, $id) (: Check to see if server already exists. If not, create new server :) let $config := if ($NewServer = $ExistingServers) then $config else if (fn:name($server) eq "http-server") then create-http-server( $config, $group-id, $NewServer, $root, $port, $module-id, $database-id) else if(fn:name($server) eq "xdbc-server") then create-xdbc-server( $config, $group-id, $NewServer, $root, $port, $module-id, $database-id) else if(fn:name($server) eq "webdav-server") then create-webdav-server( $config, $group-id, $NewServer, $root, $port, $database-id) else () return $config } catch($e) { setup:log($e) } }; declare function create-xdbc-server( $config as element(configuration), $group-id, $server-name, $root, $port, $module-id, $database-id) { try { let $config := admin:xdbc-server-create( $config, $group-id, $server-name, $root, $port, $module-id, $database-id) let $log := setup:log(fn:concat( "Creating XDBC server ", $server-name)) return $config } catch($e) { setup:log($e) } }; declare function create-webdav-server( $config as element(configuration), $group-id, $server-name, $root, $port, $database-id) { try { let $config := admin:webdav-server-create( $config, $group-id, $server-name, $root, $port, $database-id) let $log := setup:log(fn:concat( "Creating WebDAV server ", $server-name)) return $config } catch($e) { setup:log($e) } }; declare function create-http-server( $config as element(configuration), $group-id, $server-name, $root, $port, $module-id, $database-id) { try { let $config := admin:http-server-create( $config, $group-id, $server-name, $root, $port, $module-id, $database-id) let $log := setup:log(fn:concat( "Creating HTTP server ", $server-name)) return $config } catch($e) { setup:log($e) } };
The functions in this section configure the new app server. The admin:appserver-get-id function is used to get the id of the app server from the configuration. This enables the calling functions in the configure-server.xqy module to configure the newly created app server before saving the configuration to MarkLogic Server. For more details on the operation of admin:appserver-get-id and similar functions, see Creating and Configuring Objects in a Single Transaction.
The following functions set the error handler and URL rewriter for the app server. As with all other functions in this module, we first check for the presence of an object before creating it.
declare function set-error-handler( $config as element(configuration), $group-name as xs:string, $server-name as xs:string, $ErrorHandler as xs:string) { try { let $appserver-id := admin:appserver-get-id( $config, admin:group-get-id($config, $group-name), $server-name) (: Get all of the existing error handlers for this server :) let $ExistingHandler := admin:appserver-get-error-handler( $config, $appserver-id) (: Check to see if error handler is already set. If not, set error handler :) let $config := if ($ErrorHandler = $ExistingHandler) then $config else admin:appserver-set-error-handler( $config, $appserver-id, $ErrorHandler) let $log := setup:log(fn:concat( "Setting error handler ", $server-name)) return $config } catch($e) { setup:log($e) } }; declare function set-url-rewriter( $config as element(configuration), $group-name as xs:string, $server-name as xs:string, $URLrewriter as xs:string) { try { let $appserver-id := admin:appserver-get-id( $config, admin:group-get-id($config, $group-name), $server-name) (: Get all of the existing URL writers for this server :) let $ExistingURLrewriterr := admin:appserver-get-url-rewriter( $config, $appserver-id) (: Check to see if URL writer is already set. If not, set URL writer :) let $config := if ($URLrewriter = $ExistingURLrewriterr) then $config else admin:appserver-set-url-rewriter( $config, $appserver-id, $URLrewriter) let $log := setup:log(fn:concat( "Setting URL rewriter ", $server-name)) return $config } catch($e) { setup:log($e) } };
Because there may be more than one database named 'Security,' the get-security-db
function is used by the install.xqy and uninstall.xqy modules to identify the Security database used by the Admin
app server.
declare function get-security-db( $config as element(configuration), $group-name as xs:string, $server-name as xs:string) { try { let $appserver-id := admin:appserver-get-id( $config, admin:group-get-id($config, $group-name), $server-name) return admin:appserver-get-database( $config, $appserver-id) } catch($e) { setup:log($e) } };
The delete-group
function first checks to see whether the specified groups exists. If so, it calls the admin:group-delete function to remove the group. This function is not called any function in the configure-server.xqy module, but could be used by other high-level modules to remove a group from the configuration.
declare function delete-group( $config as element(configuration), $GroupName as xs:string) { try { let $group := xdmp:group($GroupName) (: Get all of the existing groups :) let $ExistingGroups := for $id in admin:get-group-ids($config) return admin:group-get-name($config, $id) (: Check to see if group exists. If so, remove the group :) let $config := if ($GroupName = $ExistingGroups) then admin:group-delete($config, $group) else $config return $config } catch($e) { setup:log($e) } };
The delete-server
function first checks to see whether the specified app server exists. If so, it calls the admin:appserver-delete function to remove the app server.
declare function delete-server( $config as element(configuration), $ServerName as xs:string, $group-name as xs:string) { try { let $group := xdmp:group($group-name) (: Get all of the existing servers :) let $ExistingServers := for $id in admin:get-appserver-ids($config) return admin:appserver-get-name($config, $id) (: Check to see if server exists. If so, remove the server :) let $config := if ($ServerName = $ExistingServers) then admin:appserver-delete( $config, admin:appserver-get-id( $config, $group, $ServerName)) else $config return $config } catch($e) { setup:log($e) } };
The set-host
function calls the admin:host-set-group
function to set the host for the specified group. This function is not called any function in the configure-server.xqy module, but could be used by other high-level modules to create another configuration.
declare function set-host( $config as element(configuration), $group-name as xs:string, $host-name as xs:string) { try { let $group := xdmp:group($group-name) let $host := xdmp:host($host-name) return admin:host-set-group( $config, $host, $group) } catch($e) { setup:log($e) } };
The databases.xqy
module defines functions that call the admin
functions that create, configure, and remove the forests and databases. The functions in this module are more 'generic' than the configuration-specific functions in the configure-server.xqy module that call them. Consequently, the functions in this module could be applied to a variety of configurations.
The functions in this module are:
Each function in this module first checks for the presence of the object it is to create or remove before taking any action. This is done to enable partial changes to be made to the configuration without the entire transaction failing, as described in Making Transactions Idempotent.
Before defining the functions, we define this module's namespace as db
and import the following modules:
xquery version "1.0-ml"; module namespace db = "http://marklogic.com/sampleConfig/database"; declare namespace error = "http://marklogic.com/xdmp/error"; declare namespace xdmpdb = "http://marklogic.com/xdmp/database"; import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy"; import module namespace setup = "http://marklogic.com/sampleConfig/setup-lib" at "setup-library.xqy";
The create-forest
function first checks to see whether the specified forest exists. If not, it calls the admin:forest-create function to create the new forest.
declare function create-forest( $config as element(configuration), $NewForest as xs:string) { try { (: Get all of the existing forests :) let $ExistingForests := for $id in admin:get-forest-ids($config) return admin:forest-get-name($config, $id) (: Check to see if forest already exists. If not, create new forest :) let $config := if ($NewForest = $ExistingForests) then $config else admin:forest-create( $config, $NewForest, xdmp:host(), "") return $config } catch($e) { setup:log($e) } };
The create-forest
function first checks to see whether the specified database exists. If not, it calls the admin:database-create function to create and configure the new database.
declare function create-database( $config as element(configuration), $NewDatabase as xs:string) { try { let $security-db := admin:database-get-id($config, "Security") let $schema-db := admin:database-get-id($config, "Schemas") (: Get all of the existing databases :) let $ExistingDatabases := for $id in admin:get-database-ids($config) return admin:database-get-name($config, $id) (: Check to see if database already exists. If not, create new database :) let $config := if ($NewDatabase = $ExistingDatabases) then $config else admin:database-create( $config, $NewDatabase, $security-db, $schema-db) return $config } catch($e) { setup:log($e) } };
The functions in this section configure the new database. The admin:database-get-id function is used to get the id of the database from the configuration. This enables the calling functions in the configure-server.xqy module to attach the forests and configure the newly created database before saving the configuration to MarkLogic Server. For more details on the operation of admin:database-get-id and similar functions, see Creating and Configuring Objects in a Single Transaction.
The following functions attached the forests and add fields and indexes to the database. As with all other functions in this module, we first check for the presence of an object before creating it.
(: Attach forest to database function :) declare function attach-forests( $config as element(configuration), $dbname as xs:string, $forest as xs:string) { try { (: Get all of the forests attached to this database :) let $AttachedForests := admin:forest-get-name( $config, (admin:database-get-attached-forests( $config, admin:database-get-id($config, $dbname)) )) (: Check to see if forest is already attached to the database. If not, attach the forest to the database :) let $config := if ($forest = $AttachedForests) then $config else admin:database-attach-forest( $config, admin:database-get-id($config, $dbname), admin:forest-get-id($config, $forest) ) return $config } catch($e) { setup:log($e) } }; (: Add field to database function :) declare function add-field( $config as element(configuration), $dbname as xs:string, $field as xs:string) { try { let $dbid := admin:database-get-id($config, $dbname) (: Construct a specification for this field :) let $fieldspec := admin:database-field($field, fn:false()) (: Get all of the existing fields for this database :) let $ExistingFields := fn:data(admin:database-get-fields( $config, $dbid)/xdmpdb:field-name) (: Check to see if field already exists for this database. If not, add the field :) let $config := if ($field = $ExistingFields) then $config else admin:database-add-field($config, $dbid, $fieldspec) return $config } catch($e) { setup:log($e) } }; (: Add include element to field function :) declare function add-field-included( $config as element(configuration), $dbname as xs:string, $field as xs:string, $included as xs:string) { try { let $dbid := admin:database-get-id( $config, $dbname) (: Construct a specification for this include element :) let $fieldspec := admin:database-included-element( "http://marklogic.com/wikipedia", $included, 1.0, "", "", "") (: Get all of the existing included elements for this field:) let $ExistingIncludes := fn:data(admin:database-get-field-included-elements( $config, $dbid, $field)/xdmpdb:localname) (: Check to see if field already has the included elements. If not, add the included elements to the field :) let $config := if ($included = $ExistingIncludes) then $config else admin:database-add-field-included-element( $config, $dbid, $field, $fieldspec) return $config } catch($e) { setup:log($e) } }; (: Add range element index to database function :) declare function add-range-element-index( $config as element(configuration), $dbname as xs:string, $type as xs:string, $namespace-uri as xs:string, $localname as xs:string) { try { let $dbid := admin:database-get-id( $config, $dbname) (: Define a new range element index :) let $range-index := admin:database-range-element-index( $type, $namespace-uri, $localname, "http://marklogic.com/collation/", fn:false() ) (: Get all of the existing range element indexes for this database :) let $ExistingREindexes := fn:data(admin:database-get-range-element-indexes( $config, $dbid)/xdmpdb:localname) (: Check to see if range element index already exists for this database. If not, add the range element index :) let $config := if ($localname = $ExistingREindexes) then $config else admin:database-add-range-element-index( $config, $dbid, $range-index) return $config } catch($e) { setup:log($e) } }; (: Add range element attribute index to database function :) declare function add-range-element-attribute-index( $config as element(configuration), $dbname as xs:string, $type as xs:string, $parent-namespace-uri as xs:string, $parent-localname as xs:string, $namespace-uri as xs:string, $localname as xs:string, $collation as xs:string) { try { let $dbid := admin:database-get-id( $config, $dbname) (: Define a new range element attribute index :) let $range-attribute-index := admin:database-range-element-attribute-index( $type, $parent-namespace-uri, $parent-localname, $namespace-uri, $localname, $collation, fn:false() ) (: Get all of the existing range element attribute indexes for this database :) let $ExistingREAindexes := fn:data(admin:database-get-range-element-attribute-indexes( $config, $dbid)/xdmpdb:localname) (: Check to see if range element attribute index already exists for this database. If not, add the range element attribute index. :) let $config := if ($localname = $ExistingREAindexes) then $config else admin:database-add-range-element-attribute-index( $config, $dbid, $range-attribute-index) return $config } catch($e) { setup:log($e) } };
The delete-database
function first checks to see whether the specified database exists. If so, it calls the admin:database-delete function to remove the database.
declare function delete-database( $config as element(configuration), $DatabaseName as xs:string) { try { let $database := admin:database-get-id($config, $DatabaseName) (: Get all of the existing databases :) let $ExistingDatabases := for $id in admin:get-database-ids($config) return admin:database-get-name($config, $id) (: Check to see if database exists. If so, remove the database :) let $config := if ($DatabaseName = $ExistingDatabases) then admin:database-delete( $config, admin:database-get-id($config, $DatabaseName)) else $config return $config } catch($e) { setup:log($e) } };
The delete-forest
function first checks to see whether the specified forest exists. If so, it calls the admin:forest-delete function to remove the forest.
declare function delete-forest( $config as element(configuration), $ForestName as xs:string) { try { let $forest := admin:forest-get-id($config, $ForestName) (: Get all of the existing forests :) let $ExistingForests := for $id in admin:get-forest-ids($config) return admin:forest-get-name($config, $id) (: Check to see if forest exists. If so, remove the forest :) let $config := if ($ForestName = $ExistingForests) then admin:forest-delete( $config, admin:forest-get-id($config, $ForestName), fn:true()) else $config return $config } catch($e) { setup:log($e) } };
Calls the functions in the security
module to create new roles and users. Unlike the configure-server.xqy, which calls the admin
functions indirectly through the groups.xqy and databases.xqy modules, this module calls the security
functions directly. Consequently, the functions in this module are specific to the configuration.
The functions in this module are:
Each function in this module first checks for the presence of the object it is to create or remove before taking any action. This is done to enable partial changes to be made to the configuration without the entire transaction failing, as described in Making Transactions Idempotent.
Before defining the functions, we define this module's namespace as conf-security
and import the following modules:
xquery version "1.0-ml"; module namespace conf-security= "http://marklogic.com/sampleConfig/conf-security"; declare namespace error="http://marklogic.com/xdmp/error"; import module namespace setup= "http://marklogic.com/sampleConfig/setup-lib" at "setup-library.xqy"; import module namespace sec="http://marklogic.com/xdmp/security" at "/MarkLogic/security.xqy";
The configure-roles
function first checks to see whether the specified roles exist. If not, it calls the sec:create-role functions to create the new roles.
declare function configure-roles() { try { (: Get all of the existing roles :) let $ExistingRoles := fn:data(/sec:role/sec:role-name) (: Check to see if role already exists. If not, create new role :) return ( if ("Sample" = $ExistingRoles) then " Sample role already exists" else sec:create-role( "Sample", "Temporary access", ("filesystem-access"), (xdmp:permission("security", "read")), ("testDocument")), if ("Developer" = $ExistingRoles) then " Developer role already exists" else sec:create-role( "Developer", "Developer access", ("filesystem-access", "pipeline-execution"), (xdmp:permission("security", "read"), xdmp:permission("security", "update")), ("testDocument")), if ("Tester" = $ExistingRoles) then " Tester role already exists" else sec:create-role( "Tester", "Tester access", ("filesystem-access"), (), ("testDocument")) ) } catch($e) { setup:log($e) } };
The configure-users
function first checks to see whether the specified user exists. If not, it calls the sec:create-user
function to create the new user and assign it a role created by the previous configure-roles function.
declare function configure-users() { try { (: Get all of the existing users :) let $ExistingUsers := fn:data(/sec:user/sec:user-name) (: Check to see if user already exists. If not, create new user :) return ( if ("Jim" = $ExistingUsers) then " User Jim already exists" else sec:create-user( "Jim", "Jim the temp", "newguy", "Sample", (xdmp:permission("security", "read")), ("http://marklogic.com/dev_modules")) ) } catch($e) { setup:log($e) } };
The remove-users
function first checks to see whether the specified user exists. If so, it calls the sec:remove-user function to remove the user.
declare function remove-users() { try { (: Get all of the existing users :) let $ExistingUsers := fn:data(/sec:user/sec:user-name) (: Check to see if user exists. If so, remove user :) return ( if ("Jim" = $ExistingUsers) then sec:remove-user("Jim") else () ) } catch($e) { setup:log($e) } };
The remove-roles
function first checks to see whether the specified roles exist. If so, it calls the sec:remove-role functions to remove the roles.
declare function remove-roles() { try { (: Get all of the existing roles :) let $ExistingRoles := fn:data(/sec:role/sec:role-name) (: Check to see if role exists. If so, remove role :) return ( if ("Sample" = $ExistingRoles) then sec:remove-role("Sample") else (), if ("Developer" = $ExistingRoles) then sec:remove-role("Developer") else (), if ("Tester" = $ExistingRoles) then sec:remove-role("Tester") else () ) } catch($e) { setup:log($e) } };