Skip to content

Commit ff08da2

Browse files
committed
Consistantly use unsafe_load for YAML
Turns out kubernetes manifests are unpredictable and can contain eg. Symbol and Time formats which raise exceptions.
1 parent 6a3ef5a commit ff08da2

1 file changed

Lines changed: 21 additions & 16 deletions

File tree

k

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ require "yaml"
1212
require "tmpdir"
1313
require "uri"
1414

15+
# Older versions of YAML (ie. in Ruby 2.5) don't have unsafe_load
16+
def yaml_load(string)
17+
YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(string) : YAML.load(string)
18+
end
19+
1520
# rubocop:disable Style/StringConcatenation
1621

1722
K_CONFIG_FILE = "#{ENV.fetch('HOME')}/.k/config".freeze
@@ -106,7 +111,7 @@ end
106111

107112
def resources_for_argocd_application(kind, application)
108113
yaml_output = read_kubectl("get #{kind} -o yaml")
109-
resources = YAML.load(yaml_output, permitted_classes: [Time]).fetch("items")
114+
resources = yaml_load(yaml_output).fetch("items")
110115
resources.select do |item|
111116
annotations = item.dig("metadata", "annotations") || {}
112117
tracking_id = annotations["argocd.argoproj.io/tracking-id"]
@@ -785,17 +790,17 @@ module Pg
785790
cluster = read_kubectl("get cluster #{cluster_name} -o yaml")
786791
abort "Error: cluster '#{cluster_name}' not found" if cluster.empty?
787792

788-
cluster = YAML.load(cluster, permitted_classes: [Time])
793+
cluster = yaml_load(cluster)
789794
user ||= cluster_name
790795

791796
app_secret = read_kubectl("get secret #{cluster_name}-app -o yaml")
792797
abort "ERROR: Could not find authentication secret for '#{cluster_name}'" if app_secret.empty?
793-
app_secret = YAML.load(app_secret).fetch("data")
798+
app_secret = yaml_load(app_secret).fetch("data")
794799

795800
if user == "superuser"
796801
superuser_secret = read_kubectl("get secret #{cluster_name}-superuser -o yaml")
797802
abort "ERROR: Could not find superuser secret for '#{cluster_name}'" if superuser_secret.empty?
798-
superuser_secret = YAML.load(superuser_secret).fetch("data")
803+
superuser_secret = yaml_load(superuser_secret).fetch("data")
799804

800805
# Superuser secrets use * as dbname since they can theoretically connect to any database,
801806
# however this doesn't provide valid URL's to successfully connect via psql.
@@ -878,7 +883,7 @@ def pg_failover
878883
# }
879884
# ...
880885
# }
881-
status = YAML.load(status_yaml)
886+
status = yaml_load(status_yaml)
882887
instance_state = status.dig("cluster", "status", "instancesReportedState")
883888
non_primary_instance = instance_state.find { |_, state| !state["isPrimary"] }
884889
abort "No non-primary instance found for cluster '#{cluster}'" unless non_primary_instance
@@ -1532,7 +1537,7 @@ def elasticsearch_url
15321537
require "base64"
15331538

15341539
secret = read_kubectl("get secret #{elasticsearch_cluster}-es-elastic-user -o yaml")
1535-
password = YAML.load(secret).fetch("data").fetch("elastic")
1540+
password = yaml_load(secret).fetch("data").fetch("elastic")
15361541
decoded_password = Base64.strict_decode64(password)
15371542

