feat(atc): add data manipulation functions to load_var#5936
feat(atc): add data manipulation functions to load_var#5936evanchaoli wants to merge 1 commit intoconcourse:masterfrom
Conversation
Signed-off-by: Chao Li <[email protected]>
|
On the one hand, I think this is really useful, but on the other, I really don't think it should be built in to Concourse. My instinct is to prevent Concourse from embedding another language within YAML:
Given these concerns, I think it would be better off if this were implemented as a Prototype. Then it can be versioned with the pipeline itself, it won't be "required learning" for Concourse, and users can use whatever language they like - there could be a I don't know exactly how this would look, but it should be easy to support given that Prototypes can consume arbitrary values and return arbitrary objects. Perhaps the plan:
- load_var: data
file: out/data.json
- run: eval
type: gval
set_var: extended_data # set returned object fields as `extended_data` local var
params:
input: ((.:data))
fields:
statement: foo + " is bar"
arrlen: len(arr)
from_vs: |
((vs:vs_var)) + " world"
- task: show-vars
config:
platform: linux
image_resource:
type: registry-image
source:
repository: busybox
outputs:
- name: out
run:
path: sh
args:
- -exc
- |
echo __((.:data.foo))__
echo __((.:extended_data.statement))__
echo The array has ((.:extended_data.arrlen)) items__
echo __((.:extended_data.from_vs))__I fully recognize that this involves more overhead (running a container), but at least does not require users to write a bunch of one-off tasks, which I think is the more important goal. One benefit from this form is that it allows for using complex values from multiple vars, e.g.: - run: eval
type: gval
set_var: extended_data # set returned object fields as `extended_data` local var
params:
input:
from_local: ((.:data))
from_vs: ((vs:vs_var))
fields:
statement: from_local.foo + " is bar"
arrlen: len(from_local.arr)
from_vs: from_vs + " world" |
|
@vito I have no intention to embed some other language into Concourse, instead, I want to introduce a Concourse own evaluation language (maybe the language itself deserves a RFC), which we can start with some basic arithmetic, string operation, regexp match, etc, where I couldn't pick up a word to accurately describe my feeling with the From my own experience of building pipelines, I am always struggling with some tiny things: add a task to do some simple data manipulation? write the task directly in pipeline YAML or put the task to a file? which language to use, bash, python, ruby, or golang? which task image to use? Those are all tiny problems, but they really burden users. So it would be wonderful if Concourse can provide as more supportive functions as possible, so that user may only focus on their own logic, like how to run tests, how to package a product, etc. |
My hesitation and the drawbacks I listed don't stem from embedding some other language, they stem from embedding a language at all. It may not be the
Sorry, that's a syntax error - I didn't mean to embed it, I accidentally indented the - run: eval
type: some-type
set_var: some-var
params: {fields: {some-field: hello}}
- run: echo
type: debug
params: {message: ((.:some-var.some-field))}The variable scoping would work the same way as
I want the answer to these questions to always be "use a prototype", and for there to be common prototypes implemented an shared within the community so that users can just use one from the catalog just as they already do with resource types. If a prototype is not available to do the job, I want it to be easy to write one and share it - only then will you have to decide which language to implement it in. From then on, everyone can just use it. I think we get to this future world by doubling down on the idea as much as possible and seeing where it fits; putting more and more logic into Concourse itself increases the complexity of Concourse and can stunt the growth of this ecosystem. |
|
@vito I think you have been talking about prototype long time back, and I just went over the RFC of prototype again. Please correct me if I am wrong. From my understanding, prototype is a generalization of resource type, which allows users to custom "resource type" more or less than check/get/put. Basically, prototype still runs as containers, inputs and outputs via files. So I'm confused how a prototype can inject vars into pipelines Let's still use the original sample: |
|
@evanchaoli I'm sure @vito can do a better job answering your questions, but I'll give it a go:
Requests to prototypes can emit two different things: bits (outputs written to disk), and streams of objects (arbitrary JSON written to
We'll likely need to rework var interpolation to support this. The reason it's string only right now (I believe) is that
Nope! The |
|
@aoldershaw you got it! Here are some further clarifications:
One quick clarification: vars already support interpolation of full values. It is only the So, this example would effectively take the value in the
As @aoldershaw pointed out, this extra So the tl;dr is that Prototypes give us a generic way to not only pass files around, but rich JSON request-responses. For prototypes which implement resources, these JSON objects would represent versions of the resource, but in other contexts we can interpret it however we want - in this case, as arbitrary data to set in local vars. |
@vito That sounds great. Has that been implemented or just planed? I cannot find any doc about that. Also from the code on master branch, I cannot see that, for example get step's param interpolation: https://github.com/concourse/concourse/blob/master/atc/exec/get_step.go#L127, I don't see how it supports full values.
Also, when |
It's implemented by the Lines 3 to 6 in b04e89f
It's planned for Q4 2020 at the moment. The RFC is done, so theoretically someone could start implementing it, but we're planning to do this gradually as it also will involve re-implementing our core resource types and we'd like to have a tight feedback loop there. |
What does this PR accomplish?
The
load_varstep make a pipeline to be able to load variables at run-time. But a new problem I have seen is that, sometime, users need to some simple manipulations on loaded vars, then they have to add a task to do so, which makes pipeline massive.This PR adds some data manipulation functions to load_var. See my test pipeline:
And see screen shot of a build of the pipeline:
Changes proposed by this PR:
Add a param
addstoload_varstep, an add contains a name and a expression, where the expression will be evaluated to a string, and inject a new var<load_var name>-<add name>.Notes to reviewer:
evaladded in this PR can be used for Step "gate" rfcs#66Contributor Checklist
Reviewer Checklist
BOSH and
Helm packaging; otherwise, ignored for
the integration
tests
(for example, if they are Garden configs that are not displayed in the
--helptext).