Skip to content

Instantly share code, notes, and snippets.

@Stono
Last active February 23, 2018 14:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Stono/73c4528a5c3497bbdba3747c7d39fba6 to your computer and use it in GitHub Desktop.
Save Stono/73c4528a5c3497bbdba3747c7d39fba6 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'psych'
require 'fileutils'
require 'yaml'
# These mappings are used by looking at the Type of the resource, and then
# from that deciding the sub folder
@mappings = {
'CustomResourceDefinition' => 'custom-resources',
'ClusterRole' => 'rbac/role',
'ClusterRoleBinding' => 'rbac/role-binding',
'ConfigMap' => 'configmap',
'Service' => 'service',
'ServiceAccount' => 'service-account',
'Deployment' => 'deployment',
'Namespace' => 'namespace',
'MutatingWebhookConfiguration' => 'webhook'
}
# These mappings forcefully override the path for some resources
@mapping_overrides = {
'istio/templates/vendor/webhook/istio-sidecar-injector.yaml' => 'manual/istio-sidecar-injector.yaml'
}
def ensure_has_labels(manifest)
if manifest['metadata']['labels'].nil?
manifest['metadata']['labels'] = nil
end
end
def decide_target(manifest, chart)
# Stick the stuff that depends on CRDs in the crd chart
if manifest['apiVersion'] == 'config.istio.io/v1alpha2'
return "istio-crd/templates/vendor/#{manifest['kind']}/#{manifest['metadata']['name']}.yaml"
end
# Stick everything else in the separate chart
target = @mappings[manifest['kind'].strip]
if target.nil?
raise "Unable to find mapping target for Kind: #{manifest['kind']}"
end
target = "#{chart}/templates/vendor/#{target}/#{manifest['metadata']['name']}.yaml"
if not @mapping_overrides[target].nil?
target = @mapping_overrides[target]
end
return target
end
def write_manifest(file_target, manifest)
path = File.dirname(file_target)
result = manifest.to_yaml({:line_width => -1})
if not file_target.start_with?('manual')
# Add standard labels
result = result.sub(' labels:', " labels:\n{{ include \"istio.labels.standard\" . | indent 4 }}")
end
FileUtils.mkdir_p path
if File.exists?(file_target)
throw "Error: #{file_target} already exists!"
else
puts "writing #{file_target}"
File.open(file_target, 'w') { |file| file.write(result) }
end
end
def ensure_service_is_internal(manifest)
if manifest['kind'] == 'Service' and manifest['spec']['type'] == 'LoadBalancer'
manifest['metadata']['annotations'] = {
'cloud.google.com/load-balancer-type' => 'Internal'
}
end
end
# These are components we dont want
@ignore_list = [
'istio/templates/vendor/service/istio-ingress.yaml',
'istio/templates/vendor/deployment/istio-ingress.yaml',
'istio/templates/vendor/namespace/istio-system.yaml',
'istio/templates/vendor/webhook/istio-sidecar-injector.yaml',
'istio-prometheus/templates/vendor/deployment/prometheus.yaml',
'istio-grafana/templates/vendor/deployment/grafana.yaml'
]
istio_exclude_9090 = -> (yaml) {
if yaml['metadata']['annotations'].nil?
yaml['metadata']['annotations'] = {}
end
yaml['metadata']['annotations']['auth.istio.io/9090'] = 'NONE'
}
istio_exclude_3000 = -> (yaml) {
if yaml['metadata']['annotations'].nil?
yaml['metadata']['annotations'] = {}
end
yaml['metadata']['annotations']['auth.istio.io/3000'] = 'NONE'
}
# See: https://github.com/istio/istio/issues/3155
long_cert_expiry = -> (yaml) {
yaml['spec']['template']['spec']['containers'][0]['args'].push('--max-workload-cert-ttl')
yaml['spec']['template']['spec']['containers'][0]['args'].push('8760h')
yaml['spec']['template']['spec']['containers'][0]['args'].push('--workload-cert-ttl')
yaml['spec']['template']['spec']['containers'][0]['args'].push('8760h')
}
# See: https://github.com/istio/istio/issues/3392
add_nodes_proxy = -> (yaml) {
yaml['rules'][0]['resources'].push('nodes/proxy')
}
do_config = -> (yaml) {
yaml['data']['mesh'] = yaml['data']['mesh'].sub('ingressService: istio-ingress', '')
}
reload_if_config_changes = -> (yaml) {
if yaml['spec']['template']['metadata']['annotations'].nil?
yaml['spec']['template']['metadata']['annotations'] = {}
end
yaml['spec']['template']['metadata']['annotations']['checksum/config'] = '{{ include (print $.Template.BasePath "/vendor/configmap/istio.yaml") . | sha256sum }}'
}
@mutators = {
'istio-grafana/templates/vendor/service/grafana.yaml' => [istio_exclude_3000],
'istio-prometheus/templates/vendor/service/prometheus.yaml' => [istio_exclude_9090],
'istio/templates/vendor/deployment/istio-ca.yaml' => [long_cert_expiry],
'istio-prometheus/templates/vendor/rbac/role/prometheus.yaml' => [add_nodes_proxy],
'istio/templates/vendor/configmap/istio.yaml' => [do_config],
'istio/templates/vendor/deployment/istio-pilot.yaml' => [reload_if_config_changes]
}
def template_file(path, chart)
file = File.open(path, "rb")
contents = file.read
contents.split('---').each do |manifest|
yaml = Psych.load(manifest)
if yaml
file_target = decide_target(yaml, chart)
if not @ignore_list.include?(file_target)
if not @mutators[file_target].nil?
@mutators[file_target].each do |lambda|
lambda.call(yaml)
end
end
ensure_has_labels(yaml)
ensure_service_is_internal(yaml)
write_manifest(file_target, yaml)
else
puts "Ignoring #{file_target}"
end
end
end
end
def prompt(*args)
print(*args)
gets
end
def remove_dir(target)
if File.exists?(target)
FileUtils.rm_r target
end
FileUtils.mkdir_p target
end
def remove_file(target)
if File.exists?(target)
FileUtils.rm target
end
end
def download_release(version)
path = "src/#{version}"
if not File.exists?(path)
FileUtils.mkdir_p path
url = "https://github.com/istio/istio/releases/download/#{version}/istio-#{version}-osx.tar.gz"
puts "Downloading: #{url}"
`wget #{url} -O /tmp/istio-#{version}.tar.gz`
`tar xf /tmp/istio-#{version}.tar.gz -C src/#{version} --strip 1`
end
end
def prep_chart(name, version)
# Remove any existing vendor files
remove_dir("#{name}/templates/vendor")
# Update the chart version
chart = YAML.load_file "#{name}/Chart.yaml"
chart['version'] = version
File.open("#{name}/Chart.yaml", 'w') { |f| YAML.dump(chart, f) }
end
def update_istio_inject_config(version)
`cp -f src/#{version}/install/kubernetes/istio-sidecar-injector-configmap-release.yaml manual/istio-sidecar-injector-configmap-release.yaml`
istio_config = "manual/istio-sidecar-injector-configmap-release.yaml"
f = File.open(istio_config, "rb")
result = f.read
result = result.sub(' - 1337', " - 1337\n - \"-i\"\n - 10.192.64.0/20,10.202.0.0/16,10.192.32.0/20,10.198.0.0/16,10.192.0.0/20,10.194.0.0/16")
result = result.sub('policy: enabled', "policy: disabled")
File.open(istio_config, 'w') { |file| file.write(result) }
end
# Prompt the user for the version to download
default = '0.5.1'
version = prompt "Istio version (#{default}): "
version.strip!
version = default if version.size == 0
# Prep the directories for the new files being written
prep_chart('istio', version)
prep_chart('istio-crd', version)
prep_chart('istio-grafana', version)
prep_chart('istio-prometheus', version)
prep_chart('istio-jaeger', version)
remove_file('manual/istio-sidecar-injector.yaml')
# Download the version of istio we want
download_release(version)
# Template the files from the official istio releases into our sub charts
template_file("src/#{version}/install/kubernetes/istio-auth.yaml", "istio")
template_file("src/#{version}/install/kubernetes/addons/grafana.yaml", "istio-grafana")
template_file("src/#{version}/install/kubernetes/addons/prometheus.yaml", "istio-prometheus")
template_file("src/#{version}/install/kubernetes/istio-sidecar-injector.yaml", "istio")
# Insert the custom ip ranges to the auto injector configmap
update_istio_inject_config(version)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment