0

I want to add and remove specific key value pair into kubernetes yamls

For eg:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: null
    version: latest
  name: null
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: null
      version: latest
  template:
    metadata:
      labels:
        app: null
        version: latest
    spec:
      containers:
      - image: aude-service
        name: aude-api
        ports:
        - containerPort: 3003
          hostPort: 3003
          protocol: TCP

Contents to be removed in spec after selector:

hostPort: 3003
protocol: TCP

Contents to be added:

strategy:
  type: RollingUpdate 
  rollingUpdate:
    maxUnavailable: 25% 

It would be of great help, if anyone suggest solution

So, I tried using bash to remove hostport key but it didn't work

awk '/^[[:alpha:]]+:/ {level1=$0; next} level1 ~ "hostPort" && /aaa/ {next} 1' aude-convert.yml
  • https://stackoverflow.com/questions/5410757/how-to-delete-from-a-text-file-all-lines-that-contain-a-specific-string – jsofri Apr 17 '23 at 07:16
  • See: [Is it possible to modify a yml file via shell script?](https://unix.stackexchange.com/q/338781) – Cyrus Apr 17 '23 at 07:46

2 Answers2

1

If you wanna try something different, you could work with yq to achieve the same. yq is a lightweight and portable command-line YAML processor. yq uses jq like syntax but works with yaml files as well as json. Read more about it here

So, in your case

To remove the content from the yaml:

yq -i 'del(.spec.template.spec.containers[0].ports[0].hostPort) | del(.spec.template.spec.containers[0].ports[0].protocol)' deployment.yaml

Here we are removing the hostPort and protocol entries from the first element of the ports array.

This gives you a lot of flexibility, for eg if you have multiple containerPort & hostPort entries you could easily select the second element of the ports array:

yq -i 'del(.spec.template.spec.containers[0].ports[1].hostPort) | del(.spec.template.spec.containers[0].ports[1].protocol)' deployment.yaml

or both elements:

yq -i 'del(.spec.template.spec.containers[0].ports[].hostPort) | del(.spec.template.spec.containers[0].ports[].protocol)' deployment.yaml

and the same can be applied to containers[0] - not providing examples for this but I hope you got the point. Really flexible.


To add the required content to the yaml:

yq -i '.spec.strategy = {"type": "RollingUpdate", "rollingUpdate": {"maxUnavailable": "25%"}}' deployment3.yaml

This adds the required content at the end of the file within spec (as is defined using .spec.strategy in the cmd).

To add it right below replicas:

yq -i '.spec |= {"replicas": .replicas, "strategy": {"type": "RollingUpdate", "rollingUpdate": {"maxUnavailable": "25%"}}, "selector": .selector, "template": .template}' deployment.yaml

adding the new strategy key-value pair to the .spec object along with the existing .replicas, .selector & template key.

This helps with not worrying about spaces or tabs that would come with sed.

Hope it helps.

rock'n rolla
  • 1,883
  • 1
  • 13
  • 19
0

I assume you have saved this yaml in deployment.yaml.

  1. To delete your given content from the yaml.

    sed -i '/hostPort/,/protocol/d' deployment.yaml
    

    Here, /hostPort/,/protocol/ is the range pattern that specifies the lines we want to delete between the pattern hostPort and protocol (inclusive). d is for deleting the lines.

  2. To add your given content to the yaml.

    sed -i '/replicas/a \  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 25%' deployment.yaml
    

    Here, /replicas/a is the pattern after which we want to append the content. a command is for appending content after the given pattern.

    Take care of the spaces here as they should have a proper indentation. Here I have considered 1 tab = 2 spaces. Please modify them according to your indentation.