diff --git a/CHANGELOG.md b/CHANGELOG.md index 8caf7747a..f74d54826 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## next +*Bug Fixes* +- Help ruby correctly identify kubectl output encoding. [#646](https://github.com/Shopify/krane/pull/646) + ## 1.1.1 *Enhancements* diff --git a/lib/krane/kubectl.rb b/lib/krane/kubectl.rb index f3451e6ca..3278f1586 100644 --- a/lib/krane/kubectl.rb +++ b/lib/krane/kubectl.rb @@ -34,7 +34,16 @@ def run(*args, log_failure: nil, use_context: true, use_namespace: true, output: (1..attempts).to_a.each do |current_attempt| logger.debug("Running command (attempt #{current_attempt}): #{cmd.join(' ')}") out, err, st = Open3.capture3(*cmd) - logger.debug("Kubectl out: " + out.gsub(/\s+/, ' ')) unless output_is_sensitive + + # https://github.com/Shopify/krane/issues/395 + unless out.valid_encoding? + out = out.dup.force_encoding(Encoding::UTF_8) + end + + if logger.debug? && !output_is_sensitive + # don't do the gsub unless we're going to print this + logger.debug("Kubectl out: " + out.gsub(/\s+/, ' ')) + end break if st.success? raise(ResourceNotFoundError, err) if err.match(ERROR_MATCHERS[:not_found]) && raise_if_not_found diff --git a/test/unit/krane/kubectl_test.rb b/test/unit/krane/kubectl_test.rb index f13efb852..a87294485 100644 --- a/test/unit/krane/kubectl_test.rb +++ b/test/unit/krane/kubectl_test.rb @@ -348,6 +348,29 @@ def test_retry_delay_backoff end end + def test_kubectl_run_fixes_encoding_when_locales_set_to_non_utf8 + ext_before = Encoding.default_external + int_before = Encoding.default_internal + logger.level = ::Logger::DEBUG + utf8 = "こんにちは!hélas!" + + # This is how setting the env from https://github.com/Shopify/krane/issues/395 manifests internally + Encoding.default_external = Encoding::US_ASCII + Encoding.default_internal = nil + + # put the string through the default external encoder + data = %x(echo #{utf8}) + assert_equal(Encoding::US_ASCII, data.encoding) + + stub_open3(%W(kubectl get pods --namespace=testn --context=testc --request-timeout=#{timeout}), resp: data) + out, _err, _st = build_kubectl.run("get", "pods") + assert_equal(utf8, out) + assert_equal(Encoding::UTF_8, out.encoding) + ensure + Encoding.default_external = ext_before + Encoding.default_internal = int_before + end + private def timeout