Skip to content

Commit

Permalink
Merge pull request #101 from backtrace-labs/stone/T33948
Browse files Browse the repository at this point in the history
Document Attributes, add Query Views
  • Loading branch information
stonefollari authored Apr 5, 2023
2 parents 6f1c00a + d1203d2 commit a925127
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 4 deletions.
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1524,3 +1524,45 @@ For example:
```
morgue actions upload --project myproj myconfig.json
```


## Attributes

Morgue can be used to create or delete project index attributes.

The provided commands are as follows:
- `morgue attribute create <project> <name> --description --type --format ` : Create a project index attribute
- `morgue attribute delete <project> <name> ` : Delete a project index attribute

Formats
- `bitmap`, `uint8`, `uint16`, `uint32`, `uint64`, `uint128`, `uuid`, `dictionary`

Types
- `none`, `commit`, `semver`, `callstack`, `hostname`, `bytes`, `kilobytes`, `gigabytes`, `nanoseconds`, `milliseconds`, `seconds`, `unix_timestamp`, `js_timestamp`, `gps_timestamp`, `memory_address`, `labels`, `sha256`, `uuid`, `ipv4`, `ipv6`

For example:

```
morgue attribute create myProject myAttribute --description='My Description' --type='uint64' --format='bytes'
```
```
morgue attribute delete myProject myAttribute
```

## Views

Morgue can be used to create or delete project query views.

The provided commands are as follows:

- `morgue view create <project> <name> <queries> <payload>` : Create a query view.
- `morgue view delete <project> <name>` : Delete query view.

For example:

```
morgue view create myProject myQueryViewName --queries=queries.json --payload=payload.json
```
```
morgue view delete myProject myQueryViewName
```
145 changes: 142 additions & 3 deletions bin/morgue.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ var commands = {
actions: coronerActions,
attachment: coronerAttachment,
attribute: coronerAttribute,
view: coronerView,
audit: coronerAudit,
project: coronerProject,
log: coronerLog,
Expand Down Expand Up @@ -4636,15 +4637,103 @@ function subcmdProcess(argv, config, opts) {
opts.usageFn("Invalid subcommand '" + subcmd + "'.");
}

function viewUsageFn(str){
if (str) {
err(str + "\n");
}
console.error("Usage: morgue view <create|delete> <project> <name> <queries> <payload>");
process.exit(1);
}

function viewSetupFn(config, argv, opts, subcmd) {
if (argv.length < 4) {
return attributeUsageFn("Incomplete command.");
}

opts.params = {
attrname: argv._[2],
};
if (!opts.params.attrname)
return viewUsageFn("Missing attribute name.");

opts.state.bpg = coronerBpgSetup(opts.state.coroner, argv);
opts.state.model = opts.state.bpg.get();
opts.state.context = coronerParams(argv, config);

const ctx = opts.state.context;
opts.state.universe = opts.state.model.universe.find((univ) => {
return univ.fields.name === ctx.universe;
});
if (!opts.state.universe)
return viewUsageFn(`Universe ${ctx.universe} not found.`);
opts.state.project = opts.state.model.project.find((proj) =>
proj.fields.universe === opts.state.universe.fields.id &&
proj.fields.name === ctx.project
);
if (!opts.state.project) {
return viewUsageFn( `Project ${ctx.universe}/${ctx.project} not found.`);
}

if (subcmd !== 'create') {
opts.state.query = opts.state.model.query.find((query) =>
query.fields.name === opts.params.attrname
);
if (!opts.state.query)
return viewUsageFn("View not found.");
opts.state.attr_key = {
project: opts.state.query.fields.project,
name: opts.state.query.fields.name,
};
}
}

function attributeUsageFn(str) {
const formats = [
'none',
'commit',
'semver',
'callstack',
'hostname',
'bytes',
'kilobytes',
'gigabytes',
'nanoseconds',
'milliseconds',
'seconds',
'unix_timestamp',
'js_timestamp',
'gps_timestamp',
'memory_address',
'labels',
'sha256',
'uuid',
'ipv4',
'ipv6',
]

const types = [
'bitmap',
'uint8',
'uint16',
'uint32',
'uint64',
'uint128',
'uuid',
'dictionary',
]

if (str)
err(str + "\n");
console.error("Usage: morgue attribute <create|delete> <project> <name> [options]");
console.error("");
console.error("Options for create (all but format are required):");
console.error(" --type=T Specify type.");
console.error("Options for create (all but format are required): ");
console.error(" --description=D Specify description.");
console.error(" --format=F Specify formatting hint.");
console.error(" --type=T Specify type. Can be of the following: ");
console.error(" " + types.join(', '))
console.error(" --format=F Specify formatting hint. Can be of the following: ");
console.error(" " + formats.slice(0, 10).join(', ') + ', ')
console.error(" " + formats.slice(10).join(', '))

process.exit(1);
}

Expand Down Expand Up @@ -4722,6 +4811,45 @@ function attributeSet(argv, config, opts) {
bpgPost(state.bpg, request, bpgCbFn('Attribute', 'update'));
}

function viewCreate(argv, config, opts) {
const state = opts.state;

if (!argv.queries) return viewUsageFn("Must specify queries.");
if (!argv.payload) return viewUsageFn("Must specify payload.");
if(!state.project.fields && !state.project.fields.pid) return viewUsageFn("Invalid Project.");
if(!config.config.uid) return viewUsageFn("Invalid user.");

// json parse or keep input as json
const queries = typeof argv.queries === 'string' ? JSON.parse(argv.queries) : argv.queries
const payload = typeof argv.payload === 'string' ? JSON.parse(argv.payload) : argv.payload
// update name
payload.name = opts.params.attrname

const request = bpgSingleRequest({
action: "create",
type: "configuration/query",
object: {
name: opts.params.attrname,
project: state.project.fields.pid,
owner: config.config.uid,
queries: JSON.stringify(queries),
payload: JSON.stringify(payload),
},
});

bpgPost(state.bpg, request, bpgCbFn('View', 'create'));
}

function viewDelete(argv, config, opts) {
const state = opts.state;
const request = bpgSingleRequest({
action: "delete",
type: "configuration/query",
key: state.attr_key,
});
bpgPost(state.bpg, request, bpgCbFn('View', 'delete'));
}

function attributeDelete(argv, config, opts) {
const state = opts.state;
const request = bpgSingleRequest({
Expand Down Expand Up @@ -4765,6 +4893,17 @@ function coronerAttribute(argv, config) {
});
}

function coronerView(argv, config) {
subcmdProcess(argv, config, {
usageFn: viewUsageFn,
setupFn: viewSetupFn,
subcmds: {
create: viewCreate,
delete: viewDelete,
},
});
}

/*
* Print frames in j, relative to availability in k. Different functions
* are bolded accordingly.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "backtrace-morgue",
"version": "1.22.1",
"version": "1.23.0",
"description": "command line interface to the Backtrace object store",
"main": "./lib/coroner.js",
"keywords": [
Expand Down

0 comments on commit a925127

Please sign in to comment.