Using Wazi Analyze APIs
With Wazi Analyze APIs, you can access impact analysis results in the Wazi Analyze server without the web user interface.
Getting started with Wazi Analyze APIs
All Wazi Analyze APIs are implemented in GraphQL and respond to the POST requests according to the GraphQL query protocol. A Wazi Analyze API is an integration layer for the Wazi Analyze server data provider and requires Wazi Analyze services to be running to provide data.
- Configure the host container. The Wazi Analyze host container should have an additional port mapping that is defined for accessing the APIs. The port by default in the container image is set to
4680
. When you start the Wazi Analyze container, run the following commands to add the port mapping parameter.-p <hostname>:4680
Note: Replace<hostname>
with your preferred port to map to, for example,-p 4680:4680
- Start up and configure the servers.
The Wazi Analyze servers (
wa-startup.sh
) should be running for the API servers to be able to query the data. The order of running the startup scripts is not important. You can run the API startup script before or after you start the other Wazi Analyze servers. To start the API server, run one of the following commands on the container's bash prompt:- Normal startup
aznapi-startup.sh --bearerToken=<token>
Note:<token>
is a string of 10 characters or longer. This is a pseudo bearer token that will be needed to call all GraphQL query API. The token will be needed as part of theAuthorization
header on the HTTP POST request as follows:Authorization: bearer <token>
The token value is not stored by the API component. Each time the component is started, you provide a token. No rules are defined as to what the content of the token can be except that it must be10 characters or longer. It might contain any combination of alphanumeric characters and special symbols except the equal sign
=
, hyphen-
, or blank.
- Detached startup
nohup aznapi-startup.sh --bearerToken=<token>
This command will launch the API component in a detached mode and all of the console output will be redirected to file
nohup.out
.
Shutting down the API server
You can run the
wa-shutdown.sh
script to shut down the Wazi Analyze API server, which will shut down all the Wazi Analyze servers. - Normal startup
- Achieve authentication and authorization.
Authentication and authorization is achieved by supplying a pseudo bearer token on each call to the Query API. Note that schema introspection queries (the information about the model) do not require a token.
- Access the API endpoint to view impact analysis results.Wazi Analyze API endpoint in the container is running on port
4680
as follows.
You can run queries programmatically through either command line tools, such as cURL, or a browser-based REST client, such as Postman.https://localhost:4680/azn-graphql/v1
API Specification
GraphQL is introspective. You can query a GraphQL schema for information about what queries it supports. No authentication is required when you query a GraphQL schema.
__schema
to
list all types that are defined in the schema. query {
__schema {
types {
name
kind
description
fields {
name
}
}
}
}
curl -X POST -H "Content-Type: application/json" -d '{"query":"query{__schema {types {name kind description fields {name}}}}"}' -k https://localhost:4680/azn-graphql/v1
-k
cURL
switch allows to bypass strict SSL/TLS certificate validation. If
you have a valid SSL/TLS certificate installed on your server, you
should omit this switch._type
to get
details about any type.query {
__type(name: "AznProject") {
name
kind
description
fields {
name
}
}
}
Available APIs
projects(queryString:ID): <AznBasicProject>
project(id:ID): AznBasicProject
project(id:ID): AznBasicProject
id:ID
type:String
label:String
metadata:JSON
//Retrieve a list of all project ids and types
POST`https://localhost:4680/azn-graphql/v1`
Authorization: bearer 0123456789
{"query":"{ projects {id type}}" }
curl -X POST -H "Authorization: bearer 0123456789" -H "Content-Type: application/json" -d '{"query":"query{projects {id type}}"}' -k https://localhost:4680/azn-graphql/v1
{
"data": {
"projects": [
{
"id":"GenAppC",
"type":"project"
},
{
"id":"GenApp_dev",
"type":"project"
},
{
"id":"GenApp_wrk",
"type":"project"
}
]
}
}
//Retrieve a list of project ids and metadata for all projects whose Id contains a string `wrk`
POST`https://localhost:4680/azn-graphql/v1`
Authorization: bearer 0123456789
{"query":"{ projects(queryString:\"wrk\") {id metadata}}" }
Response:
{
"data": {
"projects": [
{
"id":"GenApp_wrk",
"metadata": {
"metatype":"logical",
"info": [
"GenApp_wrk",
"2021-05-20T02:03:24",
"18",
"94",
"IMPACT"
]
}
}
]
}
}
programs(queryString: String, projectId: ID): <AznProgram>
//Retrieve a list of program names (labels) for all programs whose name contains a string `LGTEST` in project `GenAppC`
{
programs(projectId: "GenAppC", queryString: "LGTEST") {
label
}
}
{
"data": {
"programs": [
{
"label": "LGTESTC1"
},
{
"label": "LGTESTP1"
},
{
"label": "LGTESTP2"
},
{
"label": "LGTESTP3"
},
{
"label": "LGTESTP4"
}
]
}
}
files(queryString:String, projectId:ID): <AznFile>
//Retrieve a list of file names (labels) for all files whose name contains a string `LGC` in project `GenAppC`
{
files(projectId: "GenAppC", queryString: "LGC") {
label
}
}
{
"data": {
"files": [
{
"label": "LGCMAREA.CPY"
},
{
"label": "LGCMARER.CPY"
}
]
}
}
The Graph API retrieves the information about the types and relationships between and among generic (as defined by provider) program objects and/or generic file objects. The Graph response format is based on JSON Graph Format specificaion (V2).
graphs (
programName: String
fileName: String
projectId: ID
callDepth: BigInt
): [Graph]
The current provider for Wazi Analyze
data is for static source code analysis. Based on the static analysis
of code, the relationship between programs is a programCall
type,
and the relationship between files is a contain
type.
When you specify the programName
query parameter
without callDepth
, the relationship edges array in
the response will contain both the programCall
type
relationship for the specified program name and the contain
type
relationships for the files related to the program, such as included
source files. Note that if you have duplicate program names in your
project, where the duplicate program name is located in a file that
has a name different from the program name, the query results will
be undetermined. Also note that the File artifacts are called modules
in
the nodes map metadata. Contain
type relationships
do not have a depth specification and for programName
queries,
the entire set of related files will be returned, including files
whose references are nested in the relationship chain.
When
you specify the programName
query parameter with callDepth
,
the relationship edges will contain only programCall
type
relationship for the specified program name. Call depth specification
is honored in both call directions. That is, both parents and children
of the program are returned at the specified depth. Note that the
nodes map may still contain File (metadata type module
)
artifacts that could be ignored for the purpose of programCall
type
depth relationships.
When you specify the fileName
,
a contain
type list of edges will be returned for
the fileName
. Only files that are directly referenced
by the file containing the fileName
are returned.
For example, if file A
contains references to file B
and C
,
and file B
contains references to file D
,
only relationships to B
and C
will
be returned for file A
. The edges might also contain programCall
type
relationship, and the nodes map might contain program
type
nodes, which can be ignored for the purpose of contain
type
relationships.
When you specify both programName
and fileName
,
two separate independent graph objects will be returned. The callDepth
parameter
will be applied to the graph that is based on programName
.
//Retrieve graph for program with name `LGACUS01` and file `LGACUS01.CBL` in project `GenAppC`
{
graphs(projectId: "GenAppC", programName: "LGACUS01", fileName: "LGACUS01.CBL") {
id
nodes
edges {
source
target
relation
}
}
}
{
"data": {
"graphs": [
{
"id": "GenAppC",
"nodes": {
"program:LGACUS01": {
"label": "LGACUS01",
"metadata": {
"type": "program",
"srctype": "COBOL",
"loc": "580",
"locmt": "164",
"rloc": "382"
}
},
"module:DEFVAR.CPY": {
"label": "DEFVAR.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITP%/Include/MACLIB/DEFVAR.CPY"
}
},
"module:LGACUS01.CBL": {
"label": "LGACUS01.CBL",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITPDATA%/GenAppC/source/nazare-demo-genapp/base/src/cobol/LGACUS01.CBL"
}
},
"module:LGPOLICY.CPY": {
"label": "LGPOLICY.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITPDATA%/GenAppC/source/nazare-demo-genapp/base/src/copy/LGPOLICY.CPY"
}
},
"module:LGCMAREA.CPY": {
"label": "LGCMAREA.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITPDATA%/GenAppC/source/nazare-demo-genapp/base/src/copy/LGCMAREA.CPY"
}
},
"module:DFHEIBLK.CPY": {
"label": "DFHEIBLK.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITP%/Include/MACLIB/DFHEIBLK.CPY"
}
},
"module:DFHEIVAR.CPY": {
"label": "DFHEIVAR.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITP%/Include/MACLIB/DFHEIVAR.CPY"
}
},
"module:DIBSTAT.CPY": {
"label": "DIBSTAT.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITP%/Include/MACLIB/DIBSTAT.CPY"
}
}
},
"edges": [
{
"source": "module:LGACUS01.CBL",
"target": "module:DEFVAR.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:LGPOLICY.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:LGCMAREA.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:DFHEIBLK.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:DFHEIVAR.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:DIBSTAT.CPY",
"relation": "Contain"
},
{
"source": "program:LGACUS01",
"target": "program:LGACDB01",
"relation": "ProgramCall"
},
{
"source": "program:LGACUS01",
"target": "program:LGSTSQ",
"relation": "ProgramCall"
}
]
},
{
"id": "GenAppC",
"nodes": {
"program:LGACUS01": {
"label": "LGACUS01",
"metadata": {
"type": "program",
"srctype": "COBOL",
"loc": "580",
"locmt": "164",
"rloc": "382"
}
},
"module:LGACUS01.CBL": {
"label": "LGACUS01.CBL",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITPDATA%/GenAppC/source/nazare-demo-genapp/base/src/cobol/LGACUS01.CBL"
}
},
"module:DEFVAR.CPY": {
"label": "DEFVAR.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITP%/Include/MACLIB/DEFVAR.CPY"
}
},
"module:LGPOLICY.CPY": {
"label": "LGPOLICY.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITPDATA%/GenAppC/source/nazare-demo-genapp/base/src/copy/LGPOLICY.CPY"
}
},
"module:LGCMAREA.CPY": {
"label": "LGCMAREA.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITPDATA%/GenAppC/source/nazare-demo-genapp/base/src/copy/LGCMAREA.CPY"
}
},
"module:DFHEIBLK.CPY": {
"label": "DFHEIBLK.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITP%/Include/MACLIB/DFHEIBLK.CPY"
}
},
"module:DFHEIVAR.CPY": {
"label": "DFHEIVAR.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITP%/Include/MACLIB/DFHEIVAR.CPY"
}
},
"module:DIBSTAT.CPY": {
"label": "DIBSTAT.CPY",
"metadata": {
"type": "module",
"srctype": "COBOL",
"sourcefile": "%ITP%/Include/MACLIB/DIBSTAT.CPY"
}
}
},
"edges": [
{
"source": "module:LGACUS01.CBL",
"target": "module:DEFVAR.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:LGPOLICY.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:LGCMAREA.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:DFHEIBLK.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:DFHEIVAR.CPY",
"relation": "Contain"
},
{
"source": "module:LGACUS01.CBL",
"target": "module:DIBSTAT.CPY",
"relation": "Contain"
},
{
"source": "program:LGACUS01",
"target": "program:LGACDB01",
"relation": "ProgramCall"
},
{
"source": "program:LGACUS01",
"target": "program:LGSTSQ",
"relation": "ProgramCall"
}
]
}
]
}
}
Error handling
GraphQL
queries report data errors and data authorization errors through a
response body in an HTTP code 200 response. This behavior is different
from many REST-based systems where the data and authorization errors
might cause HTTP error response codes. GraphQL systems will produce
HTTP error responses in cases of network server, endpoint access errors,
and query syntax errors. Queries that result in empty responses or
other recoverable back end errors, the GraphQL-based API will return
HTTP 200 and either empty responses or a body with a standard GraphQL errors
array
content that contains the error message.
For individual query authorization errors, API will return an HTTP 200 with an errors array in the message body, for example:
{
"errors":[
{
"message": "Authorization failed. Token is not authorized.",
"locations":[
{"line": 1, "column": 2}
],
"path":[
"graph"
]
}
],
"data":{
graph": null
}
}