这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
8607799
console: add event triggers wip
praveenweb Aug 22, 2018
7107221
event triggers wip
praveenweb Aug 23, 2018
592debf
event triggers v1
praveenweb Aug 24, 2018
aa4c2bd
Merge remote-tracking branch 'origin/master' into console-event-triggers
praveenweb Aug 24, 2018
960ca76
breadcrumb fix
praveenweb Aug 24, 2018
fcb0f44
console: add watch and settings to a table ui
praveenweb Aug 27, 2018
f333400
init
tirumaraiselvan Aug 13, 2018
a28c8c3
take triggername and store trigger definition
tirumaraiselvan Aug 14, 2018
25de873
use mustache instead of ginger
tirumaraiselvan Aug 14, 2018
d49a29a
qualify columns
tirumaraiselvan Aug 14, 2018
7f4cf05
create event queue
tirumaraiselvan Aug 16, 2018
b74746a
add http and logging capability
tirumaraiselvan Aug 18, 2018
8c8d01c
add event trigger in schema cache
tirumaraiselvan Aug 21, 2018
249455a
getdependents and deletefromcache functions
tirumaraiselvan Aug 21, 2018
1ebbd68
invoke webhook
tirumaraiselvan Aug 22, 2018
9c3220b
fix: send op var
tirumaraiselvan Aug 22, 2018
fc927cf
implement retry
tirumaraiselvan Aug 23, 2018
4046090
create hasura metadata for event tables
tirumaraiselvan Aug 24, 2018
f350079
implement unsubscribe_table query
tirumaraiselvan Aug 24, 2018
c7882d4
clear trigger functions on init
tirumaraiselvan Aug 24, 2018
0732d58
use object instead of array relationship
tirumaraiselvan Aug 24, 2018
49dc83f
change to hdb_views
tirumaraiselvan Aug 24, 2018
cebb8b3
update cache during subscribe/unsubscribe
tirumaraiselvan Aug 24, 2018
4b4f2c9
limit on number of events per batch
tirumaraiselvan Aug 24, 2018
5daa8de
change eventtrigger schema object and recreate triggers after runsql
tirumaraiselvan Aug 27, 2018
ba50d57
change event_id to UUID
tirumaraiselvan Aug 28, 2018
9e76d8a
validate all columns exist in P1
tirumaraiselvan Aug 28, 2018
7629d7b
add any body type in HTTP library
tirumaraiselvan Aug 28, 2018
150e95e
implement metadata for event triggers
tirumaraiselvan Aug 29, 2018
52ee35e
console: add trigger ux, logs in tabs
praveenweb Aug 29, 2018
bace963
Merge remote-tracking branch 'origin/console-event-triggers' into HEAD
praveenweb Aug 29, 2018
ee2788d
fix rebase issues
tirumaraiselvan Aug 29, 2018
d561773
update metadata in cli tests
shahidhk Aug 29, 2018
cd2da8f
console: update limit in queries
praveenweb Aug 30, 2018
2b35213
Merge remote-tracking branch 'origin/console-event-triggers' into HEAD
praveenweb Aug 30, 2018
59f0a51
console: fix delete operation
praveenweb Aug 30, 2018
cc86eed
remove webhook from event_log and fetch from schema cache
tirumaraiselvan Aug 30, 2018
39a28e0
console: fix add trigger state
praveenweb Aug 30, 2018
686ac74
Merge branch 'skor' of github.com:tirumaraiselvan/graphql-engine into…
praveenweb Aug 30, 2018
4e8a161
append () for backward compatibility
tirumaraiselvan Aug 31, 2018
e4d113c
console: add trigger validations, migrations fix
praveenweb Aug 31, 2018
f27a4cf
Merge branch 'skor' of github.com:tirumaraiselvan/graphql-engine into…
praveenweb Aug 31, 2018
5923ff1
Merge remote-tracking branch 'upstream/master' into HEAD
praveenweb Aug 31, 2018
6f9a2c6
add old and new row updates in payload
tirumaraiselvan Aug 31, 2018
48c251a
update test
tirumaraiselvan Aug 31, 2018
0f36424
send event id and trigger name in payload
tirumaraiselvan Aug 31, 2018
495f564
console: change button type advanced settings
praveenweb Sep 3, 2018
b1ece51
Merge branch 'skor' of github.com:tirumaraiselvan/graphql-engine into…
praveenweb Sep 3, 2018
20e6d9b
1) make fetchevents lock first for horizontal scalability, 2) place r…
tirumaraiselvan Sep 3, 2018
70fccdd
console: retry conf handling updated
praveenweb Sep 3, 2018
957220f
take polling interval and max http connections as configurable params
tirumaraiselvan Sep 3, 2018
26dd7e7
remake triggers on buildSchemaCache
tirumaraiselvan Sep 3, 2018
8a2c313
dont need to wrap EventEngineCtx in TVar
tirumaraiselvan Sep 4, 2018
ae67746
break process event function
tirumaraiselvan Sep 4, 2018
809fc05
no need to lock event as it will already be locked
tirumaraiselvan Sep 4, 2018
8d5fabf
log all errors in EngineLogType
tirumaraiselvan Sep 4, 2018
8ff6064
convert all errors to EngineLogType
tirumaraiselvan Sep 4, 2018
ddfd0d6
console: add test for event triggers
praveenweb Sep 4, 2018
bc3c9f8
Merge remote-tracking branch 'tiru/skor' into HEAD
praveenweb Sep 4, 2018
70f4dce
change ginger to upstream repo and no-ops
tirumaraiselvan Sep 4, 2018
fcf0ab4
add trigger id to event log
tirumaraiselvan Sep 4, 2018
a790ced
no-op: moving files and imports
tirumaraiselvan Sep 4, 2018
d790522
change polling interval
tirumaraiselvan Sep 4, 2018
cf60cda
read env vars safely
tirumaraiselvan Sep 4, 2018
a7a3a38
change interval_seconds -> retry_interval
tirumaraiselvan Sep 4, 2018
e127af1
fix reading env vars
tirumaraiselvan Sep 4, 2018
8c2a446
rename subscribe_table -> create_event_trigger
tirumaraiselvan Sep 4, 2018
b886167
Merge remote-tracking branch 'upstream/master' into skor
tirumaraiselvan Sep 4, 2018
99486d8
make hlogger ctx and change time format
tirumaraiselvan Sep 4, 2018
6ff3b32
take extra log as params to runHTTP
tirumaraiselvan Sep 4, 2018
e701fbc
rename extraLog to extraContext
tirumaraiselvan Sep 4, 2018
a3d87e7
fix test
tirumaraiselvan Sep 4, 2018
a662dc3
console: add running events, update apis
praveenweb Sep 4, 2018
a03f93f
Merge remote-tracking branch 'tiru/skor' into HEAD
praveenweb Sep 4, 2018
1f08c9f
console: update tries gte -> gt
praveenweb Sep 4, 2018
444d5fa
rename skor -> hasura
tirumaraiselvan Sep 5, 2018
1530979
force regex check for event trigger name
tirumaraiselvan Sep 5, 2018
ca83351
send metadata in event payload (and remove metadata from trigger func…
tirumaraiselvan Sep 5, 2018
ecebf9e
console: remove expand icon, filter views, fetch events by triggerName
praveenweb Sep 5, 2018
9bebada
Merge remote-tracking branch 'tiru/skor' into HEAD
praveenweb Sep 5, 2018
ad25d9e
add request to invocation log as well
tirumaraiselvan Sep 5, 2018
d81eb48
define generic getFromEnv with defaults
tirumaraiselvan Sep 5, 2018
43c8983
remove insecure http session manager
tirumaraiselvan Sep 5, 2018
d345779
change trigger.sql -> trigger.sql.j2
tirumaraiselvan Sep 5, 2018
5127b84
console: fix state, streaming logs wip
praveenweb Sep 5, 2018
e06aef4
Merge remote-tracking branch 'tiru/skor' into HEAD
praveenweb Sep 5, 2018
f0e0b5a
simplify trigger drop function and quote_ident
tirumaraiselvan Sep 5, 2018
3f61ed5
throw400 instead of throw404
tirumaraiselvan Sep 5, 2018
32e94d4
Merge branch 'master' into skor
0x777 Sep 5, 2018
a3aa3b5
use assertPGCol
tirumaraiselvan Sep 5, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cli/commands/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var testMetadata = map[string][]byte{
tables:
- array_relationships: []
delete_permissions: []
event_triggers: []
insert_permissions: []
object_relationships: []
select_permissions: []
Expand Down
20 changes: 20 additions & 0 deletions console/cypress/helpers/eventHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const baseUrl = Cypress.config('baseUrl');
export const queryTypes = ['insert', 'update', 'delete'];
export const getTriggerName = (i, testName = '') =>
`apic_test_trigger_${testName}_${i}`;
export const getTableName = (i, testName = '') =>
`apic_test_table_${testName}_${i}`;
export const getWebhookURL = () => 'http://httpbin.org/post';
export const getNoOfRetries = () => '5';
export const getIntervalSeconds = () => '10';
export const getElementFromAlias = alias => `[data-test=${alias}]`;
export const makeDataAPIUrl = dataApiUrl => `${dataApiUrl}/v1/query`;
export const makeDataAPIOptions = (dataApiUrl, key, body) => ({
method: 'POST',
url: makeDataAPIUrl(dataApiUrl),
headers: {
'x-hasura-access-key': key,
},
body,
failOnStatusCode: false,
});
2 changes: 1 addition & 1 deletion console/cypress/integration/data/permissions/spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { testPermissions, permRemove, createView, trackView } from './utils';
const testName = 'perm';

export const passPTCreateTable = () => {
// Click on create tabel
// Click on create table
cy.get(getElementFromAlias('data-create-table')).click();
// Match the URL
cy.url().should('eq', `${baseUrl}/data/schema/public/table/add`);
Expand Down
188 changes: 188 additions & 0 deletions console/cypress/integration/events/create-trigger/spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import {
getElementFromAlias,
getTableName,
getTriggerName,
getWebhookURL,
getNoOfRetries,
getIntervalSeconds,
baseUrl,
} from '../../../helpers/eventHelpers';
import { getColName } from '../../../helpers/dataHelpers';
import {
setMetaData,
validateCT,
validateCTrigger,
validateInsert,
} from '../../validators/validators';

const testName = 'ctr'; // create trigger

export const visitEventsManagePage = () => {
cy.visit('/events/manage');
};

export const passPTCreateTable = () => {
// Click on create table
cy.get(getElementFromAlias('data-create-table')).click();
// Match the URL
cy.url().should('eq', `${baseUrl}/data/schema/public/table/add`);
// Type table name
cy.get(getElementFromAlias('tableName')).type(getTableName(0, testName));
// Set first column
cy.get(getElementFromAlias('column-0')).type(getColName(0));
cy.get(getElementFromAlias('col-type-0')).select('serial');
// Set second column
cy.get(getElementFromAlias('column-1')).type(getColName(1));
cy.get(getElementFromAlias('col-type-1')).select('integer');
// Set third column
cy.get(getElementFromAlias('column-2')).type(getColName(2));
cy.get(getElementFromAlias('col-type-2')).select('text');
// Set primary key
cy.get(getElementFromAlias('primary-key-select-0')).select('0');
// Create
cy.get(getElementFromAlias('table-create')).click();
cy.wait(7000);
cy.url().should(
'eq',
`${baseUrl}/data/schema/public/tables/${getTableName(0, testName)}/modify`
);
};

export const checkCreateTriggerRoute = () => {
// Click on the create trigger button
cy.visit('/events/manage');
cy.wait(15000);
cy.get(getElementFromAlias('data-create-trigger')).click();
// Match the URL
cy.url().should('eq', `${baseUrl}/events/manage/triggers/add`);
};

export const failCTWithoutData = () => {
// Type trigger name
cy.get(getElementFromAlias('trigger-name')).type(getTriggerName(0, testName));
// Click on create
cy.get(getElementFromAlias('trigger-create')).click();
// Check if the route didn't change
cy.url().should('eq', `${baseUrl}/events/manage/triggers/add`);
// Validate
validateCT(getTriggerName(0, testName), 'failure');
};

export const passCT = () => {
// Set trigger name and select table
cy.get(getElementFromAlias('trigger-name'))
.clear()
.type(getTriggerName(0, testName));
cy.get(getElementFromAlias('select-table')).select(getTableName(0, testName));

// operations
cy.get(getElementFromAlias('insert-operation')).check();
cy.get(getElementFromAlias('update-operation')).check();
cy.get(getElementFromAlias('delete-operation')).check();

// webhook url
cy.get(getElementFromAlias('webhook'))
.clear()
.type(getWebhookURL());

// advanced settings
cy.get(getElementFromAlias('advanced-settings')).click();

// retry configuration
cy.get(getElementFromAlias('no-of-retries')).type(getNoOfRetries());
cy.get(getElementFromAlias('interval-seconds')).type(getIntervalSeconds());

// Click on create
cy.get(getElementFromAlias('trigger-create')).click();
cy.wait(10000);
// Check if the trigger got created and navigated to processed events page
cy.url().should(
'eq',
`${baseUrl}/events/manage/triggers/${getTriggerName(0, testName)}/processed`
);
cy.get(getElementFromAlias(getTriggerName(0, testName)));
// Validate
validateCTrigger(getTriggerName(0, testName), 'success');
};

export const failCTDuplicateTrigger = () => {
// Visit create trigger page
cy.visit('/events/manage/triggers/add');
// trigger and table name
cy.get(getElementFromAlias('trigger-name'))
.clear()
.type(getTriggerName(0, testName));
cy.get(getElementFromAlias('select-table')).select(getTableName(0, testName));

// operations
cy.get(getElementFromAlias('insert-operation')).check();
cy.get(getElementFromAlias('update-operation')).check();
cy.get(getElementFromAlias('delete-operation')).check();

// webhook url
cy.get(getElementFromAlias('webhook'))
.clear()
.type(getWebhookURL());

// click on create
cy.get(getElementFromAlias('trigger-create')).click();
cy.wait(5000);
// should be on the same URL
cy.url().should('eq', `${baseUrl}/events/manage/triggers/add`);
};

export const insertTableRow = () => {
// visit insert row page
cy.visit(`/data/schema/public/tables/${getTableName(0, testName)}/insert`);
// one serial column. so insert a row directly.
cy.get(getElementFromAlias(`typed-input-${1}`)).type('123');
cy.get(getElementFromAlias(`typed-input-${2}`)).type('Some text');
cy.get(getElementFromAlias('insert-save-button')).click();
cy.wait(300);
validateInsert(getTableName(0, testName), 1);
// now it should invoke the trigger to webhook
cy.wait(10000);
// check if processed events has a row and it is a successful response
cy.visit(`/events/manage/triggers/${getTriggerName(0, testName)}/processed`);
cy.get(getElementFromAlias('trigger-processed-events')).contains('1');
};

export const deleteCTTestTrigger = () => {
// Go to the settings section of the trigger
cy.visit(`/events/manage/triggers/${getTriggerName(0, testName)}/processed`);
// click on settings tab
cy.get(getElementFromAlias('trigger-settings')).click();
// Click on delete
cy.get(getElementFromAlias('delete-trigger')).click();
// Confirm
cy.on('window:confirm', str => {
expect(str === 'Are you sure?').to.be.true;
return true;
});
cy.wait(7000);
// Match the URL
cy.url().should('eq', `${baseUrl}/events/manage/triggers`);
// Validate
validateCTrigger(getTriggerName(0, testName), 'success');
};

export const deleteCTTestTable = () => {
// Go to the modify section of the table
cy.visit(`/data/schema/public/tables/${getTableName(0, testName)}/modify`);
// Click on delete
cy.get(getElementFromAlias('delete-table')).click();
// Confirm
cy.on('window:confirm', str => {
expect(str === 'Are you sure?').to.be.true;
return true;
});
cy.wait(7000);
// Match the URL
cy.url().should('eq', `${baseUrl}/data/schema/public`);
// Validate
validateCT(getTableName(0, testName), 'failure');
};

export const setValidationMetaData = () => {
setMetaData();
};
51 changes: 51 additions & 0 deletions console/cypress/integration/events/create-trigger/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* eslint no-unused-vars: 0 */
/* eslint import/prefer-default-export: 0 */
import { testMode } from '../../../helpers/common';
import { setMetaData } from '../../validators/validators';

import {
passPTCreateTable,
visitEventsManagePage,
checkCreateTriggerRoute,
failCTWithoutData,
passCT,
failCTDuplicateTrigger,
failAddExistingTrigger,
insertTableRow,
deleteCTTestTrigger,
deleteCTTestTable,
} from './spec';

const setup = () => {
describe('Check Data Tab', () => {
it('Clicking on Data tab opens the correct route', () => {
// Visit the index route
cy.visit('/data/schema/public');
cy.wait(7000);
// Get and set validation metadata
setMetaData();
});
});
};

export const runCreateTriggerTests = () => {
describe('Create Trigger', () => {
it('Create table to use in triggers', passPTCreateTable);
it('Visit events manage page', visitEventsManagePage);
it(
'Create trigger button opens the correct route',
checkCreateTriggerRoute
);
it('Fails to create trigger without data', failCTWithoutData);
it('Successfuly creates trigger', passCT);
it('Fails to create duplicate trigger', failCTDuplicateTrigger);
it('Insert a row and invoke trigger', insertTableRow);
it('Delete off the test trigger', deleteCTTestTrigger);
it('Delete off the test table', deleteCTTestTable);
});
};

if (testMode !== 'cli') {
setup();
runCreateTriggerTests();
}
4 changes: 4 additions & 0 deletions console/cypress/integration/test_complete.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { runViewsTest } from './data/views/test';
import { runRawSQLTests } from './data/raw-sql/test';
import { run404Test } from './data/404/test';

import { runCreateTriggerTests } from './events/create-trigger/test';

import { runApiExplorerTests } from './api-explorer/graphql/test';

const setup = () => {
Expand All @@ -28,6 +30,8 @@ describe('Setup route', setup);

runMigrationModeTests();

runCreateTriggerTests();

runCreateTableTests();

runInsertBrowseTests();
Expand Down
21 changes: 21 additions & 0 deletions console/cypress/integration/validators/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,24 @@ export const validateMigrationMode = mode => {
expect(response.body.migration_mode == mode.toString()).to.be.true; // eslint-disable-line
});
};

// ****************** Trigger Validator *********************

export const validateCTrigger = (triggerName, result) => {
const reqBody = {
type: 'select',
args: {
table: { name: 'event_triggers', schema: 'hdb_catalog' },
columns: ['table_name'],
where: { name: triggerName },
},
};
const requestOptions = makeDataAPIOptions(dataApiUrl, accessKey, reqBody);
cy.request(requestOptions).then(response => {
if (result === 'success') {
expect(response.status === 200).to.be.true;
} else {
expect(response.status === 200).to.be.false;
}
});
};
6 changes: 5 additions & 1 deletion console/src/components/Common/Common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -466,9 +466,13 @@ input {
{
margin-bottom: 20px;
}
.add_mar_bottom_mid
{
margin-bottom: 10px;
}
.add_mar_right
{
margin-right: 20px;
margin-right: 20px !important;
}
.add_mar_right_small
{
Expand Down
21 changes: 21 additions & 0 deletions console/src/components/Main/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,27 @@ class Main extends React.Component {
</Link>
</li>
</OverlayTrigger>
<OverlayTrigger placement="right" overlay={tooltip.events}>
<li>
<Link
className={
currentActiveBlock === 'events'
? styles.navSideBarActive
: ''
}
to={appPrefix + '/events'}
>
<div className={styles.iconCenter}>
<i
title="Events"
className="fa fa-cloud"
aria-hidden="true"
/>
</div>
<p>Events</p>
</Link>
</li>
</OverlayTrigger>
</ul>
</div>
<div className={styles.clusterInfoWrapper}>{accessKeyHtml}</div>
Expand Down
4 changes: 4 additions & 0 deletions console/src/components/Main/Tooltips.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export const apiexplorer = (
<Tooltip id="tooltip-api-explorer">Test the GraphQL APIs</Tooltip>
);

export const events = (
<Tooltip id="tooltip-events">Manage Event Triggers</Tooltip>
);

export const secureEndpoint = (
<Tooltip id="tooltip-secure-endpoint">
This graphql endpoint is public and you should add an access key
Expand Down
Loading