Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Adaptations: CNF Installation (5.3) Disable new cluster tests and adapt service_discovery #2166

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion shard.lock
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ shards:

helm:
git: https://github.com/cnf-testsuite/helm.git
version: 1.0.2
version: 1.0.3

icr:
git: https://github.com/crystal-community/icr.git
Expand Down
3 changes: 2 additions & 1 deletion spec/workload/compatibility_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ describe "Compatibility" do
retries = retries + 1
end
Log.info { "Status: #{result[:output]}" }
(/(PASSED).*(CNF compatible with both Calico and Cilium)/ =~ result[:output]).should_not be_nil
(/(SKIPPED)).*(cni_compatible test was temporarily disabled due to needed redesign for cnf_to_new_cluster)/ =~ result[:output]).should_not be_nil
#(/(PASSED).*(CNF compatible with both Calico and Cilium)/ =~ result[:output]).should_not be_nil
ensure
result = ShellCmd.run_testsuite("cnf_cleanup cnf-config=sample-cnfs/sample-coredns-cnf/cnf-testsuite.yml")
result[:status].success?.should be_true
Expand Down
1 change: 1 addition & 0 deletions src/tasks/constants.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ ESSENTIAL_PASSED_THRESHOLD = 15
CNF_DIR = "cnfs"
CONFIG_FILE = "cnf-testsuite.yml"
BASE_CONFIG = "./config.yml"
COMMON_MANIFEST_FILE_PATH = "#{CNF_DIR}/common_manifest.yml"
PASSED = "passed"
FAILED = "failed"
SKIPPED = "skipped"
Expand Down
88 changes: 79 additions & 9 deletions src/tasks/utils/cnf_installation/manifest.cr
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
module CNFInstall
module Manifest
def self.parse_manifest_as_ymls(template_file_name="cnfs/temp_template.yml")
Log.info { "parse_manifest_as_ymls template_file_name: #{template_file_name}" }
templates = File.read(template_file_name)
split_template = templates.split(/(\s|^)---(\s|$)/)
ymls = split_template.map { | template |
#TODO strip out NOTES
YAML.parse(template)
def self.manifest_path_to_ymls(manifest_path)
Log.info { "manifest_path_to_ymls file_path: #{manifest_path}" }
manifest = File.read(manifest_path)
manifest_string_to_ymls(manifest)
end

def self.manifest_string_to_ymls(manifest_string)
Log.info { "manifest_string_to_ymls" }
split_content = manifest_string.split(/(\s|^)---(\s|$)/)
ymls = split_content.map { | manifest |
YAML.parse(manifest)
# compact seems to have problems with yaml::any
}.reject{|x|x==nil}
Log.debug { "read_template ymls: #{ymls}" }
Log.debug { "manifest_string_to_ymls:\n #{ymls}" }
ymls
end

def self.combine_ymls_as_manifest_string(ymls : Array(YAML::Any)) : String
Log.info { "combine_ymls_as_manifest_string" }
manifest = ymls.map do |yaml_object|
yaml_object.to_yaml
end.join
Log.debug { "combine_ymls_as_manifest:\n #{manifest}" }
manifest
end

def self.manifest_ymls_from_file_list(manifest_file_list)
ymls = manifest_file_list.map do |x|
parse_manifest_as_ymls(x)
manifest_path_to_ymls(x)
end
ymls.flatten
end
Expand Down Expand Up @@ -47,5 +60,62 @@ module CNFInstall
Log.debug { "manifest_containers: #{manifest_yml}" }
manifest_yml.dig?("spec", "template", "spec", "containers")
end

# Apply namespaces only to resources that are retrieved from Kubernetes as namespaced resource kinds.
# Namespaced resource kinds are utilized exclusively during the Helm installation process.
def self.add_namespace_to_resources(manifest_string, namespace)
Log.for("add_namespace_to_resources").info { "Updating metadata.namespace field for resources in generated manifest" }
namespaced_resources = KubectlClient::ShellCmd.run("kubectl api-resources --namespaced=true --no-headers", "", false).[:output]
list_of_namespaced_resources = namespaced_resources.split("\n").select { |item| !item.empty? }
list_of_namespaced_kinds = list_of_namespaced_resources.map do |line|
line.split(/\s+/).last
end
parsed_manifest = manifest_string_to_ymls(manifest_string)
ymls = [] of YAML::Any

parsed_manifest.each do |resource|
if resource["kind"].as_s.in?(list_of_namespaced_kinds)
Helm.ensure_resource_with_namespace(resource, namespace)
Log.for("add_namespace_to_resources").info { "Added #{namespace} namespace for resource: {kind: #{resource["kind"]}, name: #{resource["metadata"]["name"]}}" }
end
ymls << resource
end

string_manifest_with_namespaces = combine_ymls_as_manifest_string(ymls)
Log.for("add_namespace_to_resources").debug { "\n#{string_manifest_with_namespaces}" }
string_manifest_with_namespaces
end

def self.add_manifest_to_file(deployment_name : String, manifest : String, destination_file)
File.open(destination_file, "a+") do |file|
file.puts manifest
Log.info { "#{deployment_name} manifest was appended into #{destination_file} file" }
end
end

def self.generate_common_manifest(config, deployment_name, namespace)
manifest_generated_successfully = true
case config.dynamic.install_method[0]
when CNFInstall::InstallMethod::ManifestDirectory
destination_cnf_dir = config.dynamic.destination_cnf_dir
manifest_directory = config.deployments.get_deployment_param(:manifest_directory)
list_of_manifests = manifest_file_list( destination_cnf_dir + "/" + manifest_directory )
list_of_manifests.each do |manifest_path|
manifest = File.read(manifest_path)
add_manifest_to_file(deployment_name, manifest, COMMON_MANIFEST_FILE_PATH)
end

when CNFInstall::InstallMethod::HelmChart, CNFInstall::InstallMethod::HelmDirectory
begin
generated_manifest = Helm.generate_manifest(deployment_name, namespace)
generated_manifest_with_namespaces = add_namespace_to_resources(generated_manifest, namespace)
add_manifest_to_file(deployment_name, generated_manifest_with_namespaces, COMMON_MANIFEST_FILE_PATH)
rescue ex : Helm::ManifestGenerationError
Log.for("generate_common_manifest").error { ex.message }
manifest_generated_successfully = false
end
end
manifest_generated_successfully
end
end
end
72 changes: 21 additions & 51 deletions src/tasks/utils/cnf_manager.cr
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,19 @@ module CNFManager

def self.cnf_resource_ymls(args, config)
Log.info { "cnf_resource_ymls" }
template_ymls = [] of YAML::Any
case config.dynamic.install_method[0]
when CNFInstall::InstallMethod::HelmChart, CNFInstall::InstallMethod::HelmDirectory
helm_chart_path = CNFInstall::Config.get_helm_chart_path(config)
generated_manifest_file_path = CNFInstall::Config.get_manifest_file_path(config)
Log.info { "EXPORTED CHART PATH: #{helm_chart_path}" }
Helm.generate_manifest_from_templates(release_name: config.deployments.get_deployment_param(:name),
helm_chart: helm_chart_path,
output_file: generated_manifest_file_path,
namespace: CNFManager.get_deployment_namespace(config),
helm_values: config.deployments.get_deployment_param(:helm_values))
template_ymls = CNFInstall::Manifest.parse_manifest_as_ymls(generated_manifest_file_path)

when CNFInstall::InstallMethod::ManifestDirectory
template_ymls = CNFInstall::Manifest.manifest_ymls_from_file_list(
CNFInstall::Manifest.manifest_file_list(File.join(config.dynamic.destination_cnf_dir, config.deployments.get_deployment_param(:manifest_directory)))
)
end
manifest_ymls = CNFInstall::Manifest.manifest_path_to_ymls(COMMON_MANIFEST_FILE_PATH)

template_ymls = template_ymls.reject! {|x|
manifest_ymls = manifest_ymls.reject! {|x|
# reject resources that contain the 'helm.sh/hook: test' annotation
x.dig?("metadata","annotations","helm.sh/hook")
}
Log.debug { "template_ymls: #{template_ymls}" }
template_ymls
Log.debug { "cnf_resource_ymls: #{manifest_ymls}" }
manifest_ymls
end

def self.cnf_resources(args, config, &block)
template_ymls = cnf_resource_ymls(args, config)
resource_resp = template_ymls.map do | resource |
manifest_ymls = cnf_resource_ymls(args, config)
resource_resp = manifest_ymls.map do | resource |
resp = yield resource
Log.debug { "cnf_workload_resource yield resp: #{resp}" }
resp
Expand Down Expand Up @@ -96,9 +79,9 @@ module CNFManager

def self.cnf_workload_resources(args, config, &block)
deployment_namespace = CNFManager.get_deployment_namespace(config)
template_ymls = cnf_resource_ymls(args, config)
manifest_ymls = cnf_resource_ymls(args, config)
# call cnf cnf_resources to get unfiltered yml
resource_ymls = Helm.all_workload_resources(template_ymls, deployment_namespace)
resource_ymls = Helm.all_workload_resources(manifest_ymls, deployment_namespace)
resource_resp = resource_ymls.map do | resource |
resp = yield resource
Log.debug { "cnf_workload_resource yield resp: #{resp}" }
Expand Down Expand Up @@ -229,32 +212,6 @@ module CNFManager
cnf_testsuite_helm_directory.split("/")[-1]
end

#TODO move to helm module
def self.helm_template_header(helm_chart_or_directory : String, template_file="/tmp/temp_template.yml")
Log.info { "helm_template_header" }
Log.info { "helm_template_header helm_chart_or_directory: #{helm_chart_or_directory}" }
helm = Helm::BinarySingleton.helm
# generate helm chart release name
# use --dry-run to generate yml file
Helm.install("--dry-run --generate-name #{helm_chart_or_directory} > #{template_file}")
raw_template = File.read(template_file)
Log.debug { "raw_template: #{raw_template}" }
split_template = raw_template.split("---")
template_header = split_template[0]
parsed_template_header = YAML.parse(template_header)
Log.debug { "parsed_template_header: #{parsed_template_header}" }
parsed_template_header
end

#TODO move to helm module
def self.helm_chart_template_release_name(helm_chart_or_directory : String, template_file="/tmp/temp_template.yml")
Log.info { "helm_chart_template_release_name" }
Log.info { "helm_chart_template_release_name helm_chart_or_directory: #{helm_chart_or_directory}" }
hth = helm_template_header(helm_chart_or_directory, template_file)
Log.info { "helm template (should not be a full path): #{hth}" }
hth["NAME"]
end

def self.config_source_dir(config_file)
if File.directory?(config_file)
config_file
Expand Down Expand Up @@ -536,6 +493,15 @@ module CNFManager
else
raise "Deployment method not found"
end

#Generating manifest from installed CNF
#Returns true or false in case when manifest was generated successfully or not
manifest_generated_successfully = CNFInstall::Manifest.generate_common_manifest(config, release_name, deployment_namespace)

if !manifest_generated_successfully
stdout_failure "Manifest generation failed. Check CNF definition (helm charts, values, manifests, etc.)"
exit 1
end

resource_ymls = cnf_workload_resources(nil, config) do |resource|
resource
Expand Down Expand Up @@ -736,6 +702,10 @@ module CNFManager
def self.sample_cleanup(config_file, force=false, installed_from_manifest=false, verbose=true)
Log.info { "sample_cleanup" }
Log.info { "sample_cleanup installed_from_manifest: #{installed_from_manifest}" }

FileUtils.rm_rf(COMMON_MANIFEST_FILE_PATH)
Log.info { "#{COMMON_MANIFEST_FILE_PATH} file was removed." }

config = CNFInstall::Config.parse_cnf_config_from_file(CNFManager.ensure_cnf_testsuite_yml_path(config_file))
Log.for("verbose").info { "cleanup config: #{config.inspect}" } if verbose
destination_cnf_dir = config.dynamic.destination_cnf_dir
Expand Down
2 changes: 2 additions & 0 deletions src/tasks/workload/compatibility.cr
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,8 @@ end
desc "CNFs should work with any Certified Kubernetes product and any CNI-compatible network that meet their functionality requirements."
task "cni_compatible" do |t, args|
CNFManager::Task.task_runner(args, task: t) do |args, config|
# TODO (kosstennbl) adapt cnf_to_new_cluster metod to new installation process. Until then - test is disabled. More info: #2153
next CNFManager::TestcaseResult.new(CNFManager::ResultStatus::Skipped, "cni_compatible test was temporarily disabled, check #2153")
docker_version = DockerClient.version_info()
if docker_version.installed?
ensure_kubeconfig!
Expand Down
9 changes: 7 additions & 2 deletions src/tasks/workload/configuration.cr
Original file line number Diff line number Diff line change
Expand Up @@ -606,14 +606,19 @@ task "alpha_k8s_apis" do |t, args|
next CNFManager::TestcaseResult.new(CNFManager::ResultStatus::Skipped, "alpha_k8s_apis not in poc mode")
end

ensure_kubeconfig!
cluster_name = "apisnooptest"
kubeconfig_orig = ENV["KUBECONFIG"]

# TODO (kosstennbl) adapt cnf_to_new_cluster metod to new installation process. Until then - test is disabled. More info: #2153
result = CNFManager::TestcaseResult.new(CNFManager::ResultStatus::Skipped, "alpha_k8s_apis test was temporarily disabled, check #2153")
next result

ensure_kubeconfig!

# Get kubernetes version of the current server.
# This is used to setup kind with same k8s image version.
k8s_server_version = KubectlClient.server_version

cluster_name = "apisnooptest"
# Ensure any old cluster is deleted
KindManager.new.delete_cluster(cluster_name)
apisnoop = ApiSnoop.new()
Expand Down
3 changes: 1 addition & 2 deletions src/tasks/workload/microservice.cr
Original file line number Diff line number Diff line change
Expand Up @@ -631,8 +631,7 @@ task "service_discovery" do |t, args|
CNFManager::Task.task_runner(args, task: t) do |args,config|
# Get all resources for the CNF
resource_ymls = CNFManager.cnf_workload_resources(args, config) { |resource| resource }
deployment_namespace = CNFManager.get_deployment_namespace(config)
resources = Helm.workload_resource_kind_names(resource_ymls, default_namespace: deployment_namespace)
resources = Helm.workload_resource_kind_names(resource_ymls)

# Collect service names from the CNF resource list
cnf_service_names = [] of String
Expand Down
Loading