UNPKG

node-red-contrib-ibm-igc

Version:

Node-RED nodes for integrating with IBM Information Governance Catalog

490 lines (464 loc) 19.8 kB
<!-- Copyright 2017 IBM Corp. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <script type="text/x-red" data-template-name="ibm-igc"> <div class="form-row"> <label for="node-config-input-host"><i class="fa fa-bookmark"></i> Host</label> <input class="input-append-left" type="text" id="node-config-input-host" placeholder="your-server.com"> </div> <div class="form-row"> <label for="node-config-input-port"><i class="fa fa-circle-o"></i> Port</label> <input class="input-append-left" type="text" id="node-config-input-port" placeholder="9445"> </div> <div class="form-row"> <label for="node-config-input-username"><i class="fa fa-user"></i> Username</label> <input type="text" id="node-config-input-username"> </div> <div class="form-row"> <label for="node-config-input-pass"><i class="fa fa-lock"></i> Password</label> <input type="password" id="node-config-input-pass"> </div> <div class="form-row"> <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label> <input type="text" id="node-config-input-name" placeholder="Name"> </div> </script> <script type="text/javascript"> "use strict"; RED.nodes.registerType("ibm-igc",{ category: "config", color: "rgb(114, 199, 231)", defaults: { host: { value: "", required: true }, port: { value: "9445", required: true, validate: RED.validators.number() }, name: { value: "" } }, credentials: { username: { type: "text" }, pass: { type: "password" } }, label: function() { return this.host + ":" + this.port; } }); </script> <script type="text/x-red" data-template-name="IGC in"> <div class="form-row" id="node-input-external-details"> <label for="node-input-server"><i class="fa fa-bookmark"></i> Server</label> <input type="text" id="node-input-server"> </div> <div class="form-row"> <label for="node-input-search"><i class="fa fa-search"></i> Retrieve by</label> <select id="node-input-search" style="width:68%;"> <option value="_id_">RID</option> <option value="_url_">URL Passthrough</option> <option value="_query_">Complex Query</option> </select> </div> <div id="node-search-query-form" class="form-row" style="position: relative; margin-bottom: 0px;"> <label for="node-input-query"><i class="fa fa-search"></i> Query</label> <input type="hidden" id="node-input-query" autofocus="autofocus"> </div> <div id="node-search-query-editor-form" class="form-row node-text-editor-row"> <div style="height: 150px; min-height:75px;" class="node-text-editor" id="node-input-query-editor" ></div> </div> <div id="node-search-url-form" class="form-row"> <label for="node-input-url"><i class="fa fa-reply"></i> URL</label> <input type="text" id="node-input-url" placeholder="/ibm/iis/igc-rest/v1/assets/f4951817.e469fa50.kai5lu1ko.1ndscq5.0s5v4b.ql8e8cmignkcq89ic0ke4" style="width:65%;"> </div> <div id="node-search-rid-form" class="form-row"> <label for="node-input-rid"><i class="fa fa-barcode"></i> RID</label> <input type="text" id="node-input-rid" placeholder="f4951817.e469fa50.kai5lu1ko.1ndscq5.0s5v4b.ql8e8cmignkcq89ic0ke4" style="width:65%;"> </div> <div id="node-search-ridtype-form" class="form-row"> <label for="node-input-ridtype"><i class="fa fa-cubes"></i> Type</label> <input type="text" id="node-input-ridtype" placeholder="term" style="width:65%;"> </div> <div id="node-search-ridproperties-form" class="form-row"> <label for="node-input-ridproperties"><i class="fa fa-check-square-o"></i> Properties</label> <input type="text" id="node-input-ridproperties" placeholder="name, short_description" style="width:65%;"> </div> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> <input type="text" id="node-input-name" placeholder="Name" style="width:65%;"> </div> </script> <script type="text/x-red" data-template-name="IGC out"> <div class="form-row" id="node-input-external-details"> <label for="node-input-server"><i class="fa fa-bookmark"></i> Server</label> <input type="text" id="node-input-server"> </div> <div class="form-row"> <label for="node-input-operation"><i class="fa fa-wrench"></i> Operation</label> <select id="node-input-operation" style="width:68%;"> <option value="create">create</option> <option value="update">update</option> <option value="delete">delete</option> </select> </div> <div id="node-save-rid-form" class="form-row"> <label for="node-input-rid"><i class="fa fa-barcode"></i> RID</label> <input type="text" id="node-input-rid" style="width:65%;"> </div> <div id="node-save-assettype-form" class="form-row"> <label for="node-input-assettype"><i class="fa fa-cubes"></i> Type</label> <input type="text" id="node-input-assettype" style="width:65%;"> </div> <div id="node-save-details-form" class="form-row" style="position: relative; margin-bottom: 0px;"> <label for="node-input-details"><i class="fa fa-code"></i> Details</label> <input type="hidden" id="node-input-details" autofocus="autofocus"> </div> <div id="node-save-details-editor-form" class="form-row node-text-editor-row"> <div style="height: 150px; min-height:75px;" class="node-text-editor" id="node-input-details-editor" ></div> </div> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> <input type="text" id="node-input-name" placeholder="Name" style="width:65%;"> </div> </script> <script type="text/javascript"> "use strict"; RED.nodes.registerType("IGC in", { category: "storage-input", color: "rgb(114, 199, 231)", defaults: { name: { value: "" }, server: { type: "ibm-igc", required: true }, search: { value: "_query_", required: true }, query: { value: "{\n\t\"properties\": [\"name\"],\n\t\"types\": [\"term\"],\n\t\"where\": {\n\t\t\"operator\": \"and\",\n\t\t\"conditions\": [{\n\t\t\t\"property\": \"modified_on\",\n\t\t\t\"operator\": \">=\",\n\t\t\t\"value\": \"1483232400\"\n\t\t}]\n\t}\n}" }, url: { value: "" }, rid: { value: "" }, ridtype: { value: "" }, ridproperties: { value: "" } }, inputs: 1, outputs: 1, icon: "ibm-igc.png", align: "left", label: label, labelStyle: function() { return this.name ? "node_label_italic" : ""; }, oneditprepare: oneditprepareIn, oneditsave: function() { $("#node-input-query").val(this.editor.getValue()); delete this.editor; } }); function oneditprepareIn() { const node = this; const searchBySelect = $('#node-input-search'); const propertiesIn = $('#node-input-ridproperties'); const ridForm = $('#node-search-rid-form'); const typeForm = $('#node-search-ridtype-form'); const propertiesForm = $('#node-search-ridproperties-form'); const urlForm = $('#node-search-url-form'); const queryForm = $('#node-search-query-form'); const queryEditor = $('#node-search-query-editor-form'); searchBySelect.change(function() { const searchBy = searchBySelect.val(); if (searchBy === "_id_") { makeTypeRequiredIfPropertiesHasValues(); node._def.defaults.ridproperties.required = false; ridForm.show(); typeForm.show(); propertiesForm.show(); urlForm.hide(); queryForm.hide(); queryEditor.hide(); } else if (searchBy === "_url_" ) { node._def.defaults.ridtype.required = false; node._def.defaults.ridproperties.required = false; ridForm.hide(); typeForm.hide(); propertiesForm.hide(); urlForm.show(); queryForm.hide(); queryEditor.hide(); } else if (searchBy === "_query_") { node._def.defaults.ridtype.required = false; node._def.defaults.ridproperties.required = false; ridForm.hide(); typeForm.hide(); propertiesForm.hide(); urlForm.hide(); node.editor = RED.editor.createEditor({ id: 'node-input-query-editor', mode: 'ace/mode/json', value: $("#node-input-query").val() }); queryForm.show(); queryEditor.show(); node.editor.focus(); } }); propertiesIn.change(function() { makeTypeRequiredIfPropertiesHasValues(); }); function makeTypeRequiredIfPropertiesHasValues() { const properties = propertiesIn.val(); if (typeof properties !== 'undefined' && properties !== null && properties !== "") { node._def.defaults.ridtype.required = true; } else { node._def.defaults.ridtype.required = false; } } } RED.nodes.registerType("IGC out", { category: "storage-output", color: "rgb(114, 199, 231)", defaults: { name: { value: "" }, server: { type: "ibm-igc", required: true }, operation: { value: "update", required: true }, rid: { value: "" }, assettype: { value: "" }, details: { value: "{\n\t\"short_description\": \"A new short description\"\n}" } }, inputs: 1, outputs: 1, icon: "ibm-igc.png", align: "right", label: label, labelStyle: function() { return this.name ? "node_label_italic" : ""; }, oneditprepare: oneditprepareOut, oneditsave: function() { $("#node-input-details").val(this.editor.getValue()); delete this.editor; } }); function oneditprepareOut() { const node = this; const operationSelect = $('#node-input-operation'); const ridForm = $('#node-save-rid-form'); const assetTypeForm = $('#node-save-assettype-form'); const detailsForm = $('#node-save-details-form'); const detailsEditor = $('#node-save-details-editor-form'); operationSelect.change(function() { const operation = operationSelect.val(); if (operation === "create") { ridForm.hide(); assetTypeForm.show(); showDetailsEditor(); } else if (operation === "update" ) { ridForm.show(); assetTypeForm.hide(); showDetailsEditor(); } else if (operation === "delete") { ridForm.show(); assetTypeForm.hide(); detailsForm.hide(); detailsEditor.hide(); } }); function showDetailsEditor() { node.editor = RED.editor.createEditor({ id: 'node-input-details-editor', mode: 'ace/mode/json', value: $("#node-input-details").val() }); detailsForm.show(); detailsEditor.show(); node.editor.focus(); } } function label() { return this.name || "IGC"; } </script> <script type="text/x-red" data-help-name="IGC in"> <p>Retrieves metadata from Information Governance Catalog.</p> <h3>Inputs</h3> <dl class="message-properties"> <dt>query <span class="property-type">object</span></dt> <dd> the full query to POST to the REST API, when retrieval type is Complex Query</dd> <dt>url <span class="property-type">string</span></dt> <dd> the URL to GET via the REST API, when retrieval type is URL Passthrough</dd> <dt>rid <span class="property-type">string</span></dt> <dd> the unique ID (RID) of the IGC metadata asset to retrieve, when retrieval type is RID</dd> <dt class="optional">type <span class="property-type">string</span></dt> <dd> the type of asset being requested, when retrieval type is RID (mandatory when properties are specified)</dd> <dt class="optional">properties <span class="property-type">string</span></dt> <dd> an (optional) comma-separated list of properties to retrieve, when retrieval type is RID</dd> </dl> <h3>Outputs</h3> <dl class="message-properties"> <dt>results <span class="property-type">object</span></dt> <dd>the set of results for the retrieval, typically with a structure of <code>{ items: [], paging: {} }</code>, though the paging portion may be missing if there are not multiple results to page through (i.e. when retrieving by RID).</dd> </dl> <h3>Details</h3> <p> This uses the both GET- and POST-based Information Governance Catalog REST APIs to retrieve metadata using the most efficient means possible. </p> <h4>Complex Query option</h4> <p> Using the Complex Query option, you can run an arbitrary search. For example, you can pass a query like this: </p> <p> <code> { "properties": ["name"], "types": ["term"], "where": { "operator": "and", "conditions": [ { "property": "modified_on", "operator": ">=", "value": "1483232400" } ] } } </code> </p> <p> to get a listing of the names of all business terms that were modified on or after January 1, 2017 (value provided as UNIX time). </p> <p> If Query is empty, will look for the query in <code>msg.query</code>. </p> <h4>URL Passthrough option</h4> <p> Using the URL Passthrough mode allows you to invoke any arbitrary GET-based Information Governance Catalog REST API URL. For example, you can pass any URL returned by a previous query's <code>next</code> property (for pagination), or the <code>_url</code> property (to get more details on that particular asset). </p> <p> If URL is empty, will look for the URL in <code>msg.url</code>. (Note: if specific host details are supplied in the URL they will be overridden by the Server selected via configuration -- this is necessary to ensure credentials are passed appropriately). </p> <h4>RID option</h4> <p> Using the RID option you can retrieve a single asset's details by its unique Information Governance Catalog ID (RID). You can also (optionally) provide a list of specific properties to retrieve for the asset: in general this is a good practice, as it is more efficient than retrieving all properties. Note that when doing so, specifying the type of the asset then also becomes mandatory. </p> <p> If RID is empty, will look for the RID as a string in <code>msg.rid</code>; if Properties is empty, will look for properties as an array in <code>msg.properties</code>; if Type is empty will look for the type as a string in <code>msg.type</code>. </p> <h3>References</h3> <ul> <li><a href="http://www.ibm.com/support/docview.wss?uid=swg27047054&aid=1" target="_blank">Tips, Tricks &amp; Time-Savers Guide</a></li> <li><a href="http://www.ibm.com/support/docview.wss?uid=swg27047059&aid=1" target="_blank">Sample Rest API Calls and Use Case Descriptions Guide</a></li> </ul> </script> <script type="text/x-red" data-help-name="IGC out"> <p>Stores, updates or removes metadata from Information Governance Catalog.</p> <h3>Inputs</h3> <dl class="message-properties"> <dt>rid <span class="property-type">string</span></dt> <dd> the unique ID (RID) of the IGC metadata asset to update or delete</dd> <dt class="optional">type <span class="property-type">string</span></dt> <dd> the type of asset to create, when the operation is Create</dd> <dt>details <span class="property-type">object</span></dt> <dd> the detailed set of properties to create or update against the metadata asset</dd> </dl> <h3>Outputs</h3> <dl class="message-properties"> <dt>payload <span class="property-type">string | object</span></dt> <dd>results of successful operations: the RID (string) for Create, updated properties (object) for Update, and empty for Delete</dd> </dl> <h3>Details</h3> <p> This uses the appropriate Information Governance Catalog REST API to make updates to metadata, whether creating new assets, updating existing assets, or deleting existing assets. All operations will push their results out to the output port for optional consumption; if any error has occured, an error will be thrown with the details -- use a Catch node to capture these. </p> <h4>Create operation</h4> <p> The Create operation should only be used when an asset does not already exist in IGC with the details that need to be stored. If the asset already exists, and you simply wish to set some additional properties on the asset (or replace existing ones), use the Update operation instead. Using the Create operation, you need to provide both the Type of the asset to create and the Details of the property values to set within it. Note that different assets have different required properties as part of their creation; in general this will require at least the 'name' property. </p> <p> The standard output will be the RID of the created asset, as a string. </p> <p> For example, use a Type of 'category' and provide Details like this: </p> <p> <code> { "name": "Test Category" } </code> </p> <p> to create a new top-level category named 'Test Category'. </p> <p> If Type is empty, will look for the type as a string in <code>msg.type</code>; if Details is empty, will look for the detailed properties as a JSON object in <code>msg.details</code>. </p> <h4>Update operation</h4> <p> The Update operation expects a unique IGC identifier ("RID") to specify which specific piece of metadata to update. Details are also needed to define what on that piece of metadata should be updated. This second parameter is expected to be a JSON object, and should contain only the properties that need to change on the asset. </p> <p> The standard output will be the changed properties of the asset (typically matching the provided Details), as a JSON object. </p> <p> For example, you can use the following Details: </p> <p> <code> { "short_description": "a new short description", "labels": { "items": [ "6662c0f2.22257cc4.p864keo17.vbbgrpe.26j4m1.mgcmn0lh4fb2ggdjb7ujo", "6662c0f2.22257cc4.p864keo18.0o97qi8.f1ar57.dmjlsjtjghbifmi6p2tc4" ], "mode": "add" } } </code> </p> <p> to update the short description of the piece of metadata, and also add (append) two new labels. Note: <ul> <li>related items must also be specified by their RID</li> <li>using <code>replace</code> as the mode will overwrite any existing relationships (and if you provide an empty array, will remove all existing relationships).</li> </ul> </p> <p> If RID is empty, will look for the RID as a string in <code>msg.rid</code>; if Details is empty, will look for the detailed properties as a JSON object in <code>msg.details</code>. </p> <h4>Delete operation</h4> <p> Like the Update operation, the Delete operation requires a unique IGC identifier ("RID") to specify which specific piece of metadata to delete. No details object is needed as the entire asset (and all of its properties) will be deleted. </p> <p> On successful deletion, the standard output will be empty (just a payload containing only Node-RED's _msgid). </p> <p> If RID is empty, will look for the RID as a string in <code>msg.rid</code>. </p> </script>