-
Notifications
You must be signed in to change notification settings - Fork 2
Snow incidents plugin #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 16 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
74bd4f5
Initial Commit
0873495
Initial Commit of Plugin, still work left to do
2effc88
removed PluginContext from App.tsx
a860446
Added Readme content
4f9d8ce
Updated variable names to be consistent with Change servicenow plugin…
ab13423
Updated message when there are no incidents
d82cafe
updates
8c0dffc
updated from main
6dc2e25
ran yarn fix
c7e8477
two tests pass locally
aeadfbb
update so it works
f335e9c
configure snow instance from entity, improve table, other stuff
martindstone 80a2317
fix tests, some words
martindstone 38c6861
ream de
martindstone 9a07362
lint
martindstone 0dd4bd9
move fetches to hooks
martindstone 349bf54
remove asset
martindstone 5e8eb0c
revert yarn.lock
martindstone File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules/ | ||
dist/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
module.exports = { | ||
env: { | ||
browser: true, | ||
es2021: true, | ||
}, | ||
extends: [ | ||
"plugin:react/jsx-runtime", | ||
"plugin:react-hooks/recommended", | ||
"standard-with-typescript", | ||
"prettier", | ||
], | ||
overrides: [], | ||
parserOptions: { | ||
ecmaVersion: "latest", | ||
project: "tsconfig.json", | ||
sourceType: "module", | ||
tsconfigRootDir: __dirname, | ||
}, | ||
plugins: ["react"], | ||
rules: { | ||
// conflicts with no-extra-boolean-cast | ||
"@typescript-eslint/strict-boolean-expressions": "off", | ||
"no-console": ["error", { allow: ["warn", "error"] }], | ||
}, | ||
settings: { | ||
react: { | ||
version: "detect", | ||
}, | ||
}, | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# OSX | ||
*.DS_Store | ||
|
||
# IDEs | ||
.idea | ||
*.iml | ||
.vscode | ||
|
||
# This project | ||
node_modules/ | ||
dist/ | ||
yarn-error.log |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules/ | ||
dist/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# ServiceNow Incidents Plugin | ||
|
||
View ServiceNow incidents associated with a Cortex service! | ||
|
||
<div align="center"><img src="img/incidents_cortex.png" width="550" /></div> | ||
|
||
The ServiceNow Incidents plugin shows you recent incidents that have been filed against a given service in Cortex. It does this by associating the Cortex entity with a CMDB CI, and searching the ServiceNow `incident` table for incidents whose `cmdb_ci`, `business_service`, or `affected_ci` match the associated CI. Here are the ways the plugin looks for the CI for a Cortex entity: | ||
|
||
- If the Cortex entity is already mapped to a ServiceNow CMDB CI using the Cortex ServiceNow integration, the plugin will show incidents pertaining to that CI. | ||
- If it's not mapped, the plugin uses the service name in Cortex to find a corresponding service with the same name in the CMDB by searching `cmdb_ci_service` for objects with the same name as the entity's tag or name. | ||
- If you don't want to search, and want to configure a specific CI without mapping the entity to ServiceNow, you can set a custom data key `servicenow-sys_id` on the entity to the sys_id of the CI for which you want to show incidents when the plugin is displayed for that entity. | ||
|
||
<div align="center"><img src="img/incidents_snow.png" width="550" /></div> | ||
|
||
## Setup | ||
|
||
To see how to run the plugin inside of Cortex, see [our docs](https://docs.cortex.io/docs/plugins). This plugin will require a proxy to ServiceNow. | ||
|
||
### Proxy Setup | ||
|
||
- Define a Secret that is a base64 encoding of `username:password`. You can use a tool similar to [this](https://www.debugbear.com/basic-auth-header-generator) to convert it. | ||
- Define a proxy that is pointed at your ServiceNow instance with the nescessary headers. For help figuring out which headers to use, refer to the REST API explorer in your servicenow instance. Here is an example of what your proxy may look like: | ||
|
||
<div align="center"><img src="img/proxy_changes.png" width="550" /></div> | ||
|
||
### Plugin Registration | ||
|
||
- Create a Plugin and associate it with the proxy you created in the previous step | ||
- This Plugin will not work in the Global context. | ||
- Select the entity types that will have a corresponding CMDB CI. Below is what a configuration may look like. In this example the plugin will be available to both Services and Resources. | ||
<div align="center"><img src="img/snow_changes_config.png" width="350" /></div> | ||
|
||
- Follow the directions under **Getting Started** below to build `ui.html` and upload it | ||
|
||
### Set your ServiceNow instance URL | ||
|
||
Your ServiceNow instance URL should look like `https://something.service-now.com`. It's the same URL you used to set up the proxy above. We also want to create a new entity to tell the plugin what ServiceNow URL to load: | ||
|
||
- Consider creating a new entity type, so that any existing scorecards are not affected by ths configuration entity. In this example, we have created a new entity type called `plugin-configuration` | ||
- Create a new entity with the tag `servicenow-plugin-config` | ||
- Set `x-cortex-definition.servicenow-url` to the value of your ServiceNow Instance URL. For example, if my ServiceNow Instance URL was `https://martindstone.service-now.com`, my `servicenow-plugin-config` entity would look like this: | ||
|
||
``` | ||
openapi: 3.0.1 | ||
info: | ||
title: ServiceNow Plugin Config | ||
description: "" | ||
x-cortex-tag: servicenow-plugin-config | ||
x-cortex-type: plugin-configuration | ||
x-cortex-definition: | ||
servicenow-url: https://martindstone.service-now.com | ||
``` | ||
|
||
Now when you load the plugin on an entity, you should see any ServiceNow incidents that were filed against that entity's CMDB CI. | ||
|
||
## Setting up your dev environment | ||
|
||
### Prerequisites | ||
|
||
Developing and building this plugin requires either [yarn](https://classic.yarnpkg.com/lang/en/docs/install/) or [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). | ||
|
||
## Getting started | ||
|
||
1. Run `yarn` or `npm install` to download all dependencies | ||
2. Run `yarn build` or `npm run build` to compile the plugin code into `./dist/ui.html` | ||
3. Upload `ui.html` into Cortex on a create or edit plugin page | ||
4. Add or update the code and repeat steps 2-3 as necessary | ||
|
||
### Notable scripts | ||
|
||
The following commands come pre-configured in this repository. You can see all available commands in the `scripts` section of [package.json](./package.json). They can be run with npm via `npm run {script_name}` or with yarn via `yarn {script_name}`, depending on your package manager preference. For instance, the `build` command can be run with `npm run build` or `yarn build`. | ||
|
||
- `build` - compiles the plugin. The compiled code root is `./src/index.tsx` (or as defined by [webpack.config.js](webpack.config.js)) and the output is generated into `dist/ui.html`. | ||
- `test` - runs all tests defined in the repository using [jest](https://jestjs.io/) | ||
- `lint` - runs lint and format checking on the repository using [prettier](https://prettier.io/) and [eslint](https://eslint.org/) | ||
- `lintfix` - runs eslint in fix mode to fix any linting errors that can be fixed automatically | ||
- `formatfix` - runs Prettier in fix mode to fix any formatting errors that can be fixed automatically | ||
|
||
### Available React components | ||
|
||
See available UI components via our [Storybook](https://cortexapps.github.io/plugin-core/). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = "test-file-stub"; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = {}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module.exports = { | ||
plugins: ["@babel/plugin-syntax-jsx"], | ||
presets: [ | ||
["@babel/preset-env", { targets: { node: "current" } }], | ||
"@babel/preset-typescript", | ||
["@babel/preset-react", { runtime: "automatic" }], | ||
], | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
openapi: 3.0.1 | ||
info: | ||
title: Plugins Snow Incident Plugin | ||
description: "" | ||
x-cortex-tag: plugins-snow-incident-plugin | ||
x-cortex-git: | ||
github: | ||
repository: cortexapps/cortex-plugins | ||
basepath: plugins/snow-incident-plugin | ||
x-cortex-custom-metadata: | ||
cortex-template-version: 0.1.0 | ||
cortex-generated-timestamp: 2023-08-14T18:41:53.747515527 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
module.exports = { | ||
moduleNameMapper: { | ||
// map static asset imports to a stub file under the assumption they are not important to our tests | ||
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": | ||
"<rootDir>/__mocks__/fileMock.js", | ||
// map style asset imports to a stub file under the assumption they are not important to our tests | ||
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js", | ||
"@cortexapps/plugin-core/components": | ||
"<rootDir>/../../node_modules/@cortexapps/plugin-core/dist/components.cjs.js", | ||
"@cortexapps/plugin-core": | ||
"<rootDir>/../../node_modules/@cortexapps/plugin-core/dist/index.cjs.js", | ||
}, | ||
setupFilesAfterEnv: ["<rootDir>/setupTests.ts"], | ||
testEnvironment: "jsdom", | ||
transform: { | ||
"^.+\\.tsx?$": "babel-jest", | ||
}, | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
{ | ||
"name": "ServiceNowIncidentsPlugin", | ||
"version": "0.1.0", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@cortexapps/plugin-core": "^2.0.0", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.21.3", | ||
"@babel/plugin-syntax-jsx": "^7.18.6", | ||
"@babel/preset-env": "^7.20.2", | ||
"@babel/preset-react": "^7.18.6", | ||
"@babel/preset-typescript": "^7.21.0", | ||
"@popperjs/core": "^2.11.8", | ||
"@testing-library/jest-dom": "^5.16.5", | ||
"@testing-library/react": "^14.0.0", | ||
"@types/react": "^18.0.28", | ||
"@types/react-dom": "^18.0.11", | ||
"@typescript-eslint/eslint-plugin": "^5.0.0", | ||
"@typescript-eslint/parser": "^5.55.0", | ||
"babel-jest": "^29.5.0", | ||
"css-loader": "^6.7.3", | ||
"eslint": "^8.0.1", | ||
"eslint-config-prettier": "^8.7.0", | ||
"eslint-config-standard-with-typescript": "^34.0.0", | ||
"eslint-plugin-import": "^2.25.2", | ||
"eslint-plugin-n": "^15.6.1", | ||
"eslint-plugin-promise": "^6.0.0", | ||
"eslint-plugin-react": "^7.32.2", | ||
"eslint-plugin-react-hooks": "^4.6.0", | ||
"html-webpack-plugin": "^5.5.0", | ||
"jest": "^29.5.0", | ||
"jest-environment-jsdom": "^29.5.0", | ||
"jest-fetch-mock": "^3.0.3", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^2.8.4", | ||
"prop-types": "^15.8.1", | ||
"react-dev-utils": "^12.0.1", | ||
"style-loader": "^3.3.1", | ||
"terser-webpack-plugin": "^5.3.7", | ||
"ts-loader": "^9.4.2", | ||
"typescript": "^4.9.5", | ||
"url-loader": "^4.1.1", | ||
"webpack": "^5.76.1", | ||
"webpack-cli": "^5.0.1", | ||
"webpack-dev-server": "^4.15.0" | ||
}, | ||
"scripts": { | ||
"build": "webpack --mode=production", | ||
"clean": "rm -r ./dist", | ||
"dev": "webpack serve --mode=development", | ||
"fix": "run-p formatfix lintfix", | ||
"formatfix": "yarn prettier . --write", | ||
"formatcheck": "yarn prettier . --check", | ||
"lint": "run-p formatcheck lintcheck", | ||
"lintcheck": "yarn eslint src", | ||
"lintfix": "yarn lintcheck --fix", | ||
"test": "jest" | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import "@testing-library/jest-dom/extend-expect"; | ||
import fetchMock from "jest-fetch-mock"; | ||
|
||
fetchMock.enableMocks(); | ||
const mockContext = { | ||
apiBaseUrl: "https://api.cortex.dev", | ||
entity: { | ||
definition: null, | ||
description: null, | ||
groups: null, | ||
name: "Inventory planner", | ||
ownership: { | ||
emails: [ | ||
{ | ||
description: null, | ||
email: "[email protected]", | ||
inheritance: null, | ||
id: 1, | ||
}, | ||
], | ||
}, | ||
tag: "inventory-planner", | ||
type: "service", | ||
}, | ||
location: "ENTITY", | ||
user: { | ||
email: "[email protected]", | ||
name: "Ganesh Datta", | ||
role: "ADMIN", | ||
}, | ||
}; | ||
|
||
jest.mock("@cortexapps/plugin-core/components", () => { | ||
const originalModule = jest.requireActual( | ||
"@cortexapps/plugin-core/components" | ||
); | ||
return { | ||
...originalModule, | ||
usePluginContext: () => { | ||
return mockContext; | ||
}, | ||
PluginProvider: ({ children }) => { | ||
return children; | ||
}, | ||
}; | ||
}); | ||
|
||
jest.mock("@cortexapps/plugin-core", () => { | ||
const originalModule = jest.requireActual("@cortexapps/plugin-core"); | ||
return { | ||
...originalModule, | ||
CortexApi: { | ||
...originalModule.CortexApi, | ||
getContext: () => { | ||
return mockContext; | ||
}, | ||
}, | ||
}; | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { CortexApi, type CortexContextResponse } from "@cortexapps/plugin-core"; | ||
|
||
export const getCortexContext = async (): Promise<CortexContextResponse> => { | ||
const context = await CortexApi.getContext(); | ||
|
||
return context; | ||
}; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
body { | ||
font: 14px sans-serif; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { render, screen, waitFor } from "@testing-library/react"; | ||
|
||
import fetchMock from "jest-fetch-mock"; | ||
import { successMockBodies } from "../mocks/mockBodies"; | ||
|
||
import App from "./App"; | ||
|
||
describe("App", () => { | ||
beforeEach(() => { | ||
// Reset fetchMock before each test to start with a clean slate | ||
fetchMock.resetMocks(); | ||
}); | ||
|
||
it("tries to fetch", async () => { | ||
fetchMock.mockResponse(async (req) => { | ||
const url = req.url.split("?")[0]; | ||
return { | ||
status: 200, | ||
body: JSON.stringify(successMockBodies[url]), | ||
}; | ||
}); | ||
|
||
render(<App />); | ||
|
||
await waitFor(() => { | ||
expect(fetch).toHaveBeenCalledWith( | ||
"https://api.cortex.dev/catalog/servicenow-plugin-config/openapi" | ||
); | ||
expect(fetch).toHaveBeenCalledWith( | ||
"https://api.cortex.dev/catalog/inventory-planner/openapi" | ||
); | ||
expect(fetch).toHaveBeenCalledWith( | ||
expect.stringMatching( | ||
/https:\/\/unit-testing-snow-instance\.service-now\.com\/api\/now\/table\/cmdb_ci_service/ | ||
) | ||
); | ||
expect(fetch).toHaveBeenCalledWith( | ||
expect.stringMatching( | ||
/https:\/\/unit-testing-snow-instance\.service-now\.com\/api\/now\/table\/incident/ | ||
) | ||
); | ||
}); | ||
}); | ||
|
||
it("displays incidents", async () => { | ||
fetchMock.mockResponse(async (req) => { | ||
const url = req.url.split("?")[0]; | ||
return { | ||
status: 200, | ||
body: JSON.stringify(successMockBodies[url]), | ||
}; | ||
}); | ||
|
||
render(<App />); | ||
|
||
await waitFor(() => { | ||
const element = screen.getByText("Unable to connect to email", { | ||
selector: "p", | ||
}); | ||
expect(element).toBeInTheDocument(); | ||
}); | ||
}); | ||
|
||
it("fails to display incidents", async () => { | ||
fetchMock.mockResponse(async () => { | ||
return { | ||
status: 200, | ||
body: JSON.stringify({}), | ||
}; | ||
}); | ||
|
||
render(<App />); | ||
|
||
await waitFor(() => { | ||
const element = screen.getByText( | ||
"This plugin will fetch incidents from ServiceNow and display them here.", | ||
{ selector: "p" } | ||
); | ||
expect(element).toBeInTheDocument(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.