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
Config: Support multiple source extension in any object configuration #8037
Comments
@sajithneyo great thanks for proposal! It definitely makes sense to support input from many sources there. Still we have many places like that, and I wonder whether we can come up with some global solution that will allow us to use it everywhere, and not address each property like that individually. It'll probably have to be some variables resolution extension |
@medikoo yeah, it's better to have a global solution for that. but until that, it's better to have this feature for envs. |
I was thinking about sorting this with notation as following: environment:
FOO: someVal
$extend:
- ${self:custom.obj1}
- ${self:custom.obj2} Still one problem I see, is that setting |
@medikoo it looks like the gitlab folks are doing something similar in their config by extending YAML syntax, you may want to check out their proposal. |
@glb great thanks for linking that. That looks very neat. Indeed maybe then it'll be better to do it as follows: environment:
FOO: someVal
!merge:
- ${self:custom.obj1}
- ${self:custom.obj2} What do you think? Note: I've put it slightly differently, as I think notation they propose (in |
@medikoo I don't know enough about how tags work in YAML processing to comment. I liked their proposal, if that's something that can actually be done. |
@glb I've replaced PR that implements that is welcome! |
On revisiting this, I have following thoughts: A solution that works across all types of configs (YAML, JSON etc), is probably best if configured with our variables syntax. We can introduce e.g. Downside is that we cannot merge inline part with externally configured parts. custom:
environment:
FOO: value
provider:
environment: ${merge(${self:custom.environment}, ${file(common-env.json)}})} Another downside of that, is that in context of YAML, it's not as convenient to use as e.g. would be a solution based on YAML function. Still I think we may also add support for such YAML function which will work only in context of YAML confiugurations, and may look as: custom:
environment:
FOO: value
provider:
environment: !merge
- FOO: value
- ${file(common-env.json)} Both methods I think should be relatively easy to implement. @pgrzesik @glb what do you think? |
Thanks for proposal @medikoo. I like the approach based on variable syntax as it's the most universal, minus the downside that you highlighted. Then, if there's a need for that, we could also add the second, yaml-specific syntax with |
Thanks @pgrzesik I've updated main description with instructions how we can implement it. Let me know what you think about it. As you mention I would definitely first got with |
Still required after serverless/utils#79 and #9314 are merged (if they're acceptable):
|
@medikoo I am running into some complexity with the resources:
Resources: !merge
- ${file(file1.yml)}
- ${file(file2.yml)} we won't know the resolved values of I tried making the resources:
Resources: !merge
- a: 1
- b: 2 because Thoughts? |
@glb thanks for sharing. Indeed, when specyfing I didn't think of that culprit, and that's definitely tricky to solve, while needs to be solved I think your idea with Idea that comes to my mind (not sure if it's best we can do), is to:
What do you think? If that's really best we can do, I can outline on how we can implement that. |
@medikoo that's likely one way to go about it, sure. |
@glb I've updated spec in main description to reflect this solution. Let me know what you think |
Any news about the merge ? |
@throrin19 are you interested in submitting the PR? |
Use case description
Currently, environment option in provider and in function level can only accept a single JSON object. It's better to have multiple object support.
Maintainer's note:
As we receive requests to support this notation also in other places, it'll probably be good to solve with one generic solution, instead of hard-coding support for array notation in all needed places one by one.
Proposed solution (Strategy)
1. Universal solution (not specific to configuration file type)
Introduce a
merge
variable source, so single object or array can be constructed from multiple sources as follows:2. YAML configuration specific
Introduce
!merge
YAML function, which could work as followsHow to implement it? (Tactics)
Note: Solution for both methods should be proposed with two different PR's
1. Universal solution (not specific to configuration file type)
merge
source (it should be accompanied with tests that provide 100% coverage). On how to implement it, some hint could be taken from file source configuration. Still in case ofmerge
I believe we will only need to processparams
argument.Important constraints to met:
Object.assign({}, param1, param2, ..)
. In case of arrays:[].push(...param1, ...param2)
2. YAML configuration specific
!merge
support to YAML. Hint on how such extension can be configured can probably be taken from @serverless/utils/cloudformation-schema.js which add support for functions as!Ref
,!GetAtt
etc.. Let's put definition of new YAML types tolib/configuration/yaml-merge.js
.As items passed to
!merge
may be constructed with Serverless Variables, which cannot be resolved at the point of YAML resolution. We need to convert this notation intomerge
variable source (implemented at step 1). Additionally asmerge
source cannot accept inline object or array structures, we need to build some temporary collection attached directly to configuration, in which we can store items, and which we can address inmerge
sources. To achieve that I propose that:lib/configuration/yaml-merge.js
when resolving the!merge
constructs, builds in a memory a temporary object with all referenced items, and inmerge
variable sources address them via${self:_yamlMerge.<configuration-path>}
, e.g. if we list item that was configured atfoo.bar[0]
property, then we should address it inmerge
source param as${self:_yamlMerge.foo.bar[0]}
(Reason for preserving same paths, it to ensure meaningful error if e.g. variable resolution fails at those places)lib/configuration/read.js
once YAML is resolved into JSON, we should retrieve temporary object fromlib/configuration/yaml-merge.js
and add it to result configuration at_yamlMerge
property. Additional notes:!merge
tags, no_yamlMerge
object should be createdlib/configuration/yaml-merge.js
, it should be discarded in context oflib/configuration/yaml-merge.js
(so e.g. repeated configuration reads, do not build up on same temporary object)scripts/serverless.js
(before we doserverless.run()
), delete the_yamlMerge
property from the configurationThe text was updated successfully, but these errors were encountered: