diff --git a/apiclient/rancher_api/managers.py b/apiclient/rancher_api/managers.py index 5826fd6e2..b2b532d6f 100644 --- a/apiclient/rancher_api/managers.py +++ b/apiclient/rancher_api/managers.py @@ -276,8 +276,8 @@ def create_harvester(self, name, *, raw=False): raw=raw ) - def delete(self, name, *, raw=False): - return self._delete(self.PATH_fmt.format(uid=f"/{name}", ns=f"/{FLEET_DEFAULT_NAMESPACE}")) + def delete(self, name, namespace=FLEET_DEFAULT_NAMESPACE, *, raw=False): + return self._delete(self.PATH_fmt.format(uid=f"/{name}", ns=f"/{namespace}")) class ClusterRegistrationTokenManager(BaseManager): diff --git a/harvester_e2e_tests/fixtures/terraform_rancher.py b/harvester_e2e_tests/fixtures/terraform_rancher.py index fa6e4e51e..c846d5d58 100644 --- a/harvester_e2e_tests/fixtures/terraform_rancher.py +++ b/harvester_e2e_tests/fixtures/terraform_rancher.py @@ -177,7 +177,21 @@ def tf_executor(tf_script_dir): def tf_rancher(api_client, tf_script_dir, tf_provider_version, tf_executor, harvester, rancher): tf_rancher = TerraformRancher(tf_executor, tf_script_dir / datetime.now().strftime("%Hh%Mm_%m-%d")) - out, err, exc_code = tf_rancher.initial_provider(tf_provider_version, harvester, rancher) + + # kubeconfig for rancher provider + # Ref. https://registry.terraform.io/providers/rancher/rancher2/3.1.1/docs/resources/cluster_v2 + url = f'{rancher["endpoint"]}/k8s/clusters/{harvester["id"]}/v1/harvester/kubeconfig' + auth = (rancher["access_key"], rancher["secret_key"]) + data = { + "clusterRoleName": "harvesterhci.io:cloudprovider", + "namespace": "default", + "serviceAccountName": harvester["name"] + } + res = requests.post(url, auth=auth, json=data, verify=False) + kubeconfig = res.text.replace("\\n", "\n").strip('"') + + out, err, exc_code = \ + tf_rancher.initial_provider(kubeconfig, tf_provider_version, harvester, rancher) assert not err and 0 == exc_code return tf_rancher @@ -204,17 +218,7 @@ def exec_command(self, cmd, raw=False, **kws): def execute(self, cmd, raw=False, **kws): return self.exec_command(f"{self.executor} {cmd}", raw=raw, **kws) - def initial_provider(self, provider_version, harvester, rancher): - url = f'{rancher["endpoint"]}/k8s/clusters/{harvester["id"]}/v1/harvester/kubeconfig' - auth = (rancher["access_key"], rancher["secret_key"]) - data = { - "clusterRoleName": "harvesterhci.io:cloudprovider", - "namespace": "default", - "serviceAccountName": harvester["name"] - } - res = requests.post(url, auth=auth, json=data, verify=False) - kubeconfig = res.text.replace("\\n", "\n").strip('"') - + def initial_provider(self, kubeconfig, provider_version, harvester, rancher): kubefile = self.workdir / "kubeconfig" with open(kubefile, "w") as f: f.write(kubeconfig) @@ -289,7 +293,7 @@ def convert_to_hcl(self, json_spec, raw=False): out = rv.stdout.decode() out = re.sub(r'"resource"', "resource", out) # resource should not quote out = re.sub(r"\"(.+?)\" =", r"\1 =", out) # property should not quote - out = re.sub(r'"(data\.\S+?)"', r"\1", out) # data should not quote + out = re.sub(r'"(data\.\S+?)"', r"\1", out) # data should not quote out = re.sub(r"(.[^ ]+) = {", r"\1 {", out) # block should not have `=` return out @@ -316,32 +320,30 @@ def cloud_credential(self, name, harvester_name, *, convert=True, **properties): harvester_credential_config=harvester_credential_config, convert=convert, **properties) - def machine_config(self, rke2_cluster, image, network): + def machine_config(self, rke_cluster_name, network_id, image_id, ssh_user): hcl_str = TF_MACHINE_CONFIG % { - "name": rke2_cluster["name"], + "name": rke_cluster_name, "harvester_config": TF_HARVESTER_CONFIG % { - "ssh_user": image["ssh_user"], - "disk_info": TF_DISK_INFO % {"image_name": image["id"]}, - "network_info": TF_NETWORK_INFO % {"network_name": network["id"]}, + "ssh_user": ssh_user, + "disk_info": TF_DISK_INFO % {"image_name": image_id}, + "network_info": TF_NETWORK_INFO % {"network_name": network_id}, "user_data": TF_USER_DATA } } + return ResourceContext("rancher2_machine_config_v2", rke_cluster_name, hcl_str, "") - return ResourceContext("rancher2_machine_config_v2", rke2_cluster["name"], hcl_str, "") - - def cluster_config(self, rke2_cluster, harvester, cloud_credential): + def cluster_config(self, rke_cluster_name, k8s_version, harvester_name, cloud_credential_name): machine_pools = TF_MACHINE_POOLS % { - "cloud_credential_name": cloud_credential["name"], - "machine_config_name": rke2_cluster["name"] + "cloud_credential_name": cloud_credential_name, + "machine_config_name": rke_cluster_name } rke_config = TF_RKE_CONFIG % { "machine_pools": machine_pools, - "harvester_name": harvester["name"] + "harvester_name": harvester_name } hcl_str = TF_CLUSTER_CONFIG % { - "name": rke2_cluster["name"], - "rke2_version": rke2_cluster["k8s_version"], + "name": rke_cluster_name, + "rke2_version": k8s_version, "rke_config": rke_config } - - return ResourceContext("rancher2_cluster_v2", rke2_cluster["name"], hcl_str, "") + return ResourceContext("rancher2_cluster_v2", rke_cluster_name, hcl_str, "") diff --git a/harvester_e2e_tests/integration/test_z_terraform_rancher.py b/harvester_e2e_tests/integration/test_z_terraform_rancher.py index 370759ece..ef6220a7e 100644 --- a/harvester_e2e_tests/integration/test_z_terraform_rancher.py +++ b/harvester_e2e_tests/integration/test_z_terraform_rancher.py @@ -34,8 +34,8 @@ def ubuntu_image(api_client, unique_name, image_ubuntu, wait_timeout): name = data['metadata']['name'] yield { - "ssh_user": "ubuntu", - "id": f"{namespace}/{name}" + "id": f"{namespace}/{name}", + "ssh_user": "ubuntu" } api_client.images.delete(name, namespace) @@ -58,12 +58,14 @@ def vlan_network(request, api_client): f"Failed to create network-attachment-definition {network_name}\n" f"rc: {code}, data:\n{data}" ) + namespace = data['metadata']['namespace'] + name = data['metadata']['name'] yield { - "id": f"default/{data['metadata']['name']}" + "id": f"{namespace}/{name}" } - api_client.networks.delete(network_name) + api_client.networks.delete(network_name, namespace) @pytest.fixture(scope='module') @@ -85,14 +87,16 @@ def harvester(api_client, rancher_api_client, unique_name, wait_timeout): f"Fail to get MgmtCluster with clusterName {name}\n" f"rc: {rc}, data:\n{data}" ) + namespace = data['metadata']['namespace'] yield { "name": name, + "namespace": namespace, "id": data['status']['clusterName'], "kubeconfig": api_client.generate_kubeconfig() } - rancher_api_client.mgmt_clusters.delete(name) + rancher_api_client.mgmt_clusters.delete(name, namespace) updates = dict(value="") api_client.settings.update("cluster-registration-url", updates) @@ -112,16 +116,31 @@ def rancher(rancher_api_client): def rke2_cluster(unique_name, k8s_version): return { "name": f"rke2-{unique_name}", - "id": "", + "id": "", # set in test_create_rke2_cluster "k8s_version": k8s_version } @pytest.fixture(scope="module") -def cloud_credential(unique_name): - return { - "name": f"cc-{unique_name}" - } +def cloud_credential_resource(unique_name, tf_resource, harvester): + return tf_resource.cloud_credential( + f"cc-{unique_name}", harvester["name"] + ) + + +@pytest.fixture(scope="module") +def machine_config_resource(tf_resource, rke2_cluster, vlan_network, ubuntu_image): + return tf_resource.machine_config( + rke2_cluster["name"], vlan_network["id"], ubuntu_image["id"], ubuntu_image["ssh_user"] + ) + + +@pytest.fixture(scope="module") +def cluster_config_resource(tf_resource, rke2_cluster, harvester, cloud_credential_resource): + return tf_resource.cluster_config( + rke2_cluster["name"], rke2_cluster["k8s_version"], harvester["name"], + cloud_credential_resource.name + ) @pytest.mark.p0 @@ -167,11 +186,9 @@ def test_import_harvester(api_client, rancher_api_client, harvester, wait_timeou @pytest.mark.terraform @pytest.mark.rancher @pytest.mark.dependency(name="create_cloud_credential", depends=["import_harvester"]) -def test_create_cloud_credential(rancher_api_client, tf_resource, tf_rancher, - harvester, cloud_credential): - spec = tf_resource.cloud_credential(cloud_credential["name"], harvester["name"]) +def test_create_cloud_credential(rancher_api_client, tf_rancher, cloud_credential_resource): + spec = cloud_credential_resource tf_rancher.save_as(spec.ctx, "cloud_credential") - out, err, code = tf_rancher.apply_resource(spec.type, spec.name) assert not err and 0 == code @@ -185,10 +202,9 @@ def test_create_cloud_credential(rancher_api_client, tf_resource, tf_rancher, @pytest.mark.terraform @pytest.mark.rancher @pytest.mark.dependency(name="create_machine_config", depends=["create_cloud_credential"]) -def test_create_machine_config(tf_resource, tf_rancher, rke2_cluster, ubuntu_image, vlan_network): - spec = tf_resource.machine_config(rke2_cluster, ubuntu_image, vlan_network) +def test_create_machine_config(tf_rancher, machine_config_resource): + spec = machine_config_resource tf_rancher.save_as(spec.ctx, "machine_config") - out, err, code = tf_rancher.apply_resource(spec.type, spec.name) assert not err and 0 == code @@ -197,11 +213,10 @@ def test_create_machine_config(tf_resource, tf_rancher, rke2_cluster, ubuntu_ima @pytest.mark.terraform @pytest.mark.rancher @pytest.mark.dependency(name="create_rke2_cluster", depends=["create_machine_config"]) -def test_create_rke2_cluster(tf_resource, tf_rancher, rke2_cluster, rancher_api_client, - harvester, cloud_credential): - spec = tf_resource.cluster_config(rke2_cluster, harvester, cloud_credential) +def test_create_rke2_cluster(tf_rancher, rke2_cluster, rancher_api_client, + cluster_config_resource): + spec = cluster_config_resource tf_rancher.save_as(spec.ctx, "rke2_cluster") - out, err, code = tf_rancher.apply_resource(spec.type, spec.name) assert not err and 0 == code @@ -225,10 +240,9 @@ def test_create_rke2_cluster(tf_resource, tf_rancher, rke2_cluster, rancher_api_ @pytest.mark.terraform @pytest.mark.rancher @pytest.mark.dependency(name="delete_rke2_cluster", depends=["create_rke2_cluster"]) -def test_delete_rke2_cluster(tf_resource, tf_rancher, rke2_cluster, rancher_api_client, - harvester, cloud_credential): - spec = tf_resource.cluster_config(rke2_cluster, harvester, cloud_credential) - +def test_delete_rke2_cluster(tf_rancher, rke2_cluster, rancher_api_client, + cluster_config_resource): + spec = cluster_config_resource out, err, code = tf_rancher.destroy_resource(spec.type, spec.name) assert not err and 0 == code @@ -240,9 +254,8 @@ def test_delete_rke2_cluster(tf_resource, tf_rancher, rke2_cluster, rancher_api_ @pytest.mark.terraform @pytest.mark.rancher @pytest.mark.dependency(name="delete_machine_config", depends=["create_machine_config"]) -def test_delete_machine_config(tf_resource, tf_rancher, rke2_cluster, ubuntu_image, vlan_network): - spec = tf_resource.machine_config(rke2_cluster, ubuntu_image, vlan_network) - +def test_delete_machine_config(tf_rancher, machine_config_resource): + spec = machine_config_resource out, err, code = tf_rancher.destroy_resource(spec.type, spec.name) assert not err and 0 == code @@ -251,9 +264,7 @@ def test_delete_machine_config(tf_resource, tf_rancher, rke2_cluster, ubuntu_ima @pytest.mark.terraform @pytest.mark.rancher @pytest.mark.dependency(name="delete_cloud_credential", depends=["create_cloud_credential"]) -def test_delete_cloud_credential(rancher_api_client, tf_resource, tf_rancher, - harvester, cloud_credential): - spec = tf_resource.cloud_credential(cloud_credential["name"], harvester["name"]) - +def test_delete_cloud_credential(tf_rancher, cloud_credential_resource): + spec = cloud_credential_resource out, err, code = tf_rancher.destroy_resource(spec.type, spec.name) assert not err and 0 == code