Слияние массивов YAML, игнорируя другие поля в YAML

#yaml #yq

#yaml #yq

Вопрос:

Я ищу способ объединить массивы из двух отдельных YAML (добавив один к другому). Однако в YAML есть поле (не в массивах), обернутое {} для замены значениями времени выполнения. т.е.

 # yaml a
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  namespace: default
  name: {clusterRoleName}
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]

# yaml b
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  namespace: default
  name: {clusterRoleName}
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "watch", "list"]

# desired
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  namespace: default
  name: {clusterRoleName}
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "watch", "list"]
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "watch", "list"]

 

Для этого я использую yq версии 2.14. Я пробовал yq merge -a=append a.yaml b.yaml , который обрабатывает массивы правил так, как мне хотелось бы, но обрабатывает name: {clusterRoleName} как JSON и выводит:

 apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: {ClusterRoleName: ''}
...
 

Есть ли способ объединить только одно поле или игнорировать определенный ключ или тип значения? Я также не привязан к использованию yq для этого, если кто-то может предложить альтернативный метод.

Комментарии:

1. Не могли бы вы перейти на более свежую версию? В версии 4 появилось много новых функций

2. Обновление потенциально возможно, хотя это конкретное использование было частью большого проекта, поэтому идеальным было найти решение, которое работало бы с существующей версией. Если есть чистый способ в v4, хотя было бы интересно — проверю его, спасибо 🙂

Ответ №1:

При использовании выделенного синтаксического анализатора yaml, такого как yq, было бы идеально использовать awk, возможно, альтернативу:

  awk 'NR==FNR amp;amp; !/^[[:space:]]/ { tag=$1;next } tag=="rules:" amp;amp; FNR==NR { map[idx  ]=$0 } END { tag="" } NR!=FNR amp;amp; !/^[[:space:]]/ { if (tag=="rules:") { for (i in map) { print map[i]}} tag=$1 } NR!=FNR { print }' yamlb yamla
 

Объяснение:

 awk 'NR==FNR amp;amp; !/^[[:space:]]/ { # Processing yamlb (NR==FNR) and there there are spaces at the beginning of the line
         tag=$1; # Set the variable tag to the first space delimited field
         next # Skip to the next file
        } 
     tag=="rules:" amp;amp; FNR==NR { # Process where tag is "rules:" and we are processing yamlb
          map[idx  ]=$0 # Put the line in an array map with in incrementing index
        } 
     END { 
          tag="" # At the end of the file reset the variable tag
        } 
     NR!=FNR amp;amp; !/^[[:space:]]/ { # Process yamla where there are no spaces at the start of the line
          if (tag=="rules:") { 
            for (i in map) { 
               print map[i] # If tag is equal to rules: print the array map
            }
          } 
          tag=$1 # Set the variable tag to the first space delimited field.
         } 
      NR!=FNR { 
          print # Print lines when we are processing yamla
         }' yamlb yamla

 
 

Комментарии:

1. Спасибо! Это действительно круто — в конце концов я смог использовать комбинацию sed и yq для обхода значений шаблона, спасибо, что нашли время написать это, так как было интересно прочитать и попробовать. 🙂