15381543
puts "http://elastic:#{decoded_password}@#{elasticsearch_cluster}-es-http:9200"
@@ -2331,8 +2336,8 @@ def generate_deployment
23312336
.match(/# Example values\.yaml:\n([\s\S]*?)\n\n/)[1]
23322337
.gsub(/^# /, "")
23332338
values_string = File.read(values_path)
2334-
template_values = YAML.load(template_values_string)
2335-
values = YAML.load(values_string)
2339+
template_values = yaml_load(template_values_string)
2340+
values = yaml_load(values_string)
23362341

23372342
# Handle image:
23382343
if template_values.key?("image") && !values.key?("image")
@@ -2456,8 +2461,8 @@ def generate_resource
24562461
.match(/# Example values\.yaml:\n([\s\S]*?)\n\n/)[1]
24572462
.gsub(/^# /, "")
24582463
values_string = File.read(values_path)
2459-
template_values = YAML.load(template_values_string)
2460-
values = YAML.load(values_string)
2464+
template_values = yaml_load(template_values_string)
2465+
values = yaml_load(values_string)
24612466

24622467
# NOTE: We assume that 'resources', 'envFrom' and 'env' nodes exists in all
24632468
# application values.yaml files since "generate application" would create them.
@@ -2493,7 +2498,7 @@ def generate_resource
24932498
end
24942499

24952500
def node_pvcs
2496-
all_pvcs = YAML.load read_kubectl("get pvc --all-namespaces -o yaml")
2501+
all_pvcs = yaml_load read_kubectl("get pvc --all-namespaces -o yaml")
24972502

24982503
pvcs_per_node = all_pvcs.fetch("items").each_with_object({}) do |pvc, hash|
24992504
node = pvc.dig("metadata", "annotations", "volume.kubernetes.io/selected-node")
@@ -2528,7 +2533,7 @@ def node_failover
25282533
node_exists = kubectl?("get node #{node_name}")
25292534
abort "Error: node '#{node_name}' not found" unless node_exists
25302535

2531-
pods_on_node = YAML.unsafe_load(read_kubectl("get pods --field-selector spec.nodeName=#{node_name} -o yaml")).fetch("items")
2536+
pods_on_node = yaml_load(read_kubectl("get pods --field-selector spec.nodeName=#{node_name} -o yaml")).fetch("items")
25322537

25332538
primaries = pods_on_node.select do |pod|
25342539
labels = pod.fetch("metadata")["labels"]
@@ -2585,7 +2590,7 @@ def node_purge_pvcs
25852590
node_name = ARGV.delete_at(0)
25862591
abort "Must pass name of node, eg. k node:purge-pvcs <node-name> [specific-pvc]" unless node_name
25872592

2588-
all_pvcs = YAML.load read_kubectl("get pvc --all-namespaces -o yaml")
2593+
all_pvcs = yaml_load read_kubectl("get pvc --all-namespaces -o yaml")
25892594

25902595
pvcs_on_node = all_pvcs.fetch("items").select do |pvc|
25912596
pvc.dig("metadata", "annotations", "volume.kubernetes.io/selected-node") == node_name
@@ -2642,7 +2647,7 @@ def node_purge_pvcs
26422647

26432648
5.times do
26442649
sleep 0.5
2645-
all_pvcs = YAML.load read_kubectl("get pvc --all-namespaces -o yaml")
2650+
all_pvcs = yaml_load read_kubectl("get pvc --all-namespaces -o yaml")
26462651

26472652
pvcs_on_node = all_pvcs.fetch("items").select do |pvc|
26482653
pvc.dig("metadata", "annotations", "volume.kubernetes.io/selected-node") == node_name
@@ -2670,7 +2675,7 @@ def opensearch_url
26702675
secret = read_kubectl("get secret opensearch-#{opensearch_cluster}-credentials -o yaml")
26712676
abort "ERROR: No credentials secret found for opensearch cluster '#{opensearch_cluster}'" if secret.empty?
26722677

2673-
encoded_url = YAML.load(secret).fetch("data").fetch("admin_uri")
2678+
encoded_url = yaml_load(secret).fetch("data").fetch("admin_uri")
26742679
url = Base64.strict_decode64(encoded_url)
26752680

26762681
puts url
@@ -2723,7 +2728,7 @@ def opensearch_overview
27232728
secret = read_kubectl("get secret opensearch-#{opensearch_cluster}-credentials -o yaml")
27242729
abort "ERROR: No credentials secret found for opensearch cluster '#{opensearch_cluster}'" if secret.empty?
27252730

2726-
encoded_url = YAML.load(secret).fetch("data").fetch("admin_uri")
2731+
encoded_url = yaml_load(secret).fetch("data").fetch("admin_uri")
27272732
base_url = Base64.strict_decode64(encoded_url)
27282733

27292734
require "json"

0 commit comments

Comments
 (0)