Skip to content

Instantly share code, notes, and snippets.

@dhamidi
Created September 13, 2018 15:58
Show Gist options
  • Save dhamidi/a7f3144280f515fac766d993119dd94e to your computer and use it in GitHub Desktop.
Save dhamidi/a7f3144280f515fac766d993119dd94e to your computer and use it in GitHub Desktop.
Flattens yaml files

Flattens YAML files to make them greppable

$ yq docker-compose.yml 
version 3.3
services.redis.image redis:latest
services.redis.deploy.replicas 1
services.redis.ports.0.published 6379
services.redis.ports.0.target 6379
services.redis.ports.0.mode host
services.redis.volumes.0 redis-data:/data
services.elasticsearch.image docker.elastic.co/elasticsearch/elasticsearch:5.5.0
services.elasticsearch.deploy.replicas 1
services.elasticsearch.environment.0 discovery.type=single-node
services.elasticsearch.environment.1 xpack.security.enabled=false
services.elasticsearch.ports.0.published 9200
services.elasticsearch.ports.0.target 9200
services.elasticsearch.ports.0.mode host
services.elasticsearch.ports.1.published 9300
services.elasticsearch.ports.1.target 9300
services.elasticsearch.ports.1.mode host
services.elasticsearch.volumes.0 elasticsearch-data:/usr/share/elasticsearch/data
services.mariadb.image mariadb:5.5
services.mariadb.command mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
services.mariadb.deploy.replicas 1
services.mariadb.environment.0 MYSQL_ALLOW_EMPTY_PASSWORD=yes
services.mariadb.environment.1 MYSQL_ROOT_HOST=%
services.mariadb.environment.2 MYSQL_DATABASE=default
services.mariadb.ports.0.published 3306
services.mariadb.ports.0.target 3306
services.mariadb.ports.0.mode host
services.mariadb.volumes.0 mariadb-data:/var/lib/mysql
volumes.redis-data nil
volumes.elasticsearch-data nil
volumes.mariadb-data nil
#!/usr/bin/env ruby
require 'psych'
class Tree
def initialize(src)
@tree = Psych.load(src)
end
def apply(command)
each(&command.method(:call))
end
def each
return enum_for(:each) unless block_given?
walk(@tree, []) do |node, path|
yield(node, path)
end
end
def walk(node, path, &block)
case node
when Hash
node.each do |(k, v)|
walk(v, path + [k], &block)
end
when Array
node.each_with_index do |v, i|
walk(v, path + [i.to_s], &block)
end
else
yield(node, path)
end
end
end
class Flatten
def initialize(out)
@out = out
end
attr_reader :out
def call(current, path)
case current
when String
padded = current.gsub("\n", "\n ")
out.puts "#{path.join('.')} #{padded}"
else
out.puts "#{path.join('.')} #{current.inspect}"
end
end
end
class Search
def initialize(out, pattern)
@out = out
@pattern = pattern
end
attr_reader :out, :pattern
def call(current, path)
out.puts current.inspect if path.join('.') =~ pattern
end
end
command = case ARGV.first
when 'search'
ARGV.shift
Search.new(STDOUT, Regexp.new(ARGV.shift))
else
Flatten.new(STDOUT)
end
yaml_src = ARGF.read
Tree.new(yaml_src).apply(command)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment