Skip to content
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

Merged
merged 20 commits into from
Sep 26, 2017

Conversation

DrMegavolt
Copy link
Contributor

@DrMegavolt DrMegavolt commented Sep 18, 2017

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

// 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) => {
Copy link
Contributor

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?

if (err) {
return reject(err);
}
let json = yamlOrJson.load(data);
Copy link
Contributor

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)

Copy link
Member

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?

@@ -1,4 +1,5 @@
const fs = require('fs');
// const YAWN = require('yawn-yaml/cjs');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover comment?

json.apiEndpoints[req.params.name] = req.body;
return json;
})
.then(() => {
Copy link
Member

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'}));

.then(() => {
res.json({status: 'ok'});
})
.catch(next);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

})
.catch(next);
});
return router;
Copy link
Member

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.

Copy link
Contributor Author

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

}
resolve();
});
});
Copy link
Member

@XVincentX XVincentX Sep 19, 2017

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.

Copy link
Contributor

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.

Copy link
Member

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.

@XVincentX
Copy link
Member

I can see double commits with the same message 🤔
image

My only "concern" is the code duplication - it can probably be extracted and reused across the routes when the action we want to propose are almost the same.

I can live with that, anyway ;)

@kevinswiber
Copy link
Member

I can see double commits with the same message

It's of little consequence. We "Squash & Merge" PRs by default.

@codecov
Copy link

codecov bot commented Sep 19, 2017

Codecov Report

Merging #418 into master will decrease coverage by 0.57%.
The diff coverage is 43.63%.

Impacted file tree graph

@@           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
Impacted Files Coverage Δ
lib/admin/index.js 100% <ø> (ø) ⬆️
lib/rest/routes/tokens.js 81.81% <100%> (ø) ⬆️
lib/rest/routes/apps.js 83.33% <100%> (ø) ⬆️
lib/rest/routes/credentials.js 85% <100%> (ø) ⬆️
lib/rest/routes/scopes.js 64.7% <100%> (ø) ⬆️
lib/rest/index.js 93.61% <100%> (+0.59%) ⬆️
lib/rest/routes/users.js 83.01% <100%> (ø) ⬆️
lib/admin/config/policies.js 33.33% <33.33%> (ø)
lib/rest/routes/policies.js 33.33% <33.33%> (ø)
lib/config/config.js 70.42% <35.71%> (-8.53%) ⬇️
... and 8 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 82bfb31...d9fd561. Read the comment docs.

update (modifier) {
return readFile(this.gatewayConfigPath, 'utf8').then(data => {
let text;
if (this.systemConfig && this.systemConfig.preserveStructureOnUpdates) {
Copy link
Contributor Author

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)

let isUpdate;
config.update(json => {
isUpdate = req.params.name in json.apiEndpoints;
json.apiEndpoints[req.params.name] = req.body;
Copy link
Member

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.

Copy link
Contributor Author

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

Copy link
Member

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 👍

router.get('/:name', function (req, res, next) {
res.json(config.gatewayConfig.pipelines[req.params.name]);
});
router.get('/', function (req, res, next) {
Copy link
Member

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.

Copy link
Contributor Author

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

Copy link
Member

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);
Copy link
Member

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 👍

Copy link
Member

@XVincentX XVincentX left a 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.

@@ -0,0 +1,27 @@
module.exports = function (client) {
let baseUrl = `api-endpoints/`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be const

Copy link
Contributor

@stanislaw-glogowski stanislaw-glogowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@DrMegavolt DrMegavolt merged commit 2746ec7 into master Sep 26, 2017
@DrMegavolt DrMegavolt deleted the feature/admin-pipelines branch September 26, 2017 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants