├── .eslintignore ├── .node-version ├── .npmrc ├── src ├── index.ts ├── hooks │ └── init │ │ └── set-global-config.ts ├── commands │ ├── util │ │ └── timestamp.ts │ ├── tag │ │ ├── list.ts │ │ └── listobjects.ts │ ├── team │ │ ├── list.ts │ │ ├── open.ts │ │ ├── create.ts │ │ ├── user │ │ │ └── remove.ts │ │ └── ep │ │ │ ├── list.ts │ │ │ └── add.ts │ ├── auth │ │ ├── use.ts │ │ ├── list.ts │ │ ├── get.ts │ │ ├── delete.ts │ │ └── add.ts │ ├── field │ │ ├── schema │ │ │ ├── assignment │ │ │ │ ├── remove.ts │ │ │ │ └── create.ts │ │ │ ├── create.ts │ │ │ ├── removefield.ts │ │ │ └── list.ts │ │ ├── option │ │ │ ├── remove.ts │ │ │ ├── list.ts │ │ │ └── create.ts │ │ ├── list.ts │ │ └── create.ts │ ├── service │ │ ├── enable.ts │ │ ├── disable.ts │ │ ├── open.ts │ │ └── list.ts │ ├── ep │ │ ├── listdeletedusers.ts │ │ ├── list.ts │ │ └── open.ts │ ├── schedule │ │ ├── list.ts │ │ ├── listdeletedusers.ts │ │ ├── open.ts │ │ └── copy.ts │ ├── bs │ │ ├── list.ts │ │ └── subscriber │ │ │ └── list.ts │ ├── automation │ │ ├── action │ │ │ └── list.ts │ │ └── runner │ │ │ └── list.ts │ ├── orchestration │ │ ├── add.ts │ │ ├── list.ts │ │ └── route │ │ │ ├── list.ts │ │ │ └── add.ts │ ├── rest │ │ ├── get.ts │ │ ├── delete.ts │ │ ├── put.ts │ │ └── post.ts │ ├── incident │ │ ├── open.ts │ │ ├── notes.ts │ │ ├── resolve.ts │ │ ├── set.ts │ │ ├── merge.ts │ │ ├── ack.ts │ │ └── subscriber │ │ │ └── update.ts │ ├── log.ts │ └── user │ │ ├── contact │ │ ├── add.ts │ │ ├── set.ts │ │ └── list.ts │ │ └── list.ts └── base │ ├── docopts.ts │ └── list-base-command.ts ├── .tool-versions ├── bin ├── dev.cmd ├── run.cmd ├── run └── dev ├── .eslintrc ├── test ├── mocha.opts ├── tsconfig.json └── commands │ ├── set-global-config.test.ts │ └── hello.test.ts ├── .gitignore ├── .editorconfig ├── tsconfig.json ├── docs ├── help.md ├── version.md ├── autocomplete.md ├── update.md ├── commands.md ├── log.md ├── util.md └── auth.md ├── LICENSE.txt ├── examples ├── ep-tags.py ├── user-tags.py ├── integrations.py ├── team-users-and-tags.py ├── snow_pass.py ├── ep-rules-list-targets.py ├── schedule_coverage.py ├── user-create-delete.py ├── all_oncalls_with_contacts.py ├── alert_compression.py ├── README.md └── basic_incident_details.py ├── README.md ├── install-rc.sh └── install.sh /.eslintignore: -------------------------------------------------------------------------------- 1 | /lib 2 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 16.19.0 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export {run} from '@oclif/core' 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | nodejs 16.19.0 2 | yarn 1.22.19 3 | -------------------------------------------------------------------------------- /bin/dev.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | node "%~dp0\dev" %* 4 | -------------------------------------------------------------------------------- /bin/run.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | node "%~dp0\run" %* 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "oclif", 4 | "oclif-typescript" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require ts-node/register 2 | --watch-extensions ts 3 | --recursive 4 | --reporter spec 5 | --timeout 5000 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *-debug.log 2 | *-error.log 3 | /.nyc_output 4 | /dist 5 | /lib 6 | /package-lock.json 7 | /tmp 8 | node_modules 9 | .DS_Store 10 | .envrc 11 | -------------------------------------------------------------------------------- /bin/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const oclif = require('@oclif/core') 4 | 5 | oclif.run().then(require('@oclif/core/flush')).catch(require('@oclif/core/handle')) -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "compilerOptions": { 4 | "noEmit": true 5 | }, 6 | "references": [ 7 | {"path": ".."} 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /src/hooks/init/set-global-config.ts: -------------------------------------------------------------------------------- 1 | import {Hook} from '@oclif/core' 2 | 3 | const globalAny: any = global 4 | 5 | const hook: Hook<'init'> = async function (opts) { 6 | globalAny.config = opts.config 7 | } 8 | 9 | export default hook 10 | -------------------------------------------------------------------------------- /test/commands/set-global-config.test.ts: -------------------------------------------------------------------------------- 1 | import {expect, test} from '@oclif/test' 2 | 3 | describe('hooks', () => { 4 | test 5 | .stdout() 6 | .hook('init', {id: 'mycommand'}) 7 | .do(output => expect(output.stdout).to.contain('example hook running mycommand')) 8 | .it('shows a message') 9 | }) 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "importHelpers": true, 5 | "module": "commonjs", 6 | "outDir": "lib", 7 | "rootDir": "src", 8 | "strict": true, 9 | "target": "es2020", 10 | "esModuleInterop": true 11 | }, 12 | "include": [ 13 | "src/**/*" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /test/commands/hello.test.ts: -------------------------------------------------------------------------------- 1 | import {expect, test} from '@oclif/test' 2 | 3 | describe('hello', () => { 4 | test 5 | .stdout() 6 | .command(['hello']) 7 | .it('runs hello', ctx => { 8 | expect(ctx.stdout).to.contain('hello world') 9 | }) 10 | 11 | test 12 | .stdout() 13 | .command(['hello', '--name', 'jeff']) 14 | .it('runs hello --name jeff', ctx => { 15 | expect(ctx.stdout).to.contain('hello jeff') 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /bin/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const oclif = require('@oclif/core') 4 | 5 | const path = require('path') 6 | const project = path.join(__dirname, '..', 'tsconfig.json') 7 | 8 | // In dev mode -> use ts-node and dev plugins 9 | process.env.NODE_ENV = 'development' 10 | 11 | require('ts-node').register({project}) 12 | 13 | // In dev mode, always show stack traces 14 | oclif.settings.debug = true; 15 | 16 | // Start the CLI 17 | oclif.run().then(oclif.flush).catch(oclif.Errors.handle) 18 | -------------------------------------------------------------------------------- /docs/help.md: -------------------------------------------------------------------------------- 1 | `pd help` 2 | ========= 3 | 4 | Display help for pd. 5 | 6 | * [`pd help [COMMANDS]`](#pd-help-commands) 7 | 8 | ## `pd help [COMMANDS]` 9 | 10 | Display help for pd. 11 | 12 | ``` 13 | USAGE 14 | $ pd help [COMMANDS] [-n] 15 | 16 | ARGUMENTS 17 | COMMANDS Command to show help for. 18 | 19 | FLAGS 20 | -n, --nested-commands Include all nested commands in the output. 21 | 22 | DESCRIPTION 23 | Display help for pd. 24 | ``` 25 | 26 | _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v5.2.4/src/commands/help.ts)_ 27 | -------------------------------------------------------------------------------- /docs/version.md: -------------------------------------------------------------------------------- 1 | `pd version` 2 | ============ 3 | 4 | 5 | 6 | * [`pd version`](#pd-version) 7 | 8 | ## `pd version` 9 | 10 | ``` 11 | USAGE 12 | $ pd version [--json] [--verbose] 13 | 14 | FLAGS 15 | --verbose Show additional information about the CLI. 16 | 17 | GLOBAL FLAGS 18 | --json Format output as json. 19 | 20 | FLAG DESCRIPTIONS 21 | --verbose Show additional information about the CLI. 22 | 23 | Additionally shows the architecture, node version, operating system, and versions of plugins that the CLI is using. 24 | ``` 25 | 26 | _See code: [@oclif/plugin-version](https://github.com/oclif/plugin-version/blob/v1.2.1/src/commands/version.ts)_ 27 | -------------------------------------------------------------------------------- /src/commands/util/timestamp.ts: -------------------------------------------------------------------------------- 1 | import { BaseCommand } from '../../base/base-command' 2 | import * as chrono from 'chrono-node' 3 | 4 | export default class UtilTimestamp extends BaseCommand { 5 | static description = 'Make ISO8601 timestamps' 6 | 7 | static strict = false 8 | 9 | static args = [ 10 | { 11 | name: 'date', 12 | description: 'A human-style date/time, like "4pm 1/1/2021" or "Dec 2 1pm", etc. Default: now', 13 | }, 14 | ] 15 | 16 | async run() { 17 | let dateObj 18 | if (this.argv.length > 0) { 19 | dateObj = chrono.strict.parseDate(this.argv.join(' ')) 20 | } 21 | if (!dateObj) { 22 | dateObj = new Date() 23 | } 24 | this.log(dateObj.toISOString()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docs/autocomplete.md: -------------------------------------------------------------------------------- 1 | `pd autocomplete` 2 | ================= 3 | 4 | display autocomplete installation instructions 5 | 6 | * [`pd autocomplete [SHELL]`](#pd-autocomplete-shell) 7 | 8 | ## `pd autocomplete [SHELL]` 9 | 10 | display autocomplete installation instructions 11 | 12 | ``` 13 | USAGE 14 | $ pd autocomplete [SHELL] [-r] 15 | 16 | ARGUMENTS 17 | SHELL shell type 18 | 19 | FLAGS 20 | -r, --refresh-cache Refresh cache (ignores displaying instructions) 21 | 22 | DESCRIPTION 23 | display autocomplete installation instructions 24 | 25 | EXAMPLES 26 | $ pd autocomplete 27 | 28 | $ pd autocomplete bash 29 | 30 | $ pd autocomplete zsh 31 | 32 | $ pd autocomplete --refresh-cache 33 | ``` 34 | 35 | _See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v1.4.6/src/commands/autocomplete/index.ts)_ 36 | -------------------------------------------------------------------------------- /src/commands/tag/list.ts: -------------------------------------------------------------------------------- 1 | import { ListBaseCommand } from '../../base/list-base-command' 2 | 3 | export default class TagList extends ListBaseCommand { 4 | static description = 'List PagerDuty Tags' 5 | 6 | async run() { 7 | const params: Record = { 8 | } 9 | 10 | if (this.flags.name) { 11 | params.query = this.flags.name 12 | } 13 | 14 | let tags = await this.pd.fetchWithSpinner('tags', { 15 | params, 16 | activityDescription: 'Getting tags from PD', 17 | fetchLimit: this.flags.limit, 18 | }) 19 | 20 | if (tags.length === 0) { 21 | this.error('No tags found.', { exit: 1 }) 22 | } 23 | if (this.flags.json) { 24 | await this.printJsonAndExit(tags) 25 | } 26 | 27 | const columns: Record = { 28 | id: { 29 | header: 'ID', 30 | }, 31 | summary: { 32 | header: 'Name', 33 | }, 34 | } 35 | 36 | this.printTable(tags, columns, this.flags) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/commands/team/list.ts: -------------------------------------------------------------------------------- 1 | import { ListBaseCommand } from '../../base/list-base-command' 2 | 3 | export default class TeamList extends ListBaseCommand { 4 | static pdObjectName = 'team' 5 | static pdObjectNamePlural = 'teams' 6 | static description = 'List PagerDuty Teams' 7 | 8 | async run() { 9 | const params: Record = {} 10 | 11 | if (this.flags.name) { 12 | params.query = this.flags.name 13 | } 14 | 15 | const teams = await this.pd.fetchWithSpinner('teams', { 16 | params: params, 17 | activityDescription: 'Getting teams from PD', 18 | fetchLimit: this.flags.limit, 19 | }) 20 | 21 | if (this.flags.json) { 22 | await this.printJsonAndExit(teams) 23 | } 24 | 25 | const columns: Record = { 26 | id: { 27 | header: 'ID', 28 | }, 29 | summary: { 30 | header: 'Name', 31 | }, 32 | description: { 33 | extended: true, 34 | }, 35 | } 36 | 37 | this.printTable(teams, columns, this.flags) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/commands/auth/use.ts: -------------------------------------------------------------------------------- 1 | import { BaseCommand } from '../../base/base-command' 2 | import { Flags } from '@oclif/core' 3 | import chalk from 'chalk' 4 | import { Config } from '../../config' 5 | 6 | export default class AuthUse extends BaseCommand { 7 | static description = 8 | 'Choose a saved authenticated PagerDuty domain to use with all pd commands' 9 | 10 | static flags = { 11 | alias: Flags.string({ 12 | char: 'a', 13 | description: 'The alias of the PD domain to use', 14 | required: true, 15 | }), 16 | } 17 | 18 | async run() { 19 | const config = new Config() 20 | if (config.setDefaultAlias(this.flags.alias)) { 21 | this.log( 22 | `You are logged in to ${chalk.bold.blue( 23 | config.getCurrentSubdomain() 24 | )} as ${chalk.bold.blue( 25 | config.get()?.user?.email || 'nobody' 26 | )} (alias: ${chalk.bold.blue(config.defaultAlias())})` 27 | ) 28 | } else { 29 | this.error('No such alias', { suggestions: ['pd auth:list'], exit: 1 }) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/update.md: -------------------------------------------------------------------------------- 1 | `pd update` 2 | =========== 3 | 4 | update the pd CLI 5 | 6 | * [`pd update [CHANNEL]`](#pd-update-channel) 7 | 8 | ## `pd update [CHANNEL]` 9 | 10 | update the pd CLI 11 | 12 | ``` 13 | USAGE 14 | $ pd update [CHANNEL] [-a] [-v | -i] [--force] 15 | 16 | FLAGS 17 | -a, --available Install a specific version. 18 | -i, --interactive Interactively select version to install. This is ignored if a channel is provided. 19 | -v, --version= Install a specific version. 20 | --force Force a re-download of the requested version. 21 | 22 | DESCRIPTION 23 | update the pd CLI 24 | 25 | EXAMPLES 26 | Update to the stable channel: 27 | 28 | $ pd update stable 29 | 30 | Update to a specific version: 31 | 32 | $ pd update --version 1.0.0 33 | 34 | Interactively select version: 35 | 36 | $ pd update --interactive 37 | 38 | See available versions: 39 | 40 | $ pd update --available 41 | ``` 42 | 43 | _See code: [@oclif/plugin-update](https://github.com/oclif/plugin-update/blob/v3.1.4/src/commands/update.ts)_ 44 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Martin Stone 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/ep-tags.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import csv 4 | import json 5 | import subprocess 6 | import argparse 7 | 8 | parser = argparse.ArgumentParser('Get escalation policies with teams and tags') 9 | parser.add_argument('-o', '--output_file', help="File to write CSV results", required=True) 10 | args = parser.parse_args() 11 | 12 | def runcmd(cmd): 13 | r = subprocess.run(cmd, shell=True, capture_output=True) 14 | return json.loads(r.stdout) 15 | 16 | print(f"Getting escalation policies... ", end='', flush=True) 17 | eps = runcmd(f"pd ep:list -j") 18 | print(f"got {len(eps)}") 19 | 20 | rows = [] 21 | for ep in eps: 22 | print(f"Getting tags for {ep['name']}... ", end='', flush=True) 23 | ep['tags'] = runcmd(f"pd rest:fetch -e escalation_policies/{ep['id']}/tags") 24 | print(f"got {len(ep['tags'])}") 25 | rows.append([ 26 | ep['id'], 27 | ep['name'], 28 | "\n".join([t['summary'] for t in ep['teams']]), 29 | "\n".join([t['summary'] for t in ep['tags']]) 30 | ]) 31 | 32 | f = open(args.output_file, "w") 33 | w = csv.writer(f) 34 | w.writerow(["Escalation Policy ID", "Escalation Policy Name", "Team Names", "Tag Names"]) 35 | w.writerows(rows) -------------------------------------------------------------------------------- /examples/user-tags.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import csv 4 | import json 5 | import subprocess 6 | import argparse 7 | 8 | parser = argparse.ArgumentParser('Get users with tags') 9 | parser.add_argument('-o', '--output_file', help="File to write CSV results", required=True) 10 | args = parser.parse_args() 11 | 12 | def runcmd(cmd): 13 | r = subprocess.run(cmd, shell=True, capture_output=True) 14 | return json.loads(r.stdout) 15 | 16 | print(f"Getting users... ", end='', flush=True) 17 | users = runcmd(f"pd user:list -j") 18 | print(f"got {len(users)}") 19 | 20 | rows = [] 21 | for user in users: 22 | print(f"Getting tags for {user['email']}... ", end='', flush=True) 23 | user['tags'] = runcmd(f"pd rest:fetch -e users/{user['id']}/tags") 24 | print(f"got {len(user['tags'])}") 25 | rows.append([ 26 | user['id'], 27 | user['name'], 28 | user['email'], 29 | user['role'], 30 | "\n".join([t['summary'] for t in user['teams']]), 31 | "\n".join([t['summary'] for t in user['tags']]) 32 | ]) 33 | 34 | f = open(args.output_file, "w") 35 | w = csv.writer(f) 36 | w.writerow(["User ID", "User Name", "User Email", "User Role", "Team Names", "Tag Names"]) 37 | w.writerows(rows) -------------------------------------------------------------------------------- /src/commands/auth/list.ts: -------------------------------------------------------------------------------- 1 | import { BaseCommand } from '../../base/base-command' 2 | import { CliUx } from '@oclif/core' 3 | import { Config } from '../../config' 4 | 5 | export default class AuthList extends BaseCommand { 6 | static description = 'List authenticated PagerDuty domains' 7 | 8 | async run() { 9 | this.requireAuth() 10 | const config = new Config() 11 | const subdomains = config.all() 12 | const defaultAlias = config.defaultAlias() 13 | 14 | const columns: Record = { 15 | default: { 16 | get: (row: any) => (row.alias === defaultAlias ? ' ✅' : ''), 17 | }, 18 | alias: {}, 19 | subdomain: {}, 20 | email: { 21 | get: (row: { user: any }) => row.user?.email || '', 22 | }, 23 | type: { 24 | get: (row: any) => { 25 | if (row.accessToken) { 26 | return 'OAuth' 27 | } 28 | if (row.legacyToken) { 29 | if (row.isDomainToken) { 30 | return 'Legacy (Global)' 31 | } 32 | return 'Legacy (User)' 33 | } 34 | }, 35 | }, 36 | } 37 | 38 | this.printTable(subdomains, columns, {}) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/commands/field/schema/assignment/remove.ts: -------------------------------------------------------------------------------- 1 | import { AuthenticatedBaseCommand } from '../../../../base/authenticated-base-command' 2 | import {CliUx, Flags} from '@oclif/core' 3 | import chalk from 'chalk' 4 | 5 | export default class FieldSchemaAssignmentRemove extends AuthenticatedBaseCommand { 6 | static description = 'Remove a PagerDuty Custom Field Schema Assignment' 7 | 8 | static flags = { 9 | id: Flags.string({ 10 | char: 'i', 11 | description: 'The ID of a Field Schema Assignment to remove.', 12 | required: true, 13 | }), 14 | } 15 | 16 | async run() { 17 | const headers = { 18 | 'X-EARLY-ACCESS': 'flex-service-early-access', 19 | } 20 | 21 | const { 22 | id: assignment_id, 23 | } = this.flags 24 | 25 | CliUx.ux.action.start(`Removing PagerDuty field schema assignment ${chalk.bold.blue(assignment_id)}`) 26 | const r = await this.pd.request({ 27 | endpoint: `customfields/schema_assignments/${assignment_id}`, 28 | method: 'DELETE', 29 | headers, 30 | }) 31 | if (r.isFailure) { 32 | this.error(`Request failed: ${r.getFormattedError()}`, {exit: 1}) 33 | } 34 | CliUx.ux.action.stop(chalk.bold.green('done')) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/integrations.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import csv 4 | import json 5 | import subprocess 6 | import argparse 7 | 8 | parser = argparse.ArgumentParser('Get integrations for all services') 9 | parser.add_argument('-o', '--output_file', help="File to write CSV results", required=True) 10 | args = parser.parse_args() 11 | 12 | def runcmd(cmd): 13 | r = subprocess.run(cmd, shell=True, capture_output=True) 14 | return json.loads(r.stdout) 15 | 16 | print(f"Getting services with integrations... ", end='', flush=True) 17 | services = runcmd(f"pd rest fetch -e services -P \"include[]=integrations\"") 18 | print(f"got {len(services)}") 19 | 20 | rows = [] 21 | for service in services: 22 | for integration in service['integrations']: 23 | rows.append([ 24 | service['id'], 25 | service['name'], 26 | integration['id'], 27 | integration['summary'], 28 | integration['type'], 29 | integration['integration_key'] if 'integration_key' in integration else integration['integration_email'] 30 | ]) 31 | 32 | f = open(args.output_file, "w") 33 | w = csv.writer(f) 34 | w.writerow([ 35 | 'Service ID', 36 | 'Service Name', 37 | 'Integration ID', 38 | 'Integration Name', 39 | 'Integration Type', 40 | 'Integration Key/Address', 41 | ]) 42 | w.writerows(rows) -------------------------------------------------------------------------------- /docs/commands.md: -------------------------------------------------------------------------------- 1 | `pd commands` 2 | ============= 3 | 4 | list all the commands 5 | 6 | * [`pd commands`](#pd-commands) 7 | 8 | ## `pd commands` 9 | 10 | list all the commands 11 | 12 | ``` 13 | USAGE 14 | $ pd commands [--json] [-h] [--hidden] [--tree] [--columns | -x] [--sort ] [--filter ] 15 | [--output csv|json|yaml | | [--csv | --no-truncate]] [--no-header | ] 16 | 17 | FLAGS 18 | -h, --help Show CLI help. 19 | -x, --extended show extra columns 20 | --columns= only show provided columns (comma-separated) 21 | --csv output is csv format [alias: --output=csv] 22 | --filter= filter property by partial string matching, ex: name=foo 23 | --hidden show hidden commands 24 | --no-header hide table header from output 25 | --no-truncate do not truncate output to fit screen 26 | --output=