Simplest and Optimised way to read and edit YAMLs - docker

I've some YAML files which I wanted to apply to create Custom Resources. But before applying it I want to change the spec and ENVs of the YAML snippet. So what could be the best way to do this?
What I'm doing now is:
Let suppose this is the YAML
apiVersion: litmuschaos.io/v1alpha1
kind: ChaosEngine
metadata:
name: nginx-chaos
namespace: default
spec:
appinfo:
appns: 'default'
applabel: 'app=nginx'
appkind: 'deployment'
# It can be true/false
annotationCheck: 'false'
# It can be active/stop
engineState: 'active'
chaosServiceAccount: pod-delete-sa
monitoring: false
# It can be delete/retain
jobCleanUpPolicy: 'delete'
experiments:
- name: pod-delete
spec:
components:
env:
# set chaos duration (in sec) as desired
- name: TOTAL_CHAOS_DURATION
value: '30'
# set chaos interval (in sec) as desired
- name: CHAOS_INTERVAL
value: '10'
# pod failures without '--force' & default terminationGracePeriodSeconds
- name: FORCE
value: 'false'
I Download this file from the raw link. (1 function for this)
Replace a field like jobCleanUpPolicy: 'delete' to jobCleanUpPolicy: 'retain' (1 fn)
Replace the next line when a match is found like value: 'false' to value: 'true' for FORCE ENV. (1 fn)
Applying the final manifest created! (1 function)
Can this be optimized?

If you create a struct representing the resource (or, even better, can import the package which defines the CRD) you could take the yaml string, marshal it into the struct and then edit the fields directly as fields of a struct instead

Hi You may use LitmusPortal to use this.Refer

Related

Jenkins writeYaml not replacing value in yaml file

I have a yaml file with the following structure:
transfers:
- name: xyz
cloud: aws
subheading:
impact: Low
reason: ---
artifacts:
- name: name1
type: type1
source:
hash: a1b2C3dd4 ---> VALUE TO OVERWRITE
I would like to overwrite the existing hash value with a value of the latest GIT_COMMIT.
I have tried the method from the following question: write yaml file in jenkins with groovy. However, the value of hash[0][0] remains unchanged. This is the case even when I replace env.GIT_COMMIT with a test hash string "testHash123". I'm unsure why this is the case?
def filename = ('path/to/file.yaml')
def datas = readYaml file: filename
//change hash
datas.transfers['artifacts'].source.hash[0][0] = env.GIT_COMMIT
writeYaml file: filename, data: datas, overwrite: true
Please try the following.
datas.transfers[0]['artifacts'][0]['source'].hash = env.GIT_COMMIT
The easiest way to figure this out is by printing, so you can understand the structure.
[transfers:[[name:xyz, cloud:aws, subheading:[impact:Low, reason:xxxx], artifacts:[[name:name1, type:type1, source:[hash:a1b2C3dd4]]]]]]
As you can see above the transfer is a sequence, so you need to extract the correct segment with an index.

How to specify an example of two path template parts in OpenAPI / Swagger

Given a path template with two parts such as:
paths:
/blah/{fooPart}-stuff-{barPart}:
parameters:
- in: path
name: fooPart
description: foo part of this matrix ID
required: true
schema:
type: string
- in: path
name: barPart
description: bar part of this matrix ID
required: true
schema:
type: string
I'd like to provide an list of examples. Since the fooPart and the barPart are correlated, i'd like to have each example have the corrrelated data elements. I'd imagine putting it in the components
examples:
Happy:
summary: Happy path
value:
fooPart: red
barPart: up
Sad:
summary: Sad path
value:
fooPart: up
barPart: red
When i add the refs as an examples list to each parameter, like so
- in: path
name: fooPart
description: foo part of this matrix ID
required: true
schema:
type: string
examples:
happy:
$ref: "#/components/example/Happy"
sad:
$ref: "#/components/example/Sad"
the rendered display is ... adequate? Wrong? Not helpful? The examples aren't correlated and the array specified as value is presented in the box for each parameter, as seen here. I recognize, this is what i told it to do. Is there any way to bundle all the examples together? Or is my only option the one i will offer as an answer? Ugh.
I'm assuming the only option is
examples:
HappyFoo:
summary: Happy path
value: red
HappyBar:
summary: Happy path
value: up
SadFoo:
summary: Sad path
value: red
SadBar:
summary: Sad path
value: red
With each parameter only including its own values like so:
parameters:
- in: path
name: fooPart
description: foo part of this matrix ID
required: true
schema:
type: string
examples:
Happy:
$ref: "#/components/examples/HappyFoo"
Sad:
$ref: "#/components/examples/SadFoo"
The examples aren't correlated, but at least the value in the box is correct as seen here.

