@gnar-engine/cli 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/gnar-engine-logo-white.svg +9 -0
- package/bootstrap/deploy.localdev.yml +51 -0
- package/bootstrap/secrets.localdev.yml +27 -0
- package/bootstrap/services/agent/Dockerfile +23 -0
- package/bootstrap/services/agent/notes.md +28 -0
- package/bootstrap/services/agent/package.json +16 -0
- package/bootstrap/services/agent/src/app.js +52 -0
- package/bootstrap/services/agent/src/commands/agent.handler.js +104 -0
- package/bootstrap/services/agent/src/config.js +52 -0
- package/bootstrap/services/agent/src/controllers/http.controller.js +44 -0
- package/bootstrap/services/agent/src/controllers/message.controller.js +51 -0
- package/bootstrap/services/agent/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +36 -0
- package/bootstrap/services/agent/src/policies/agent.policy.js +13 -0
- package/bootstrap/services/agent/src/schema/Agent.schema.js +17 -0
- package/bootstrap/services/agent/src/services/agent.service.js +259 -0
- package/bootstrap/services/agent/src/services/chatgpt.service.js +46 -0
- package/bootstrap/services/agent/src/services/manifest.service.js +21 -0
- package/bootstrap/services/control/Dockerfile +23 -0
- package/bootstrap/services/control/Dockerfile.prod +37 -0
- package/bootstrap/services/control/README.md +25 -0
- package/bootstrap/services/control/package.json +16 -0
- package/bootstrap/services/control/src/app.js +45 -0
- package/bootstrap/services/control/src/commands/control.handler.js +231 -0
- package/bootstrap/services/control/src/commands/service.handler.js +81 -0
- package/bootstrap/services/control/src/commands/task.handler.js +247 -0
- package/bootstrap/services/control/src/config.js +55 -0
- package/bootstrap/services/control/src/controllers/http.controller.js +228 -0
- package/bootstrap/services/control/src/controllers/message.controller.js +40 -0
- package/bootstrap/services/control/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/control/src/db/migrations/02-control-service-init.js +60 -0
- package/bootstrap/services/control/src/db/migrations/03-alter-tasks.js +29 -0
- package/bootstrap/services/control/src/policies/task.policy.js +53 -0
- package/bootstrap/services/control/src/schema/control.schema.js +42 -0
- package/bootstrap/services/control/src/services/registry.service.js +83 -0
- package/bootstrap/services/control/src/services/reset.service.js +28 -0
- package/bootstrap/services/control/src/services/task.service.js +153 -0
- package/bootstrap/services/control/src/tests/control.test.js +50 -0
- package/bootstrap/services/notification/Dockerfile +23 -0
- package/bootstrap/services/notification/Dockerfile.prod +37 -0
- package/bootstrap/services/notification/README.md +3 -0
- package/bootstrap/services/notification/package.json +34 -0
- package/bootstrap/services/notification/src/app.js +51 -0
- package/bootstrap/services/notification/src/commands/command-bus.js +20 -0
- package/bootstrap/services/notification/src/commands/handlers/control.handler.js +18 -0
- package/bootstrap/services/notification/src/commands/handlers/notification.handler.js +157 -0
- package/bootstrap/services/notification/src/config.js +15 -0
- package/bootstrap/services/notification/src/controllers/message.controller.js +82 -0
- package/bootstrap/services/notification/src/services/logger.service.js +16 -0
- package/bootstrap/services/notification/src/services/ses.service.js +23 -0
- package/bootstrap/services/notification/src/templates/admin-order-recieved.hbs +136 -0
- package/bootstrap/services/notification/src/templates/admin-subscription-failed.hbs +87 -0
- package/bootstrap/services/notification/src/templates/customer-order-recieved.hbs +132 -0
- package/bootstrap/services/notification/src/templates/customer-subscription-failed.hbs +77 -0
- package/bootstrap/services/notification/src/tests/notification.test.js +0 -0
- package/bootstrap/services/portal/Dockerfile +23 -0
- package/bootstrap/services/portal/Dockerfile.remote +40 -0
- package/bootstrap/services/portal/README.md +22 -0
- package/bootstrap/services/portal/nginx.conf +12 -0
- package/bootstrap/services/portal/package.json +59 -0
- package/bootstrap/services/portal/public/favicon.ico +0 -0
- package/bootstrap/services/portal/public/gnar-white.png +0 -0
- package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/public/index.html +43 -0
- package/bootstrap/services/portal/public/logo192.png +0 -0
- package/bootstrap/services/portal/public/logo512.png +0 -0
- package/bootstrap/services/portal/public/manifest.json +25 -0
- package/bootstrap/services/portal/public/robots.txt +3 -0
- package/bootstrap/services/portal/src/App.js +56 -0
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +1 -0
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +1 -0
- package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +1 -0
- package/bootstrap/services/portal/src/assets/activity.svg +3 -0
- package/bootstrap/services/portal/src/assets/arrow.svg +3 -0
- package/bootstrap/services/portal/src/assets/bin-white.svg +3 -0
- package/bootstrap/services/portal/src/assets/bin.svg +3 -0
- package/bootstrap/services/portal/src/assets/check.svg +3 -0
- package/bootstrap/services/portal/src/assets/chevron.svg +3 -0
- package/bootstrap/services/portal/src/assets/contact.svg +3 -0
- package/bootstrap/services/portal/src/assets/dots-vertical.svg +5 -0
- package/bootstrap/services/portal/src/assets/eye-off.svg +3 -0
- package/bootstrap/services/portal/src/assets/eye.svg +4 -0
- package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +47 -0
- package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +47 -0
- package/bootstrap/services/portal/src/assets/gnar_engine.svg +3 -0
- package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/src/assets/home.svg +3 -0
- package/bootstrap/services/portal/src/assets/link.svg +3 -0
- package/bootstrap/services/portal/src/assets/lock.svg +3 -0
- package/bootstrap/services/portal/src/assets/package.svg +4 -0
- package/bootstrap/services/portal/src/assets/raffle.svg +3 -0
- package/bootstrap/services/portal/src/assets/settings.svg +4 -0
- package/bootstrap/services/portal/src/assets/shopping-bag.svg +3 -0
- package/bootstrap/services/portal/src/assets/user-black.svg +3 -0
- package/bootstrap/services/portal/src/assets/user.svg +3 -0
- package/bootstrap/services/portal/src/assets/users.svg +3 -0
- package/bootstrap/services/portal/src/assets/wallet.svg +3 -0
- package/bootstrap/services/portal/src/css/style.css +1007 -0
- package/bootstrap/services/portal/src/data/data.js +70 -0
- package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +32 -0
- package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +160 -0
- package/bootstrap/services/portal/src/features/crud/crudEdit.less +230 -0
- package/bootstrap/services/portal/src/features/crud/crudList.less +134 -0
- package/bootstrap/services/portal/src/features/crud/crudPage.less +31 -0
- package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +108 -0
- package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +243 -0
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +109 -0
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +315 -0
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +104 -0
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +388 -0
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +104 -0
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +208 -0
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +110 -0
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +261 -0
- package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +107 -0
- package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +402 -0
- package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +30 -0
- package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +113 -0
- package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +56 -0
- package/bootstrap/services/portal/src/features/loginForm/loginForm.less +56 -0
- package/bootstrap/services/portal/src/features/notes/Notes.jsx +18 -0
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +96 -0
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +74 -0
- package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +102 -0
- package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +24 -0
- package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +99 -0
- package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +46 -0
- package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +64 -0
- package/bootstrap/services/portal/src/features/sidebar/sidebar.less +49 -0
- package/bootstrap/services/portal/src/features/skus/Skus.jsx +109 -0
- package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +44 -0
- package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +32 -0
- package/bootstrap/services/portal/src/features/user/User.jsx +54 -0
- package/bootstrap/services/portal/src/features/user/user.less +57 -0
- package/bootstrap/services/portal/src/includes/utilities.js +259 -0
- package/bootstrap/services/portal/src/index.js +14 -0
- package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +50 -0
- package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +17 -0
- package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +48 -0
- package/bootstrap/services/portal/src/layouts/loginLayout.less +33 -0
- package/bootstrap/services/portal/src/layouts/portalLayout.less +67 -0
- package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +199 -0
- package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +17 -0
- package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +10 -0
- package/bootstrap/services/portal/src/pages/login/Login.jsx +15 -0
- package/bootstrap/services/portal/src/pages/login/login.less +10 -0
- package/bootstrap/services/portal/src/pages/orders/Orders.jsx +199 -0
- package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +15 -0
- package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +15 -0
- package/bootstrap/services/portal/src/pages/payments/Payments.jsx +10 -0
- package/bootstrap/services/portal/src/pages/portal/Portal.jsx +43 -0
- package/bootstrap/services/portal/src/pages/products/Products.jsx +212 -0
- package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +124 -0
- package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +186 -0
- package/bootstrap/services/portal/src/pages/reports/Reports.jsx +10 -0
- package/bootstrap/services/portal/src/pages/settings/Settings.jsx +10 -0
- package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +199 -0
- package/bootstrap/services/portal/src/pages/users/Users.jsx +193 -0
- package/bootstrap/services/portal/src/pages/users/users.less +25 -0
- package/bootstrap/services/portal/src/slices/authSlice.js +71 -0
- package/bootstrap/services/portal/src/store/configureStore.js +12 -0
- package/bootstrap/services/portal/src/styles/global.less +159 -0
- package/bootstrap/services/portal/src/styles/inputs.less +157 -0
- package/bootstrap/services/portal/src/styles/main.less +26 -0
- package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +97 -0
- package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +23 -0
- package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +17 -0
- package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +42 -0
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +63 -0
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +63 -0
- package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +63 -0
- package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +92 -0
- package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +19 -0
- package/bootstrap/services/portal/src/ui/loader/Loader.jsx +12 -0
- package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +23 -0
- package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +29 -0
- package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +69 -0
- package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
- package/bootstrap/services/rabbit-mq/Dockerfile.prod +9 -0
- package/bootstrap/services/user/Dockerfile +23 -0
- package/bootstrap/services/user/Dockerfile.prod +37 -0
- package/bootstrap/services/user/README.md +8 -0
- package/bootstrap/services/user/package.json +16 -0
- package/bootstrap/services/user/src/app.js +45 -0
- package/bootstrap/services/user/src/commands/session.handler.js +23 -0
- package/bootstrap/services/user/src/commands/user.handler.js +286 -0
- package/bootstrap/services/user/src/config.js +73 -0
- package/bootstrap/services/user/src/controllers/http.controller.js +156 -0
- package/bootstrap/services/user/src/controllers/message.controller.js +51 -0
- package/bootstrap/services/user/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/user/src/db/migrations/02-user-service-init.js +63 -0
- package/bootstrap/services/user/src/db/migrations/03-unauth-sessions.js +43 -0
- package/bootstrap/services/user/src/db/seeders/development/01-root-user.js +29 -0
- package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +27 -0
- package/bootstrap/services/user/src/db/seeders/production/01-root-user.js +29 -0
- package/bootstrap/services/user/src/policies/user.policy.js +81 -0
- package/bootstrap/services/user/src/schema/user.schema.js +69 -0
- package/bootstrap/services/user/src/services/authentication.service.js +127 -0
- package/bootstrap/services/user/src/services/session.service.js +58 -0
- package/bootstrap/services/user/src/services/user.service.js +130 -0
- package/bootstrap/services/user/src/tests/user.test.js +126 -0
- package/package.json +3 -7
- package/src/agent/agent.client.js +28 -0
- package/src/agent/commands.js +48 -0
- package/src/cli.js +30 -0
- package/src/config.js +8 -0
- package/src/control/commands.js +156 -0
- package/src/control/control.client.js +127 -0
- package/src/dev/commands.js +71 -0
- package/src/dev/dev.service.js +320 -0
- package/src/engine/infra.js +142 -0
- package/src/helpers/helpers.js +63 -0
- package/src/profiles/command.js +170 -0
- package/src/profiles/profiles.client.js +101 -0
- package/src/scaffolder/commands.js +123 -0
- package/src/scaffolder/scaffolder.handler.js +252 -0
- package/src/services/client.js +174 -0
- package/templates/service/Dockerfile.hbs +20 -0
- package/templates/service/app.js.hbs +38 -0
- package/templates/service/commands/{{serviceName}}.handler.js.hbs +97 -0
- package/templates/service/config.js.hbs +48 -0
- package/templates/service/controllers/http.controller.js.hbs +87 -0
- package/templates/service/controllers/message.controller.js.hbs +51 -0
- package/templates/service/db/migrations/01-init.js.hbs +50 -0
- package/templates/service/db/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +23 -0
- package/templates/service/package.json.hbs +18 -0
- package/templates/service/policies/{{serviceName}}.policy.js.hbs +49 -0
- package/templates/service/schema/{{serviceName}}.schema.js.hbs +14 -0
- package/templates/service/services/{{serviceName}}.service.js.hbs +32 -0
- package/dist/cli.js +0 -18
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { commands } from '@gnar-engine/core';
|
|
2
|
+
import { authorise } from '../policies/task.policy.js';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* HTTP controller
|
|
7
|
+
*/
|
|
8
|
+
export const httpController = {
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Schedule a task
|
|
12
|
+
*/
|
|
13
|
+
tasksSchedule: {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
url: '/tasks/schedule',
|
|
16
|
+
preHandler: async (request, reply) => authorise.scheduleTaskByApi(request, reply),
|
|
17
|
+
handler: async (request, reply) => {
|
|
18
|
+
|
|
19
|
+
// params from request
|
|
20
|
+
const params = {
|
|
21
|
+
name: request.body.name,
|
|
22
|
+
payload: request.body.payload
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// execute
|
|
26
|
+
const task = await commands.execute('scheduleTask', params);
|
|
27
|
+
|
|
28
|
+
// handle response
|
|
29
|
+
reply.code(200).send(
|
|
30
|
+
{ task: task }
|
|
31
|
+
);
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Execute task (not implemented)
|
|
37
|
+
*/
|
|
38
|
+
tasksExecute: {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
url: '/tasks/execute',
|
|
41
|
+
preHandler: async (request, reply) => authorise.executeTaskByApi(request, reply),
|
|
42
|
+
handler: async (request, reply) => {
|
|
43
|
+
|
|
44
|
+
// handle response
|
|
45
|
+
reply.code(400).send(
|
|
46
|
+
{ message: 'Not implemented' }
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Execute task batch
|
|
53
|
+
*/
|
|
54
|
+
tasksExecuteBatch: {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
url: '/tasks/execute-batch',
|
|
57
|
+
preHandler: async (request, reply) => authorise.executeTaskByApi(request, reply),
|
|
58
|
+
handler: async (request, reply) => {
|
|
59
|
+
|
|
60
|
+
// execute
|
|
61
|
+
const errors = await commands.execute('handleTaskBatch', request.body?.status);
|
|
62
|
+
|
|
63
|
+
if (errors && errors.length > 0) {
|
|
64
|
+
// handle response
|
|
65
|
+
reply.code(200).send(
|
|
66
|
+
{
|
|
67
|
+
message: 'Task batch run but had errors',
|
|
68
|
+
errors: errors
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// handle response
|
|
75
|
+
reply.code(200).send(
|
|
76
|
+
{ message: 'Task batch run with no errors' }
|
|
77
|
+
);
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get tasks by status
|
|
83
|
+
*/
|
|
84
|
+
tasksGet: {
|
|
85
|
+
method: 'GET',
|
|
86
|
+
url: '/tasks/',
|
|
87
|
+
preHandler: async (request, reply) => authorise.executeTaskByApi(request, reply),
|
|
88
|
+
handler: async (request, reply) => {
|
|
89
|
+
|
|
90
|
+
const status = request.query.status || 'scheduled';
|
|
91
|
+
|
|
92
|
+
// execute
|
|
93
|
+
const tasks = await commands.execute('getTasksByStatus', status);
|
|
94
|
+
|
|
95
|
+
// handle response
|
|
96
|
+
reply.code(200).send(
|
|
97
|
+
{
|
|
98
|
+
status: status,
|
|
99
|
+
tasks: tasks
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Delete failed tasks
|
|
107
|
+
*/
|
|
108
|
+
tasksDeleteFailed: {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
url: '/tasks/delete-failed',
|
|
111
|
+
preHandler: async (request, reply) => authorise.executeTaskByApi(request, reply),
|
|
112
|
+
handler: async (request, reply) => {
|
|
113
|
+
|
|
114
|
+
// execute
|
|
115
|
+
const numDeletedTasks = await commands.execute('deleteFailedTasks');
|
|
116
|
+
|
|
117
|
+
// handle response
|
|
118
|
+
reply.code(200).send(
|
|
119
|
+
{
|
|
120
|
+
message: 'Failed tasks deleted',
|
|
121
|
+
numDeletedTasks: numDeletedTasks
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Migrations
|
|
129
|
+
*/
|
|
130
|
+
runMigrations: {
|
|
131
|
+
method: 'POST',
|
|
132
|
+
url: '/control/migrations',
|
|
133
|
+
preHandler: async (request, reply) => authorise.runMigrationsByApi(request, reply),
|
|
134
|
+
handler: async (request, reply) => {
|
|
135
|
+
|
|
136
|
+
const params = {
|
|
137
|
+
service: request.body.service || null,
|
|
138
|
+
migration: request.body.migration || null
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// execute
|
|
142
|
+
await commands.execute('runMigrations', params);
|
|
143
|
+
|
|
144
|
+
// handle response
|
|
145
|
+
reply.code(200).send(
|
|
146
|
+
{ message: 'Migrations triggered' }
|
|
147
|
+
);
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Seeders
|
|
153
|
+
*/
|
|
154
|
+
runSeeders: {
|
|
155
|
+
method: 'POST',
|
|
156
|
+
url: '/control/seeders',
|
|
157
|
+
preHandler: async (request, reply) => authorise.runSeedersByApi(request, reply),
|
|
158
|
+
handler: async (request, reply) => {
|
|
159
|
+
|
|
160
|
+
const params = {
|
|
161
|
+
service: request.body.service || null
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// execute
|
|
165
|
+
await commands.execute('runSeeders', params);
|
|
166
|
+
|
|
167
|
+
// handle response
|
|
168
|
+
reply.code(200).send(
|
|
169
|
+
{ message: 'Seeders triggered' }
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Reset
|
|
176
|
+
*/
|
|
177
|
+
reset: {
|
|
178
|
+
method: 'POST',
|
|
179
|
+
url: '/control/reset',
|
|
180
|
+
preHandler: async (request, reply) => authorise.runResetByApi(request, reply),
|
|
181
|
+
handler: async (request, reply) => {
|
|
182
|
+
|
|
183
|
+
const params = {
|
|
184
|
+
service: request.body.service || null
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// execute
|
|
188
|
+
await commands.execute('runReset', params);
|
|
189
|
+
|
|
190
|
+
// handle response
|
|
191
|
+
reply.code(200).send(
|
|
192
|
+
{ message: 'Reset triggered' }
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Health check
|
|
199
|
+
*/
|
|
200
|
+
healthCheck: {
|
|
201
|
+
method: 'GET',
|
|
202
|
+
url: '/control/health',
|
|
203
|
+
handler: async (request, reply) => {
|
|
204
|
+
|
|
205
|
+
// execute
|
|
206
|
+
await commands.execute('runHealthcheck');
|
|
207
|
+
|
|
208
|
+
// handle response
|
|
209
|
+
reply.code(200).send(
|
|
210
|
+
{ message: 'health check passed!' }
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* ECS health check
|
|
217
|
+
*/
|
|
218
|
+
ecsHealthCheck: {
|
|
219
|
+
method: 'GET',
|
|
220
|
+
url: '/control/',
|
|
221
|
+
handler: async (request, reply) => {
|
|
222
|
+
reply.code(200).send(
|
|
223
|
+
{ message: 'Server is up' }
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { commands } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Message Controller: handlers for incoming service messages
|
|
6
|
+
*/
|
|
7
|
+
export const messageHandlers = {
|
|
8
|
+
|
|
9
|
+
registerService: async (payload) => {
|
|
10
|
+
const service = await commands.execute('registerService', {
|
|
11
|
+
service: payload.data.service,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return { service };
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
getServices: async (payload) => {
|
|
18
|
+
const services = await commands.execute('getServices', payload.data);
|
|
19
|
+
|
|
20
|
+
return { services };
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
scheduleTask: async (payload) => {
|
|
24
|
+
const task = await commands.execute('scheduleTask', payload.data);
|
|
25
|
+
|
|
26
|
+
return { task };
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
cancelTasks: async (payload) => {
|
|
30
|
+
const tasks = await commands.execute('cancelTasks', payload.data);
|
|
31
|
+
|
|
32
|
+
return { tasks };
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
getManifests: async (payload) => {
|
|
36
|
+
const manifests = await commands.execute('getManifests', payload.data);
|
|
37
|
+
|
|
38
|
+
return { manifests };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { logger, db } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Up
|
|
5
|
+
*/
|
|
6
|
+
export const up = async () => {
|
|
7
|
+
await initDatabaseTables();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Down
|
|
12
|
+
*/
|
|
13
|
+
export const down = async () => {
|
|
14
|
+
await dropDatabaseTables();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Create all tables
|
|
19
|
+
*/
|
|
20
|
+
export const initDatabaseTables = async () => {
|
|
21
|
+
|
|
22
|
+
// Migrations table
|
|
23
|
+
logger.info("Creating migrations table");
|
|
24
|
+
const createMigrationsTableQuery = `
|
|
25
|
+
CREATE TABLE migrations (
|
|
26
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
27
|
+
name VARCHAR(255) NOT NULL UNIQUE,
|
|
28
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
29
|
+
)`;
|
|
30
|
+
await db.query(createMigrationsTableQuery);
|
|
31
|
+
|
|
32
|
+
// Seeders table
|
|
33
|
+
logger.info("Creating seeders table");
|
|
34
|
+
const createSeedersTableQuery = `
|
|
35
|
+
CREATE TABLE seeders (
|
|
36
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
37
|
+
name VARCHAR(255) NOT NULL UNIQUE,
|
|
38
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
39
|
+
)`;
|
|
40
|
+
await db.query(createSeedersTableQuery);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Drop all tables
|
|
45
|
+
*/
|
|
46
|
+
export const dropDatabaseTables = async () => {
|
|
47
|
+
logger.info('Dropping tables');
|
|
48
|
+
await db.query('DROP TABLE IF EXISTS migrations');
|
|
49
|
+
await db.query('DROP TABLE IF EXISTS seeders');
|
|
50
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { logger, db } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Up
|
|
5
|
+
*/
|
|
6
|
+
export const up = async () => {
|
|
7
|
+
await initDatabaseTables();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Down
|
|
12
|
+
*/
|
|
13
|
+
export const down = async () => {
|
|
14
|
+
await dropDatabaseTables();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Create all tables
|
|
19
|
+
*/
|
|
20
|
+
export const initDatabaseTables = async () => {
|
|
21
|
+
|
|
22
|
+
// Tasks table
|
|
23
|
+
logger.info('Creating tasks table');
|
|
24
|
+
const createTasksTableQuery = `
|
|
25
|
+
CREATE TABLE tasks (
|
|
26
|
+
id CHAR(36) PRIMARY KEY,
|
|
27
|
+
name VARCHAR(255) NOT NULL,
|
|
28
|
+
payload TEXT,
|
|
29
|
+
status ENUM('scheduled', 'queued', 'completed', 'failed', 'cancelled') DEFAULT 'scheduled',
|
|
30
|
+
scheduled TIMESTAMP,
|
|
31
|
+
recurring_interval ENUM('daily', 'weekly', 'monthly', 'yearly', 'none') DEFAULT 'none',
|
|
32
|
+
recurring_interval_count INT DEFAULT 0,
|
|
33
|
+
handler_service_name VARCHAR(255) NOT NULL,
|
|
34
|
+
handler_name VARCHAR(255) NOT NULL,
|
|
35
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
36
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
37
|
+
)`;
|
|
38
|
+
await db.query(createTasksTableQuery);
|
|
39
|
+
|
|
40
|
+
// Service registry table
|
|
41
|
+
logger.info('Creating service registry table');
|
|
42
|
+
const createServiceRegistryTableQuery = `
|
|
43
|
+
CREATE TABLE service_registry (
|
|
44
|
+
id CHAR(36) PRIMARY KEY,
|
|
45
|
+
name VARCHAR(255) NOT NULL,
|
|
46
|
+
manifest JSON,
|
|
47
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
48
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
49
|
+
)`;
|
|
50
|
+
await db.query(createServiceRegistryTableQuery);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Drop all tables
|
|
55
|
+
*/
|
|
56
|
+
export const dropDatabaseTables = async () => {
|
|
57
|
+
logger.info('Dropping tables');
|
|
58
|
+
await db.query('DROP TABLE IF EXISTS tasks');
|
|
59
|
+
await db.query('DROP TABLE IF EXISTS service_registry');
|
|
60
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { logger, db } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Up
|
|
5
|
+
*/
|
|
6
|
+
export const up = async () => {
|
|
7
|
+
await alertTaskTable();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Down
|
|
12
|
+
*/
|
|
13
|
+
export const down = async () => {
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Add new columns to task table
|
|
19
|
+
*/
|
|
20
|
+
export const alertTaskTable = async () => {
|
|
21
|
+
const alterTasksTableQuery = `
|
|
22
|
+
ALTER TABLE tasks
|
|
23
|
+
MODIFY COLUMN recurring_interval ENUM('hourly', 'daily', 'weekly', 'monthly', 'yearly', 'none') DEFAULT 'none',
|
|
24
|
+
ADD COLUMN reschedule_centrally_on_success BOOLEAN DEFAULT FALSE,
|
|
25
|
+
ADD COLUMN reschedule_centrally_on_failure BOOLEAN DEFAULT FALSE,
|
|
26
|
+
ADD COLUMN idempotency_key VARCHAR(255) DEFAULT NULL
|
|
27
|
+
`;
|
|
28
|
+
await db.query(alterTasksTableQuery);
|
|
29
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
|
|
2
|
+
export const authorise = {
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Authorise update product
|
|
6
|
+
*/
|
|
7
|
+
scheduleTaskByApi: async (request, reply) => {
|
|
8
|
+
// only service admins can schedule tasks via the API
|
|
9
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
10
|
+
reply.code(403).send({error: 'not authorised'});
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Authorise execute task
|
|
16
|
+
*/
|
|
17
|
+
executeTaskByApi: async (request, reply) => {
|
|
18
|
+
// only service admins can execute tasks via the API
|
|
19
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
20
|
+
reply.code(403).send({error: 'not authorised'});
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Authorise run migrations
|
|
26
|
+
*/
|
|
27
|
+
runMigrationsByApi: async (request, reply) => {
|
|
28
|
+
// only service admins can run migrations via the API
|
|
29
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
30
|
+
reply.code(403).send({error: 'not authorised'});
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Authorise run seeders
|
|
36
|
+
*/
|
|
37
|
+
runSeedersByApi: async (request, reply) => {
|
|
38
|
+
// only service admins can run seeders via the API
|
|
39
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
40
|
+
reply.code(403).send({error: 'not authorised'});
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Authorise run reset
|
|
46
|
+
*/
|
|
47
|
+
runResetByApi: async (request, reply) => {
|
|
48
|
+
// only service admins can run reset via the API
|
|
49
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
50
|
+
reply.code(403).send({error: 'not authorised'});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { schema } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
// Task schema
|
|
4
|
+
const taskSchema = {
|
|
5
|
+
schemaName: 'controlService.taskSchema',
|
|
6
|
+
schema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
name: { type: 'string' },
|
|
10
|
+
payload: { type: 'object' },
|
|
11
|
+
status: { type: 'string', enum: ['scheduled'] },
|
|
12
|
+
scheduled: { type: 'string', format: 'mysql-date' },
|
|
13
|
+
recurringInterval: { type: 'string', enum: ['hourly', 'daily', 'weekly', 'monthly', 'yearly'] },
|
|
14
|
+
recurringIntervalCount: { type: 'number' },
|
|
15
|
+
handlerServiceName: { type: 'string' },
|
|
16
|
+
handlerName: { type: 'string' },
|
|
17
|
+
rescheduleCentrallyOnSuccess: { type: 'boolean' },
|
|
18
|
+
rescheduleCentrallyOnFailure: { type: 'boolean' },
|
|
19
|
+
idempotencyKey: { type: 'string' }
|
|
20
|
+
},
|
|
21
|
+
required: ['name', 'payload', 'scheduled', 'handlerServiceName', 'handlerName'],
|
|
22
|
+
additionalProperties: false
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Service schema
|
|
27
|
+
const serviceSchema = {
|
|
28
|
+
schemaName: 'controlService.serviceSchema',
|
|
29
|
+
schema: {
|
|
30
|
+
type: 'object',
|
|
31
|
+
properties: {
|
|
32
|
+
name: { type: 'string' },
|
|
33
|
+
manifest: { type: 'object' }
|
|
34
|
+
},
|
|
35
|
+
required: ['name'],
|
|
36
|
+
additionalProperties: false
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Compile schemas
|
|
41
|
+
export const validateTask = schema.compile(taskSchema);
|
|
42
|
+
export const validateService = schema.compile(serviceSchema);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { db, utils, logger } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Registry Service
|
|
6
|
+
*/
|
|
7
|
+
export const registry = {
|
|
8
|
+
|
|
9
|
+
// register service
|
|
10
|
+
registerService: async ({name, manifest}) => {
|
|
11
|
+
try {
|
|
12
|
+
const [result] = await db.execute(
|
|
13
|
+
'INSERT INTO `service_registry` (`id`, `name`, `manifest`) VALUES (?, ?, ?)',
|
|
14
|
+
[utils.uuid(), name, manifest]
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
return result.insertId;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
logger.error("Error registering service: " + error);
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
updateService: async ({name, manifest}) => {
|
|
25
|
+
try {
|
|
26
|
+
const [result] = await db.execute(
|
|
27
|
+
'UPDATE `service_registry` SET `manifest` = ?, `updated_at` = CURRENT_TIMESTAMP WHERE `name` = ?',
|
|
28
|
+
[manifest, name]
|
|
29
|
+
);
|
|
30
|
+
return result.affectedRows;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
logger.error("Error updating service: " + error);
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// get services
|
|
38
|
+
getServices: async () => {
|
|
39
|
+
try {
|
|
40
|
+
const [result] = await db.execute(
|
|
41
|
+
'SELECT name FROM `service_registry`'
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return result;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
logger.error("Error getting services: " + error);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get services with manifests
|
|
53
|
+
*/
|
|
54
|
+
getServicesWithManifests: async () => {
|
|
55
|
+
try {
|
|
56
|
+
const [result] = await db.execute(
|
|
57
|
+
'SELECT * FROM `service_registry`'
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return result;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
logger.error("Error getting services: " + error);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get manifests
|
|
70
|
+
*/
|
|
71
|
+
getManifests: async () => {
|
|
72
|
+
try {
|
|
73
|
+
const [result] = await db.execute(
|
|
74
|
+
'SELECT manifest FROM `service_registry`'
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return result;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
logger.error("Error getting manifests: " + error);
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { logger } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Registry Service
|
|
6
|
+
*/
|
|
7
|
+
export const reset = {
|
|
8
|
+
|
|
9
|
+
// drop MYSQL databases
|
|
10
|
+
dropMysqlDatabases: async () => {
|
|
11
|
+
try {
|
|
12
|
+
throw new Error("Not implemented");
|
|
13
|
+
} catch (error) {
|
|
14
|
+
logger.error("Error resetting MYSQL: " + error);
|
|
15
|
+
throw error;
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
// drop all mongodb collections
|
|
20
|
+
dropMongoCollections: async () => {
|
|
21
|
+
try {
|
|
22
|
+
throw new Error("Not implemented");
|
|
23
|
+
} catch (error) {
|
|
24
|
+
logger.error("Error resetting MYSQL: " + error);
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|