-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #533 from Shopify/consistent-validations
First pass at shared validation
- Loading branch information
Showing
14 changed files
with
229 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# frozen_string_literal: true | ||
module KubernetesDeploy | ||
class TaskConfig | ||
attr_reader :context, :namespace | ||
|
||
def initialize(context, namespace, logger = nil) | ||
@context = context | ||
@namespace = namespace | ||
@logger = logger | ||
end | ||
|
||
def logger | ||
@logger ||= KubernetesDeploy::FormattedLogger.build(@namespace, @context) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# frozen_string_literal: true | ||
module KubernetesDeploy | ||
class TaskConfigValidator | ||
DEFAULT_VALIDATIONS = %i( | ||
validate_kubeconfig | ||
validate_context_exists_in_kubeconfig | ||
validate_context_reachable | ||
validate_server_version | ||
validate_namespace_exists | ||
).freeze | ||
|
||
delegate :context, :namespace, :logger, to: :@task_config | ||
|
||
def initialize(task_config, kubectl, kubeclient_builder, only: nil) | ||
@task_config = task_config | ||
@kubectl = kubectl | ||
@kubeclient_builder = kubeclient_builder | ||
@errors = nil | ||
@validations = only || DEFAULT_VALIDATIONS | ||
end | ||
|
||
def valid? | ||
@errors = [] | ||
@validations.each do |validator_name| | ||
break if @errors.present? | ||
send(validator_name) | ||
end | ||
@errors.empty? | ||
end | ||
|
||
def errors | ||
valid? | ||
@errors | ||
end | ||
|
||
private | ||
|
||
def validate_kubeconfig | ||
@errors += @kubeclient_builder.validate_config_files | ||
end | ||
|
||
def validate_context_exists_in_kubeconfig | ||
unless context.present? | ||
return @errors << "Context can not be blank" | ||
end | ||
|
||
_, err, st = @kubectl.run("config", "get-contexts", context, "-o", "name", | ||
use_namespace: false, use_context: false, log_failure: false) | ||
|
||
unless st.success? | ||
@errors << if err.match("error: context #{context} not found") | ||
"Context #{context} missing from your kubeconfig file(s)" | ||
else | ||
"Something went wrong. #{err} " | ||
end | ||
end | ||
end | ||
|
||
def validate_context_reachable | ||
_, err, st = @kubectl.run("get", "namespaces", "-o", "name", | ||
use_namespace: false, log_failure: false) | ||
|
||
unless st.success? | ||
@errors << "Something went wrong connecting to #{context}. #{err} " | ||
end | ||
end | ||
|
||
def validate_namespace_exists | ||
unless namespace.present? | ||
return @errors << "Namespace can not be blank" | ||
end | ||
|
||
_, err, st = @kubectl.run("get", "namespace", "-o", "name", namespace, | ||
use_namespace: false, log_failure: false) | ||
|
||
unless st.success? | ||
@errors << if err.match("Error from server [(]NotFound[)]: namespace") | ||
"Could not find Namespace: #{namespace} in Context: #{context}" | ||
else | ||
"Could not connect to kubernetes cluster. #{err}" | ||
end | ||
end | ||
end | ||
|
||
def validate_server_version | ||
if @kubectl.server_version < Gem::Version.new(MIN_KUBE_VERSION) | ||
logger.warn(server_version_warning(@kubectl.server_version)) | ||
end | ||
end | ||
|
||
def server_version_warning(server_version) | ||
"Minimum cluster version requirement of #{MIN_KUBE_VERSION} not met. "\ | ||
"Using #{server_version} could result in unexpected behavior as it is no longer tested against" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# frozen_string_literal: true | ||
require 'integration_test_helper' | ||
|
||
class TaskConfigValidatorTest < KubernetesDeploy::IntegrationTest | ||
def test_valid_configuration | ||
assert_predicate(validator(context: KubeclientHelper::TEST_CONTEXT, namespace: 'default'), :valid?) | ||
end | ||
|
||
def test_only_is_respected | ||
assert_predicate(validator(only: []), :valid?) | ||
end | ||
|
||
def test_invalid_kubeconfig | ||
bad_file = "/IM_NOT_A_REAL_FILE.yml" | ||
builder = KubernetesDeploy::KubeclientBuilder.new(kubeconfig: bad_file) | ||
assert_match("Kubeconfig not found at #{bad_file}", | ||
validator(kubeclient_builder: builder, only: [:validate_kubeconfig]).errors.join("\n")) | ||
end | ||
|
||
def test_context_does_not_exists_in_kubeconfig | ||
fake_context = "fake-context" | ||
assert_match(/Context #{fake_context} missing from your kubeconfig file/, | ||
validator(context: fake_context).errors.join("\n")) | ||
end | ||
|
||
def test_context_not_reachable | ||
fake_context = "fake-context" | ||
assert_match(/Something went wrong connecting to #{fake_context}/, | ||
validator(context: fake_context, only: [:validate_context_reachable]).errors.join("\n")) | ||
end | ||
|
||
def test_namespace_does_not_exists | ||
assert_match(/Could not find Namespace: test-namespace in Context: #{KubeclientHelper::TEST_CONTEXT}/, | ||
validator(context: KubeclientHelper::TEST_CONTEXT).errors.join("\n")) | ||
end | ||
|
||
def test_invalid_server_version | ||
old_min_version = KubernetesDeploy::MIN_KUBE_VERSION | ||
new_min_version = "99999" | ||
KubernetesDeploy.const_set(:MIN_KUBE_VERSION, new_min_version) | ||
validator(context: KubeclientHelper::TEST_CONTEXT, namespace: 'default', logger: @logger).valid? | ||
assert_logs_match_all([ | ||
"Minimum cluster version requirement of #{new_min_version} not met.", | ||
]) | ||
ensure | ||
KubernetesDeploy.const_set(:MIN_KUBE_VERSION, old_min_version) | ||
end | ||
|
||
private | ||
|
||
def validator(context: nil, namespace: nil, logger: nil, kubeclient_builder: nil, only: nil) | ||
context ||= "test-context" | ||
namespace ||= "test-namespace" | ||
config = task_config(context: context, namespace: namespace, logger: logger) | ||
kubectl = KubernetesDeploy::Kubectl.new(namespace: config.namespace, | ||
context: config.context, logger: config.logger, log_failure_by_default: true) | ||
kubeclient_builder ||= KubernetesDeploy::KubeclientBuilder.new | ||
KubernetesDeploy::TaskConfigValidator.new(config, kubectl, kubeclient_builder, only: only) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.