Resque scheduler pass hash argument to Job

I have a job that receives a hash argument in its perform method. I want to call it periodically. I defined a CRON to schedule it on the resque_schedule.yml file. I am trying this way:
UpdateInterestHistoryJob:
cron: "0 0 * * * America/Sao_Paulo"
args:
classifier: :SIAPE
However, inside the job, I get the arguments as an array:
["classifier", "SIAPE"]
How do I define it correctly? How do I define the job argument as a hash on the yml file?
I just tested here and a simple dash should be enough:
UpdateInterestHistoryJob:
cron: "* * * * * America/Sao_Paulo"
args:
- classifier: :SIAPE
Also, should you need more arguments in your Resque job, simply place them without further dashes:
UpdateInterestHistoryJob:
cron: "* * * * * America/Sao_Paulo"
args:
- classifier: :SIAPE
another: value
between your Hash and the one included in this example from Ceilingfish I see discrepancy:
You can mark it up like this
feeds:
-
url: 'http://www.google.com'
label: 'default'
Note the spacing is important here. "-" must be indented by a single space (not a tab), and followed by a single space. And url & label must be indented by two spaces (not tabs either).
Additionally this might be helpful: http://www.yaml.org/YAML_for_ruby.html
This is from ww.yaml.org
Simple Inline Hash
Mapping can also be contained on a single line, using the inline syntax. Each key-value pair is separated by a colon, with a comma between each entry in the mapping. Enclose with curly braces.
Yaml
Simple Inline Hash in YAML?
hash: { name: Steve, foo: bar }
Ruby
Simple Inline Hash in Ruby?
{ 'hash' => { 'name' => 'Steve', 'foo' => 'bar' } }
I also include this link from the official YAMLSyntax and there is many explanation about this
Convert Ruby Hash into YAML
https://codedump.io/share/w2EriSJ0wO7T/1/convert-ruby-hash-into-yaml

Concatenate lists for a given key in mustache template

