Skip to content

Commit

Permalink
Merge branch 'master' into jylee/deletedefaultclasses
Browse files Browse the repository at this point in the history
  • Loading branch information
eatwithforks authored Oct 8, 2018
2 parents 59700d3 + cdf5940 commit b92f947
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 74 deletions.
2 changes: 1 addition & 1 deletion lib/samson/extra_dig.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def dig_set(keys, value)
raise ArgumentError, "No key given" if keys.empty?
keys = keys.dup
last = keys.pop
failed = ->(*) { raise KeyError, "key not found: #{(keys << last).inspect}" }
failed = ->(*) { raise KeyError, "key not found: #{keys.inspect}" }
nested = keys.inject(self) { |h, k| h.fetch(k, &failed) }
nested[last] = value
end
Expand Down
4 changes: 2 additions & 2 deletions lib/samson/logging.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
{
params: params,
user_id: request.env['warden']&.user&.id,
ip: request.remote_ip
client_ip: request.remote_ip
}
end

config.logger = Syslog::Logger.new('samson')
config.action_cable.logger = Syslog::Logger.new('samson')
config.action_cable.logger.formatter = Samson::SyslogFormatter.new
config.lograge.formatter = Lograge::Formatters::Logstash.new
config.logger.formatter = config.action_cable.logger.formatter = Samson::SyslogFormatter.new

elsif ENV["SERVER_MODE"] # regular file logger that needs rotating
# Reopen logfile when we receive a SIGHUP for log-rotation
Expand Down
21 changes: 17 additions & 4 deletions lib/samson/syslog_formatters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,24 @@
module Samson
class SyslogFormatter < Syslog::Logger::Formatter
def call(severity, timestamp, _progname, message)
message_h =
if message.is_a?(String) && message.start_with?('{')
begin
JSON.parse(message)
rescue JSON::ParserError
{message: message}
end
elsif message.is_a?(Hash)
message
else
{message: message}
end
{
severity: severity,
time: timestamp,
message: message
}.to_json
level: severity,
"@timestamp": timestamp,
application: "samson",
host: Rails.application.config.samson.uri.host
}.merge(message_h).to_json
end
end
end
38 changes: 19 additions & 19 deletions plugins/kubernetes/app/models/kubernetes/template_filler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def to_hash(verification: false)

set_namespace
set_project_labels if template.dig(:metadata, :annotations, :"samson/override_project_label")
set_deploy_url

case kind
when 'HorizontalPodAutoscaler'
Expand Down Expand Up @@ -48,8 +49,6 @@ def to_hash(verification: false)
set_pre_stop if kind == 'Deployment'

set_name
set_contact_info
set_repo_info
set_spec_template_metadata
set_docker_image unless verification
set_resource_usage
Expand Down Expand Up @@ -91,6 +90,15 @@ def build_selector_for_container(container)
end
end

def set_deploy_url
templates = [template]
templates << pod_template if Kubernetes::RoleConfigFile::PRIMARY_KINDS.include?(template[:kind])
templates.each do |t|
annotations = (t[:metadata][:annotations] ||= {})
annotations[:"samson/deploy_url"] = @doc.kubernetes_release.deploy&.url
end
end

def set_service_blue_green
template.dig_set([:spec, :selector, :blue_green], blue_green_color)
end
Expand Down Expand Up @@ -177,13 +185,14 @@ def set_history_limit
def expand_secret_annotations
resolver = Samson::Secrets::KeyResolver.new(project, [@doc.deploy_group])
secret_annotations.each do |k, v|
annotations = pod_annotations
annotations.delete(k)
resolver.expand(k, v).each { |k, v| annotations[k.to_sym] = v }
end
resolver.verify!
end

def annotations
def pod_annotations
pod_template[:metadata][:annotations] ||= {}
end

Expand All @@ -195,17 +204,8 @@ def pod_template
end
end

def set_contact_info
annotations[:deployer] = @doc.kubernetes_release.user&.email.to_s
annotations[:owner] = project.owner.to_s
end

def set_repo_info
annotations[:"samson/github-repo"] = project.repository_path
end

def secret_annotations
annotations.select do |annotation_name, _|
pod_annotations.select do |annotation_name, _|
annotation_name.to_s.start_with?(SECRET_PREFIX)
end
end
Expand Down Expand Up @@ -253,9 +253,9 @@ def set_init_containers
key = Kubernetes::Api::Pod::INIT_CONTAINER_KEY
if init_containers_in_beta?
pod_template.dig_set([:spec, :initContainers], init_containers)
annotations.delete(key)
pod_annotations.delete(key)
else
annotations[key] = JSON.pretty_generate(init_containers)
pod_annotations[key] = JSON.pretty_generate(init_containers)
pod_template[:spec].delete(:initContainers)
end
end
Expand Down Expand Up @@ -352,7 +352,7 @@ def missing_env
end

def required_env
((annotations || {})[:"samson/required_env"] || "").strip.split(/[\s,]+/)
(pod_annotations[:"samson/required_env"] || "").strip.split(/[\s,]+/)
end

def verify_env
Expand Down Expand Up @@ -442,14 +442,14 @@ def convert_secret_env_to_annotations
converted << value

key = "#{SECRET_PREFIX}#{var.fetch(:name)}".to_sym
if (old = annotations[key]) && old != secret_key
if (old = pod_annotations[key]) && old != secret_key
raise(
Samson::Hooks::UserError,
"Annotation key #{key} is already set to #{old}, cannot set it via environment to #{secret_key}.\n" \
"Either delete the environment variable or make them both point to the same key."
)
end
annotations[key] = secret_key
pod_annotations[key] = secret_key
end
end
end
Expand Down Expand Up @@ -500,7 +500,7 @@ def set_pre_stop

