-
Notifications
You must be signed in to change notification settings - Fork 93
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
Support configuration templates #2
Comments
Will this include support for pipeline parameters? Templates and parameters really go hand in hand. Templates provide common build steps that can then be varied via parameters. We are currently managing 50+ pipelines and are looking to bring in another 100+. One of our use cases is a building -> testing -> packaging -> deploy .NET nuget packages. This process is almost exactly the same for all our .NET projects. The only variations are project names and folder structures. The template allows us to re-use the same build steps and vary the project names / folders. Our other (more complex) use case relates to a more complex build process. We have a piece of software that is, unfortunately, built from two repositories, a common repo and a client specific repo. We use a pipeline per client that brings the two repo's together to build a client specific artefact. The templates allow us to have common build steps + parameters to vary the artefacts per client. |
Yes, it is close. I care about visualizing it, so people can say, "Yes, that looks like a configuration I want to use". About your proposal: I think it's fine. You've summarized the idea well. You want to provide full file-level templating support. As @johncmckim said, there will be a need to pass in (in Ruby terms) the "binding", or at least some key-value pairs, to implement parameters, right? Otherwise, these templates will become very small pieces so that they include no params. With params, the templates can include more details and feel coherent. You need something like: One problem I can see, since this will not be using something standard like ERB is that it'll be up to the user to put together the template "in their head" so that they understand what the final pipeline looks like. So, you might need to provide a way to do that. It will probably be time to consider non-Java plugin registration soon. |
Yes of course. My main point is that it can also be flexible like:
Parameters would be stored in configuration repository and become the ERB's Kernel.binding`, while templates would be stored in some shared repository and provide common templates to be expanded.
I think that even if it is ERB, then still a tool to preview what gets expanded with some example parameters should exist. This could emerge into testable templates too, e.g.
@arvindsv Yes it would be helpful here, but until then, do you think a config repo plugin could leverage the fact that Go server runs on jruby and actually implement ERB templates within the server process? |
Of course. Once there are templates, they can do anything. As long as the plugin understands what's happening and the final JSON or YAML or whatever is valid, then sure, one template can lead to multiple pipelines or just a job.
I don't think the JRuby classes are exposed to the plugin. We were trying to once make it so that jruby.jar can be inside the plugin's lib/ directory, so that it can start its own instance of JRuby. But, that needs the OSGi part to expose I was thinking of having an HTTPS level endpoint for plugins to register, just like an agent would. Then, communication happens using JSON like usual. Maybe having a websocket open between the plugin and the server. Complications: Security (currently plugins can only start physically from the server box) and agent-side plugins. I can take a quick look at trying to see what it takes to run a Clojure or JRuby-based plugin run in a few days, unless you or someone else has some time earlier than that. |
I like this approach. Then "plugin" can be really anything, just another independent application talking to go-server. Regarding security, the plugins could be using similar mechanism to agents, either a key or manual approval. Why do you think security is such a problem then? Are you concerned with intercepting the communication?
Yes please :) A proof of concept would be nice to get me started on this. I could pick it up from there and then write the plugin part to support some common scenarios with parameters. |
Exactly. It can be anything which can open a port, keep a connection alive (communication can happen from server to agent too) and respond using JSON.
No. I'd just like the authentication to be a little more unique to a plugin, rather than just having one key (as agent auto register key is today). I was thinking of a per-plugin key. But, I'd need to think more deeply about the security it offers (does it?) vs. convenience. Either way, it's a decision we can take quickly.
Ok, I was thinking of a normal Java plugin, but written using JRuby or Clojure. Did you mean thinking about the non-Java plugin, or that? I think the JRuby or Clojure plugin can be easier and quicker for now. |
That's was my first thought too. Personally I don't like that agents all share the same key, I think master key is an anti-pattern. I like how hashicorp's vault App ID solves this scenario. But that is a different topic.
I was thinking to get jruby working in a java plugin. So that we can implement ERB templates. From user perspective one could write something like: pipelines:
my_dry_pipeline:
group: <%= @group %>
label_template: "${mygit[:8]}"
tracking_tool:
<%= @tool %>
stages:
...
<% if @include_some_stage %>
.... In longer term, with out-of-process plugins, it could be rewritten in ruby, or just run in its own process with jruby. |
Ok. I have a flight to catch later and it has wifi. :) I'll try this. |
@arvindsv based on what @ketan says about loader jruby voodoo magic, that might be a reason to stop going in this direction. I mean it sounds that adding jruby to the plugin may make it unstable between jruby releases. I wouldn't want the plugin to be broken on half of deployments because of hacky setup needed for it to work. The main point was to get good file-level templates support, ERB was a candidate because it is well known and stable. We can move to other templating engine which has actual java implementation, if this is too hard. |
Hi guys, I am handling my gocd XML config using Saltstack and Jinja templates (Python), I have a fully working example and it really suits this project, as Saltstack's pillar values are in YAML (equivalent to the config files for this plugin). I know you haven't considered Jinja and there might be a reason for that, if not, I want to let you know that there is a Java Jinja implementation and I would love to see template and parameter support here (which is a must for me), then I would for sure switch to this plugin. If you are interested, I can share my Jinja template with you, which supports templates and parameters. Of course, there would be some work to match the YAML specification for this project, but I don't think is too much. |
Nice. @tomzo is away for a little bit, I think. He'll probably reply once he's back. |
@darioblanco thanks for suggestion. Please share your template and some examples. If you have been already managing pipelines using file-level templates as you say then we could use some of that to craft a few test cases. |
Hi @tomzo I have experience with Jinja from my Flask/Django days, but not with its Java implementation. I would personally use a native Java solution if is available, I just don't know what are the limitations for adopting templates and parameters into this project. My reason to use Jinja is the following: as I am provisioning my gocd instance with Saltstack, I wanted to have the configuration as code, and I dislike XML a lot. As I already use Jinja for Saltstack templating, I thought it was a good idea to just create a cruise-config.xml file as a template and support as much as possible from GoCD configuration reference. I already have experience with Jinja, so it was relatively easy to create a template. My Jinja templates currently support:
I will share the config in another post (it is divided in different template files). If this plugin supports templates and parameters/environment variables I will simplify my Saltstack configuration a lot, as I will move the pipeline/template definition to a different repository and saltstack will just have to add the repository load tag into cruise-config.xml. So yes, Saltstack won't need to manage pipeline configurations :) |
About my example, I have created a gist: https://gist.github.com/darioblanco/f5d9840d91a875d92ac9b718ee128f6d The YAML file sadly doesn't match your reference. It can be adapted with strong Jinja changes though. For this project I guess the only interesting files are templates.jinja and pipelines.jinja. I decided to share the other files as well to give some context. I supported as much as possible for my specific use case, not all the attributes from the GoCD configuration reference, I just add them in my template on demand, so imagine how helpful would be to use your plugin :) |
Hi all, just another user's perspective:
Any templating approach that improves on those points would be a big plus. As a user, I've had experience with Jinja2 (mostly coming from Ansible), and it's pleasant enough to use. However it's mostly meant for HTML or text file output, whereas for the pipeline configuration, the result really is a data structure, encoded in YAML. I wonder if there is something better that works on the data structure level, not on the text level that is then again parsed as YAML. Thanks for all of your work on this, |
+1 |
I'm doing templates using Mustache. If it's usefull to someone can I publish examples. |
@davidUser Can you post examples? |
I was searching for this template feature some 6months ago when we started switching to Pipeline As Code in GoCD. Having looked at this issue #2, we decided to go with j2 templates and wrote a little python script to generate the yaml pipelines (1 gocd.yml = 1 pipeline) based on j2 template and variables. Since then, I managed to create 19 different j2 templates for the 71 pipelines and counting. We thought this is much better than the GoCD template which only looks after of the stages. Whereas the implementation we did is to j2 template the entire pipeline including materials, upstream/downstream dependencies, etc. I might get trouble with the company if I post examples but I would suggest looking at python jinja2 lib. |
from gitter we made pipelines which consume git repo url as parameter and use jinja2 for generating base *.gocd.yaml
such way with using shared scripts in stages without templates allows customizing only one stage from casual flow and getting updates for other stages |
@fire Here is the example, sorry by the while but i need remove a lot of restrict information from the example. |
I've done an experiment to use the jsonnet data template language for the JSON plugin, and written up a summary in the wiki. |
Looks useful, I'll try it with my pipelines. |
@moritz looks like the example is not in link. & don't referred to config yaml pluing can you more elaborate like @davidUser |
@davidUser i like your approach. But there are two problems now.
|
@davidUser config repo plugin will look for only changes. and once we did with change for service component repo. how do we automatically trigger for template code with some manual paramter? |
I did something similar with jsonnet. For the gocd to scan for changes, all the relevant repositories must be added as watched materials. [Edited] If the output json is different that will cause a reload. |
is there any example? |
let say component.repo has ci.gocd.yaml and i want to make generic templates for the same component which is of 200. Config repository plugin looks for ci.gocd.yaml. |
@thatsk I think that a better approach is maybe use some programmatic interface and write your business rules to pipeline generation. My example is just a simple workaround that I use to manage simple bootstrap to pipeline configurations. |
There's some related work being done by @marques-work here: gocd/gocd#6123 (comment) |
Forked and added some code showing what it could look like to have true YAML templates. This allows you to use existing old/archaic The template only contains This is a very crude, but fully working, demonstration of what is possible. We are using it at my company right now with success. Best of luck. https://github.com/timothy-cloudopsguy/gocd-yaml-config-plugin At a high-level, we just tapped into the PipelineTransform.java file, at the point where it finds the
|
For whoever is of interest, similar to @davidUser's approach I have implement in my project
See links below: I hope it's useful!! |
Templates in configuration repositories
In my understanding GoCD pipeline templates were introduced at all is because any organization faces some similarity in the pipelines they declare. User can have a template with some configuration pre-defined and parameterized. So that rather than declare a full pipeline with all its stages, jobs and tasks, one may provide a few key-value pairs and tell GoCD to expand a template. This is basically a feature to support the DRY (Don't repeat yourself) priciple.
Internally this is exactly what happens, XML parameters are replaced by some variables which are in the scope of particular pipeline definition, eventually pipeline configuration instance expanded from template is not different in any way from explictly defined one. It is also not any different than a pipeline returned by
configrepo
extension point to server.Once in a while a GoCD user will come along and say that he has found a pattern in all his pipelines, but it is impossible to express it with current pipeline-template model. A few examples:
I propose to
Some questions come along then..
If organization has templates to be shared among many projects (many repositories) then where should the templates be stored and hosted? For private pipelines and templates, this could be a repository with limited access. But there could be public templates too, users could be sharing pieces of configuration on github, just like we share libraries. (PS: @arvindsv I guess this is was what you mentioned once before).
How to reference reference remote configuration elements/templates from particular configuration repository? E.g. if you are a SCM-fanatic then you'll want to put templates themselves in a git repository. Then easiest way is to use a gitsubmodule to have your templates checked out in the configuration repo subdirectory, e.g.
gocd-templates
. Then configuration repository code looks like this:But another method could be a http link reference like so:
The first method has
gocd-templates
as a git submodule (or could be a plain directory actually), if that is versioned with exact commit, then any update in module reference will trigger pipeline configuration to be reloaded in GoCD.In second method if content served by URL changes, Go will not know about it, configuration will be stale until next commit is pushed. It might be undesired in some cases.
The right templating engine
I am currently looking into which engine would fit best here. It should rather have java implementation because GoCD plugins limitations. It should be powerful but also easy to use and learn.
Recently I discovered jtwig, I really like the modularity part of it.
If you have any suggestions, please say so.
Discussion
If you have managed 100+ pipelines then you know exactly all the shortcomings of GoCD pipeline templates. If you have some ideas on templating pipelines or some interesting use cases, then please share.
The text was updated successfully, but these errors were encountered: