From 6c98438fc534c5beb6a689eab6f66f0d7ddf3b71 Mon Sep 17 00:00:00 2001 From: "Michael N. Lipp" Date: Sat, 19 Aug 2023 15:22:31 +0200 Subject: [PATCH] Basics for automated test. --- dev-example/Readme.md | 4 + dev-example/config.yaml | 8 +- dev-example/kustomization.yaml | 15 ++++ dev-example/test-vm.yaml | 5 -- org.jdrupes.vmoperator.manager/build.gradle | 17 ++++ .../test-resources/unittest-vm.yaml | 35 ++++++++ .../vmoperator/manager/BasicTests.java | 81 +++++++++++++++++++ .../vmoperator/manager/package-info.java | 1 + .../.settings/org.eclipse.jdt.core.prefs | 10 +-- 9 files changed, 160 insertions(+), 16 deletions(-) create mode 100644 org.jdrupes.vmoperator.manager/test-resources/unittest-vm.yaml create mode 100644 org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/BasicTests.java create mode 100644 org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/package-info.java diff --git a/dev-example/Readme.md b/dev-example/Readme.md index c8e40eb..99f8d0f 100644 --- a/dev-example/Readme.md +++ b/dev-example/Readme.md @@ -13,3 +13,7 @@ The `kustomize.yaml` also changes the image repository for the operator to a private repository for development. You have to either remove this or adapt it to your own repository if you also want to test your development version in a container. + +If you want to run the unittests, this setup must be run with a private +repository and the private repository must match the one configured +for gradle pushImages. \ No newline at end of file diff --git a/dev-example/config.yaml b/dev-example/config.yaml index 6b1e824..6f380de 100644 --- a/dev-example/config.yaml +++ b/dev-example/config.yaml @@ -1,12 +1,8 @@ -# The values in comments are the defaults. - +# Used for running manager outside Kubernetes. +# Keep in sync with kustomize.yaml "/Manager": "/Controller": namespace: vmop-dev "/Reconciler": runnerData: storageClassName: null - loadBalancerService: | - labels: - test1: info - test2: toBeDeleted diff --git a/dev-example/kustomization.yaml b/dev-example/kustomization.yaml index 2974028..142aff3 100644 --- a/dev-example/kustomization.yaml +++ b/dev-example/kustomization.yaml @@ -20,6 +20,21 @@ patches: storage: 10Gi storageClassName: local-path +- patch: |- + kind: ConfigMap + apiVersion: v1 + metadata: + name: vm-operator + data: + # Keep in sync with config.yaml + config.yaml: | + "/Manager": + "/Controller": + namespace: vmop-dev + "/Reconciler": + runnerData: + storageClassName: null + - target: group: apps version: v1 diff --git a/dev-example/test-vm.yaml b/dev-example/test-vm.yaml index 500efd2..f82c973 100644 --- a/dev-example/test-vm.yaml +++ b/dev-example/test-vm.yaml @@ -14,11 +14,6 @@ spec: cpu: 1 memory: 2Gi - loadBalancerService: - labels: - test2: null - test3: added - vm: # state: Running bootMenu: yes diff --git a/org.jdrupes.vmoperator.manager/build.gradle b/org.jdrupes.vmoperator.manager/build.gradle index f0d47ec..0d32058 100644 --- a/org.jdrupes.vmoperator.manager/build.gradle +++ b/org.jdrupes.vmoperator.manager/build.gradle @@ -21,6 +21,8 @@ dependencies { runtimeOnly 'com.electronwill.night-config:yaml:3.6.6' runtimeOnly 'org.slf4j:slf4j-jdk14:[2.0.7,3)' + + testImplementation 'io.fabric8:kubernetes-client:6.8.1' } application { @@ -75,3 +77,18 @@ task pushImages { dependsOn pushLatestImage } +test { + enabled = project.hasProperty("k8s.testCluster") + + dependsOn project.tasks["pushImages"] + + useJUnitPlatform() + + testLogging { + showStandardStreams = true + } + + systemProperty "k8s.testCluster", project.hasProperty("k8s.testCluster") + ? project.getProperty("k8s.testCluster") : null +} + diff --git a/org.jdrupes.vmoperator.manager/test-resources/unittest-vm.yaml b/org.jdrupes.vmoperator.manager/test-resources/unittest-vm.yaml new file mode 100644 index 0000000..0d395bd --- /dev/null +++ b/org.jdrupes.vmoperator.manager/test-resources/unittest-vm.yaml @@ -0,0 +1,35 @@ +apiVersion: "vmoperator.jdrupes.org/v1" +kind: VirtualMachine +metadata: + namespace: vmop-dev + name: unittest-vm +spec: + resources: + requests: + cpu: 1 + memory: 2Gi + + loadBalancerService: + labels: + test2: null + test3: added + + vm: + # state: Running + maximumRam: 4Gi + currentRam: 2Gi + maximumCpus: 4 + currentCpus: 2 + powerdownTimeout: 1 + + networks: + - user: {} + disks: + - cdrom: + # image: "" + image: https://download.fedoraproject.org/pub/fedora/linux/releases/38/Workstation/x86_64/iso/Fedora-Workstation-Live-x86_64-38-1.6.iso + # image: "Fedora-Workstation-Live-x86_64-38-1.6.iso" + + display: + spice: + port: 5812 diff --git a/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/BasicTests.java b/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/BasicTests.java new file mode 100644 index 0000000..9452608 --- /dev/null +++ b/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/BasicTests.java @@ -0,0 +1,81 @@ +package org.jdrupes.vmoperator.manager; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext; +import io.fabric8.kubernetes.client.Config; + +class BasicTests { + + private static KubernetesClient client; + private static ResourceDefinitionContext vmsContext; + + @BeforeAll + static void setUpBeforeClass() throws Exception { + var testCluster = System.getProperty("k8s.testCluster"); + assertNotNull(testCluster); + + // Get client + client = new KubernetesClientBuilder() + .withConfig(Config.autoConfigure(testCluster)).build(); + + // Context for working with our CR + vmsContext = new ResourceDefinitionContext.Builder() + .withGroup("vmoperator.jdrupes.org").withKind("VirtualMachine") + .withPlural("vms").withNamespaced(true).withVersion("v1").build(); + + // Cleanup + var resourcesInNamespace = client.genericKubernetesResources(vmsContext) + .inNamespace("vmop-dev"); + resourcesInNamespace.withName("unittest-vm").delete(); + + // Update pod by scaling deployment + client.apps().deployments().inNamespace("vmop-dev") + .withName("vm-operator").scale(0); + client.apps().deployments().inNamespace("vmop-dev") + .withName("vm-operator").scale(1); + + // Wait until available + for (int i = 0; i < 10; i++) { + if (client.apps().deployments().inNamespace("vmop-dev") + .withName("vm-operator").get().getStatus().getConditions() + .stream().filter(c -> "Available".equals(c.getType())).findAny() + .isPresent()) { + return; + } + } + fail("vm-operator not deployed."); + } + + @AfterAll + static void tearDownAfterClass() throws Exception { + // Bring down manager + client.apps().deployments().inNamespace("vmop-dev") + .withName("vm-operator").scale(0); + client.close(); + } + + @Test + void test() throws IOException { + // Load from Yaml + var vm = client.genericKubernetesResources(vmsContext) + .load(Files + .newInputStream(Path.of("test-resources/unittest-vm.yaml"))); + // Create Custom Resource + vm.create(); + + // Cleanup + var resourcesInNamespace = client.genericKubernetesResources(vmsContext) + .inNamespace("vmop-dev"); + resourcesInNamespace.withName("unittest-vm").delete(); + } + +} diff --git a/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/package-info.java b/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/package-info.java new file mode 100644 index 0000000..7a983a6 --- /dev/null +++ b/org.jdrupes.vmoperator.manager/test/org/jdrupes/vmoperator/manager/package-info.java @@ -0,0 +1 @@ +package org.jdrupes.vmoperator.manager; \ No newline at end of file diff --git a/org.jdrupes.vmoperator.util/.settings/org.eclipse.jdt.core.prefs b/org.jdrupes.vmoperator.util/.settings/org.eclipse.jdt.core.prefs index c3c017d..c3d4bc7 100644 --- a/org.jdrupes.vmoperator.util/.settings/org.eclipse.jdt.core.prefs +++ b/org.jdrupes.vmoperator.util/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,5 @@ # -#Wed Aug 02 12:50:19 CEST 2023 +#Sat Aug 19 11:33:46 CEST 2023 org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert @@ -22,12 +22,12 @@ org.eclipse.jdt.core.formatter.blank_lines_after_package=1 org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.comment.indent_root_tags=false org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=false org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=false -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert @@ -43,8 +43,8 @@ org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invoc org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 @@ -63,8 +63,8 @@ org.eclipse.jdt.core.formatter.alignment_for_type_parameters=16 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert