-
Notifications
You must be signed in to change notification settings - Fork 350
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
Feature/admin pipelines, endpoints, whitelist #418
Conversation
lib/config/config.js
Outdated
// due to fragile nature of YAWN it may not work properly. | ||
updateGently (modifier) { | ||
return new Promise((resolve, reject) => { | ||
fs.readFile(this.gatewayConfigPath, 'utf8', (err, data) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use util.promisify for all callback like methods?
lib/config/config.js
Outdated
if (err) { | ||
return reject(err); | ||
} | ||
let json = yamlOrJson.load(data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be const
instead of let
. (let
is a signal that the variable may be reassigned)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eslint
is usually able to catch these things - is it configured in CircleCI?
lib/config/config.js
Outdated
@@ -1,4 +1,5 @@ | |||
const fs = require('fs'); | |||
// const YAWN = require('yawn-yaml/cjs'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover comment?
lib/rest/routes/api-endpoints.js
Outdated
json.apiEndpoints[req.params.name] = req.body; | ||
return json; | ||
}) | ||
.then(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick:
.then(() => res.json({status: 'ok'}));
lib/rest/routes/api-endpoints.js
Outdated
.then(() => { | ||
res.json({status: 'ok'}); | ||
}) | ||
.catch(next); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
lib/rest/routes/pipelines.js
Outdated
}) | ||
.catch(next); | ||
}); | ||
return router; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be almost the same code as api-endpoints.js
(and other files as well), the only difference is the target json object. It can be probably generalized and reused in all the places you need.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no generalization, intentionally copy pasted.
The reason is further differences:
validation is one example
additional methods to manipulate policies
Having some generic monster would greatly affect maintainability
lib/config/config.js
Outdated
} | ||
resolve(); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would refactor this piece of code to take advantage of the util.promisify
and chain the promises instead of going into a callback hell.
Something like this:
Pseudo code (it might be a bit different)
const fs = require("fs");
const readFile = util.promisify(fs.readFile);
const writeFile = util.promisify(fs.writeFile);
function updateGently(modifier) {
return readFile(this.gatewayConfigPath, 'utf8').then((data) => {
let json = yamlOrJson.load(data);
let result = modifier(json);
let text = yamlOrJson.dump(result);
return writeFile(this.gatewayConfigPath, text);
});
}
This feels more readable to me but more importantly - easier to reason about.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we consider switching to babel? async / await syntax really helps in working with promises.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally speaking I would refrain to introduce babel and a transpilation step for node programs. Promises
are good enough and can handle all the use cases without sacrificing the readability, it's just matter of reorganizing the flows a bit. We can discuss that separately.
It's of little consequence. We "Squash & Merge" PRs by default. |
Codecov Report
@@ Coverage Diff @@
## master #418 +/- ##
========================================
- Coverage 90.58% 90% -0.58%
========================================
Files 214 219 +5
Lines 8888 8993 +105
========================================
+ Hits 8051 8094 +43
- Misses 837 899 +62
Continue to review full report at Codecov.
|
lib/config/config.js
Outdated
update (modifier) { | ||
return readFile(this.gatewayConfigPath, 'utf8').then(data => { | ||
let text; | ||
if (this.systemConfig && this.systemConfig.preserveStructureOnUpdates) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kevinswiber seems to be a compromise on yawn with comments vs nuke it all approach?
by default it will be nuke it all, and if people complain it will be a doc section describing this flag
(obviously name can be better)
lib/rest/routes/api-endpoints.js
Outdated
let isUpdate; | ||
config.update(json => { | ||
isUpdate = req.params.name in json.apiEndpoints; | ||
json.apiEndpoints[req.params.name] = req.body; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you guys already discussed this - so bear with me if I am repetitive - but this might be harmful as fundamentally I can put everything I want without having any sort of validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree as for general idea, why it is not in this PR
I cannot do it for pipeline policies, because it depends on introducing schema for policies in plugins.
Here the only thing that is required is 'host' field. but for paths
it is quite complex and I would like to move it after approach for pipelines validation is settled. (+ some intentionally undocumented fields do exist)
and by the way UI is going to add some new fields like fieldId to each entity that has nothing to do with EG, but needed for UI. so its cannot be strict schema
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes perfectly sense - thanks a lot for the clarification 👍
lib/rest/routes/pipelines.js
Outdated
router.get('/:name', function (req, res, next) { | ||
res.json(config.gatewayConfig.pipelines[req.params.name]); | ||
}); | ||
router.get('/', function (req, res, next) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the next
parameter needed for all these routes? This can probably be safely removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and what is the problem with having next ?
(req,res), or (req,res,next) are well known signatures for middleware
and it seems that there is no rule in standard js that says it is not good
https://standardjs.com/rules.html
I remember having that rule enabled in the project but I didn't like the experience, because in some cases implementation change and you need add\remove arguments constantly.
but I will agree if this will promoted as ESlint rule
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The general rule I found among the project (although it's not codified) is
route: fn(req, res)
middleware: fn(req, res, next)
but it's a nitpick, it's absolutely not blocking anything.
let result = modifier(json); | ||
text = yamlOrJson.dump(result); | ||
} | ||
return writeFile(this.gatewayConfigPath, text); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this now so much 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I'm missing some more general picture, I think we're good to go.
lib/admin/config/api-endpoints.js
Outdated
@@ -0,0 +1,27 @@ | |||
module.exports = function (client) { | |||
let baseUrl = `api-endpoints/`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
pipelines, apiEndpoints, serviceEndpoints
/pipelines, /api-enpoints, /service-endpoints
GET / -> list of all entities
GET /:name -> entity by object key
PUT /:name with body -> create\update entity with this name as key
DELETE /:name -> remove entity
whitelist
GET /policies/whitelist -> list of all allowed policies
PUT /policies/whitelist/:name - add to the list
DELETE /policies/whitelist/:name - rm from list