Here's what my data looks like (YAML):
-
name: objectA
components:
-
name: "component_1"
-
name: "component_2"
styles:
-
name: "new style"
components:
-
name: "component_1"
-
name: "other style"
components:
-
name: "component_4"
I would like to retrieve in my mustache the full list of components for objectA, meaning i need to access all the components children values and concatenate them or uniq them.
The goal would be to have a template like this:
{{#allComponents}}
{{name}}
{{/allComponents}}
which should output:
component_1
component_2
component_4
PS: i am using GRMustache
There's very little chance any Mustache implementation could handle such a specific need with any native built-in syntax of any kind. And GRMustache does actually not.
The simplest path is to prepare your allComponents key before rendering your data.

Use YAML with variables

Are variables within YAML files possible? For example:
theme:
name: default
css_path: compiled/themes/$theme.name
layout_path: themes/$theme.name
In this example, how can theme: name: default be used in other settings? What is the syntax?
I had this same question, and after a lot of research, it looks like it's not possible.
The answer from cgat is on the right track, but you can't actually concatenate references like that.
Here are things you can do with "variables" in YAML (which are officially called "node anchors" when you set them and "references" when you use them later):
Define a value and use an exact copy of it later:
default: &default_title This Post Has No Title
title: *default_title
{ or }
example_post: &example
title: My mom likes roosters
body: Seriously, she does. And I don't know when it started.
date: 8/18/2012
first_post: *example
second_post:
title: whatever, etc.
For more info, see this section of the wiki page about YAML: http://en.wikipedia.org/wiki/YAML#References
Define an object and use it with modifications later:
default: &DEFAULT
URL: stooges.com
throw_pies?: true
stooges: &stooge_list
larry: first_stooge
moe: second_stooge
curly: third_stooge
development:
<<: *DEFAULT
URL: stooges.local
stooges:
shemp: fourth_stooge
test:
<<: *DEFAULT
URL: test.stooges.qa
stooges:
<<: *stooge_list
shemp: fourth_stooge
This is taken directly from a great demo here: https://gist.github.com/bowsersenior/979804
After some search, I've found a cleaner solution wich use the % operator.
In your YAML file :
key : 'This is the foobar var : %{foobar}'
In your ruby code :
require 'yaml'
file = YAML.load_file('your_file.yml')
foobar = 'Hello World !'
content = file['key']
modified_content = content % { :foobar => foobar }
puts modified_content
And the output is :
This is the foobar var : Hello World !
As #jschorr said in the comment, you can also add multiple variable to the value in the Yaml file :
Yaml :
key : 'The foo var is %{foo} and the bar var is %{bar} !'
Ruby :
# ...
foo = 'FOO'
bar = 'BAR'
# ...
modified_content = content % { :foo => foo, :bar => bar }
Output :
The foo var is FOO and the bar var is BAR !
This is an old post, but I had a similar need and this is the solution I came up with. It is a bit of a hack, but it works and could be refined.
require 'erb'
require 'yaml'
doc = <<-EOF
theme:
name: default
css_path: compiled/themes/<%= data['theme']['name'] %>
layout_path: themes/<%= data['theme']['name'] %>
image_path: <%= data['theme']['css_path'] %>/images
recursive_path: <%= data['theme']['image_path'] %>/plus/one/more
EOF
data = YAML::load("---" + doc)
template = ERB.new(data.to_yaml);
str = template.result(binding)
while /<%=.*%>/.match(str) != nil
str = ERB.new(str).result(binding)
end
puts str
A big downside is that it builds into the yaml document a variable name (in this case, "data") that may or may not exist. Perhaps a better solution would be to use $ and then substitute it with the variable name in Ruby prior to ERB. Also, just tested using hashes2ostruct which allows data.theme.name type notation which is much easier on the eyes. All that is required is to wrap the YAML::load with this
data = hashes2ostruct(YAML::load("---" + doc))
Then your YAML document can look like this
doc = <<-EOF
theme:
name: default
css_path: compiled/themes/<%= data.theme.name %>
layout_path: themes/<%= data.theme.name %>
image_path: <%= data.theme.css_path %>/images
recursive_path: <%= data.theme.image_path %>/plus/one/more
EOF
This is how I was able to configure yaml files to refer to variable.
I have values.yaml where we have root level fields which are used as template variables inside values.yaml
values.yaml
.....
databaseUserPropName: spring.datasource.username
databaseUserName: sa
.....
secrets:
type: Opaque
name: dbservice-secrets
data:
- name: "{{ .Values.databaseUserPropName }}"
value: "{{ .Values.databaseUserName }}"
.....
When referencing these values in secret.yaml, we would use tpl function using syntax {{ tpl TEMPLATE_STRING VALUES }}
secret.yaml
when using inside range i:e iteration
{{ range .Values.deployments.secrets.data }}
{{ tpl .name $ }}: "{{ tpl .value $ }}"
{{ end }}
when directly referring as variable
{{ tpl .Values.deployments.secrets.data.name . }}
{{ tpl .Values.deployments.secrets.data.value . }}
$ - this is global variable and will always point to the root context
. - this variable will point to the root context based on where it used.
if your requirement is like parsing an replacing multiple variable and then use it as a hash/or anything then you can do something like this
require 'yaml'
require 'json'
yaml = YAML.load_file("xxxx.yaml")
blueprint = yaml.to_json % { var_a: "xxxx", var_b: "xxxx"}
hash = JSON.parse(blueprint)
inside the yaml just put variables like this
"%{var_a}"
Rails / ruby frameworks are able to do some templating ... it's frequently used to load env variables ...
# fooz.yml
foo:
bar: <%= $ENV[:some_var] %>
No idea if this works for javascript frameworks as I think that YML format is superset of json and it depends on what reads the yml file for you.
If you can use the template like that or the << >> or the {{ }} styles depending on your reader, after that you just ...
In another yml file ...
# boo.yml
development:
fooz: foo
Which allows you to basically insert a variable as your reference that original file each time which is dynamically set. When reading I was also seeing you can create or open YML files as objects on the fly for several languages which allows you to create a file & chain write a series of YML files or just have them all statically pointing to the dynamically created one.

Resources