def init_containers
@init_containers ||=
JSON.parse(annotations[Kubernetes::Api::Pod::INIT_CONTAINER_KEY] || '[]', symbolize_names: true) +
JSON.parse(pod_annotations[Kubernetes::Api::Pod::INIT_CONTAINER_KEY] || '[]', symbolize_names: true) +
(pod_template.dig(:spec, :initContainers) || [])
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def worker_is_unstable
end

it "does limited amounts of queries" do
assert_sql_queries(26) do
assert_sql_queries(27) do
assert execute, out
end
end
Expand Down
53 changes: 12 additions & 41 deletions plugins/kubernetes/test/models/kubernetes/template_filler_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ def add_init_container(container)
it "sets name for unknown kinds" do
raw_template[:kind] = "foobar"
template.to_hash[:metadata][:name].must_equal "test-app-server"

it "adds deploy url to resource and templates" do
result = template.to_hash
result.dig(:metadata, :annotations, :"samson/deploy_url").must_equal doc.kubernetes_release.deploy.url
result.dig(:spec, :template, :metadata, :annotations, :"samson/deploy_url").
must_equal doc.kubernetes_release.deploy.url
end

describe "unqiue deployments" do
Expand Down Expand Up @@ -166,49 +172,14 @@ def add_init_container(container)
end
end

describe "deployer" do
let(:result) { template.to_hash.dig_fetch(:spec, :template, :metadata, :annotations, :deployer) }

it "sets deployer" do
result.must_equal "[email protected]"
end

it "does not set nil deployer which breaks kubernetes api" do
doc.kubernetes_release.user.email = nil
result.must_equal ""
end
end

describe "owner" do
let(:result) { template.to_hash.dig_fetch(:spec, :template, :metadata, :annotations, :owner) }

it "sets owner" do
project.owner = "[email protected]"
result.must_equal "[email protected]"
end

it "does not set nil owner which breaks kubernetes api" do
project.owner = nil
result.must_equal ""
end
end

describe "github-repo" do
let(:result) { template.to_hash.dig_fetch(:spec, :template, :metadata, :annotations, :"samson/github-repo") }

it "sets github-repo" do
result.must_equal "bar/foo"
end
end

describe "configmap" do
it "only modifies namespace since there is no template" do
raw_template[:kind] = "ConfigMap"
raw_template.delete(:spec)
raw_template[:metadata][:namespace] = 'old'
old = raw_template.deep_dup
old[:metadata][:namespace] = 'pod1'
template.to_hash.must_equal old
result = template.to_hash
result[:metadata][:namespace].must_equal 'pod1'
refute result[:spec]
end
end

Expand Down Expand Up @@ -834,9 +805,9 @@ def secret_annotations(hash)
end

describe "when something is required" do
let(:annotations) { raw_template[:spec][:template][:metadata][:annotations] = {} }
let(:pod_annotations) { raw_template[:spec][:template][:metadata][:annotations] = {} }

before { annotations[:"samson/required_env"] = 'FOO' }
before { pod_annotations[:"samson/required_env"] = 'FOO' }

it "fails when value is missing" do
e = assert_raises Samson::Hooks::UserError do
Expand All @@ -846,7 +817,7 @@ def secret_annotations(hash)
end

it "fails when multiple values are missing" do
annotations[:"samson/required_env"] = 'FOO BAR,BAZ, FOO2 FOO3'
pod_annotations[:"samson/required_env"] = 'FOO BAR,BAZ, FOO2 FOO3'
e = assert_raises Samson::Hooks::UserError do
template.send(:verify_env)
end
Expand Down
2 changes: 1 addition & 1 deletion test/lib/samson/extra_dig_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

it "does not set missing since we do not know if things are arrays or hashes" do
e = assert_raises(KeyError) { subject.dig_set([:b, :c], 2) }
e.message.must_equal "key not found: [:b, :c]"
e.message.must_equal "key not found: [:b]"
end

it "fail without value" do
Expand Down
48 changes: 43 additions & 5 deletions test/lib/samson/syslog_formatters_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,52 @@

describe Samson::SyslogFormatter do
describe '.json' do
before do
@output = StringIO.new
@logger = Logger.new(@output)
@logger.formatter = Samson::SyslogFormatter.new
@log_template = {level: "INFO", "@timestamp": Time.now, application: "samson", host: "www.test-url.com"}
end

def output_matcher(message, output)
@log_template[:"@timestamp"] = Time.now
@logger.info(message)
expected = @log_template.merge(output)
@output.string.must_equal(expected.to_json)
end

it 'returns a json formatted log' do
travel_to Time.parse("2017-05-01 01:00 +0000").utc do
output = StringIO.new
logger = Logger.new(output)
logger.formatter = Samson::SyslogFormatter.new
logger.info('test')
message = 'test'
output_matcher(message, message: message)
end
end

it 'allows Hash and appends to log' do
travel_to Time.parse("2017-05-01 01:00 +0000").utc do
message = {content: "xyz", data: "123"}
output_matcher(message, message)
end
end

output.string.must_equal({severity: "INFO", time: Time.now, message: "test"}.to_json)
it 'returns original message with invalid json' do
travel_to Time.parse("2017-05-01 01:00 +0000").utc do
message = "{\"content\",\"xyz\",\"data\",\"123\"}"
output_matcher(message, message: message)
end
end

it 'parse and format json messages' do
travel_to Time.parse("2017-05-01 01:00 +0000").utc do
message = {content: "xyz"}
output_matcher(message.to_json, message)
end
end

it 'skips parser when message isn`t hash' do
travel_to Time.parse("2017-05-01 01:00 +0000").utc do
message = "[1,2]"
output_matcher(message, message: message)
end
end
end
Expand Down

0 comments on commit b92f947

Please sign in to comment.