def kube_api_test_prepare_late_binding_infraenv(
        self, kube_api_context: KubeAPIContext, nodes: Nodes, infraenv_config: InfraEnvConfig
    ):
        api_client = kube_api_context.api_client
        spoke_namespace = kube_api_context.spoke_namespace
        infraenv_name = infraenv_config.entity_name.get()
        infraenv_config.iso_download_path = utils.get_iso_download_path(infraenv_name)
        nodes.prepare_nodes()

        spoke_namespace = spoke_namespace
        secret = Secret(api_client, f"{infraenv_name}-secret", spoke_namespace)
        secret.create(pull_secret=infraenv_config.pull_secret)

        ignition_config_override = None

        infra_env = InfraEnv(api_client, f"{infraenv_name}-infra-env", spoke_namespace)
        infra_env.create(
            cluster_deployment=None,
            ignition_config_override=ignition_config_override,
            secret=secret,
            proxy=None,
            ssh_pub_key=infraenv_config.ssh_public_key,
        )

        agents = self.start_nodes(nodes, infra_env, infraenv_config, infraenv_config.is_static_ip)

        log.info("Waiting for agent status verification")
        Agent.wait_for_agents_to_be_ready_for_install(agents)

        return infra_env
示例#2
0
    def start_nodes(cls, nodes: Nodes, infra_env: InfraEnv, entity_config: BaseEntityConfig) -> List[Agent]:
        infra_env.status()  # wait until install-env will have status (i.e until resource will be processed).
        cls.download_iso_from_infra_env(infra_env, entity_config.iso_download_path)

        log.info("iso downloaded, starting nodes")
        nodes.controller.log_configuration()
        log.info(f"Entity configuration {entity_config}")

        nodes.start_all(check_ips=not (entity_config.is_static_ip and entity_config.is_ipv6))

        log.info("waiting for host agent")
        agents = infra_env.wait_for_agents(len(nodes))
        node_list = nodes.controller.list_nodes()
        for agent in agents:
            agent.approve()
            cls._set_host_name_from_node(node_list, agent, entity_config.is_ipv4)

        return agents
 def download_iso_from_infra_env(cls, infra_env: InfraEnv,
                                 iso_download_path: str):
     log.info("getting iso download url")
     iso_download_url = infra_env.get_iso_download_url()
     log.info("downloading iso from url=%s", iso_download_url)
     utils.download_file(iso_download_url,
                         iso_download_path,
                         verify_ssl=False)
     assert os.path.isfile(iso_download_path)
def delete_kube_api_resources_for_namespace(
    kube_api_client,
    name,
    namespace,
    *,
    secret_name=None,
    infraenv_name=None,
    nmstate_name=None,
    image_set_name=None,
):
    CoreV1Api.delete_namespaced_secret = suppress_not_found_error(
        fn=CoreV1Api.delete_namespaced_secret,
    )
    CustomObjectsApi.delete_namespaced_custom_object = suppress_not_found_error(
        fn=CustomObjectsApi.delete_namespaced_custom_object
    )

    cluster_deployment = ClusterDeployment(
        kube_api_client=kube_api_client,
        name=name,
        namespace=namespace,
    )

    for agent in cluster_deployment.list_agents():
        agent.delete()

    cluster_deployment.delete()

    Secret(
        kube_api_client=kube_api_client,
        name=secret_name or name,
        namespace=namespace,
    ).delete()

    InfraEnv(
        kube_api_client=kube_api_client,
        name=infraenv_name or f"{name}-infra-env",
        namespace=namespace,
    ).delete()

    NMStateConfig(
        kube_api_client=kube_api_client,
        name=nmstate_name or f"{name}-nmstate-config",
        namespace=namespace,
    ).delete()

    ClusterImageSet(
        kube_api_client=kube_api_client, name=image_set_name or f"{name}-image-set", namespace=namespace
    ).delete()
def kube_api_test_prepare_late_binding_infraenv(
        kube_api_context,
        nodes: Nodes,
        infraenv_config: InfraEnvConfig,
        *,
        is_ipv4=True):
    infraenv_name = infraenv_config.entity_name.get()

    secret = Secret(
        kube_api_client=kube_api_context.api_client,
        name=f"{infraenv_name}-secret",
        namespace=global_variables.spoke_namespace,
    )
    secret.create(pull_secret=infraenv_config.pull_secret)

    ignition_config_override = None

    infra_env = InfraEnv(
        kube_api_client=kube_api_context.api_client,
        name=f"{infraenv_name}-infra-env",
        namespace=global_variables.spoke_namespace,
    )
    infra_env.create(
        cluster_deployment=None,
        ignition_config_override=ignition_config_override,
        secret=secret,
        proxy=None,
        ssh_pub_key=infraenv_config.ssh_public_key,
    )

    infra_env.status()

    download_iso_from_infra_env(infra_env, infraenv_config.iso_download_path)

    log.info("iso downloaded, starting nodes")
    nodes.start_all()

    log.info("waiting for host agent")
    agents = infra_env.wait_for_agents(len(nodes))
    for agent in agents:
        agent.approve()
        set_agent_hostname(nodes[0], agent,
                           is_ipv4)  # Currently only supports single node

    log.info("Waiting for agent status verification")
    Agent.wait_for_agents_to_be_ready_for_install(agents)

    return infra_env
    def kube_api_test(
        self,
        kube_api_context: KubeAPIContext,
        nodes: Nodes,
        cluster_config: ClusterConfig,
        prepared_controller_configuration: BaseNodeConfig,
        infra_env_configuration: BaseInfraEnvConfig,
        proxy_server: Optional[Callable] = None,
        *,
        is_disconnected: bool = False,
    ):
        cluster_name = cluster_config.cluster_name.get()
        api_client = kube_api_context.api_client
        spoke_namespace = kube_api_context.spoke_namespace

        # TODO resolve it from the service if the node controller doesn't have this information
        #  (please see cluster.get_primary_machine_cidr())

        agent_cluster_install = AgentClusterInstall(
            api_client, f"{cluster_name}-agent-cluster-install", spoke_namespace
        )

        secret = Secret(api_client, f"{cluster_name}-secret", spoke_namespace)
        secret.create(pull_secret=cluster_config.pull_secret)

        cluster_deployment = ClusterDeployment(api_client, cluster_name, spoke_namespace)
        cluster_deployment.create(agent_cluster_install_ref=agent_cluster_install.ref, secret=secret)
        proxy = self.setup_proxy(nodes, cluster_config, proxy_server)

        if is_disconnected:
            log.info("getting ignition and install config override for disconnected install")
            ca_bundle = self.get_ca_bundle_from_hub(spoke_namespace)
            self.patch_install_config_with_ca_bundle(cluster_deployment, ca_bundle)
            ignition_config_override = self.get_ignition_config_override(ca_bundle)
        else:
            ignition_config_override = None

        infra_env = InfraEnv(api_client, f"{cluster_name}-infra-env", spoke_namespace)
        infraenv = infra_env.create(
            cluster_deployment, secret, proxy, ignition_config_override, ssh_pub_key=cluster_config.ssh_public_key
        )
        cluster_config.iso_download_path = utils.get_iso_download_path(infraenv.get("metadata", {}).get("name"))
        nodes.prepare_nodes()

        agent_cluster_install.create(
            cluster_deployment_ref=cluster_deployment.ref,
            image_set_ref=self.deploy_image_set(cluster_name, api_client),
            cluster_cidr=cluster_config.cluster_networks[0].cidr,
            host_prefix=cluster_config.cluster_networks[0].host_prefix,
            service_network=cluster_config.service_networks[0].cidr,
            ssh_pub_key=cluster_config.ssh_public_key,
            hyperthreading=cluster_config.hyperthreading,
            control_plane_agents=nodes.masters_count,
            worker_agents=nodes.workers_count,
            proxy=proxy.as_dict() if proxy else {},
        )

        agent_cluster_install.wait_to_be_ready(ready=False)

        if infra_env_configuration.is_static_ip:
            self.apply_static_network_config(kube_api_context, nodes, cluster_name)

        agents = self.start_nodes(nodes, infra_env, cluster_config, infra_env_configuration.is_static_ip)

        if len(nodes) == 1:
            # for single node set the cidr and take the actual ip from the host
            # the vips is the ip of the host
            self._set_agent_cluster_install_machine_cidr(agent_cluster_install, nodes)
            # wait till the ip is set for the node and read it from its inventory
            self.set_single_node_ip(cluster_deployment, nodes)
            api_vip = ingress_vip = get_ip_for_single_node(cluster_deployment, nodes.is_ipv4)
        else:
            # for multi node allocate 2 address at a safe distance from the beginning
            # of the available address block to allow enough addresses for workers
            access_vips = nodes.controller.get_ingress_and_api_vips()
            api_vip = access_vips["api_vip"]
            ingress_vip = access_vips["ingress_vip"]
            # patch the aci with the vips. The cidr will be derived from the range
            agent_cluster_install.set_api_vip(api_vip)
            agent_cluster_install.set_ingress_vip(ingress_vip)

        nodes.controller.set_dns(api_ip=api_vip, ingress_ip=ingress_vip)

        log.info("Waiting for install")
        self._wait_for_install(agent_cluster_install, agents)
    def capi_test(
        self,
        kube_api_context: KubeAPIContext,
        nodes: Nodes,
        cluster_config: ClusterConfig,
        is_static_ip: bool,
        proxy_server: Optional[Callable] = None,
        *,
        is_disconnected: bool = False,
    ):
        cluster_name = cluster_config.cluster_name.get()
        api_client = kube_api_context.api_client
        spoke_namespace = kube_api_context.spoke_namespace
        cluster_config.iso_download_path = utils.get_iso_download_path(cluster_name)
        nodes.prepare_nodes()

        secret = Secret(api_client, f"{cluster_name}-secret", spoke_namespace)
        secret.create(pull_secret=cluster_config.pull_secret)

        if is_disconnected:
            log.info("getting igntion and install config override for disconected install")
            ca_bundle = self.get_ca_bundle_from_hub(spoke_namespace)
            ignition_config_override = self.get_ignition_config_override(ca_bundle)
        else:
            ignition_config_override = None

        proxy = self.setup_proxy(nodes, cluster_config, proxy_server)

        infra_env = InfraEnv(api_client, f"{cluster_name}-infra-env", spoke_namespace)
        infra_env.create(
            cluster_deployment=None,
            ignition_config_override=ignition_config_override,
            secret=secret,
            proxy=proxy,
            ssh_pub_key=cluster_config.ssh_public_key,
        )
        self.start_nodes(nodes, infra_env, cluster_config, is_static_ip)
        hypershift = HyperShift(name=cluster_name, kube_api_client=api_client)

        with utils.pull_secret_file() as ps:
            with tempfile.NamedTemporaryFile(mode="w") as f:
                f.write(cluster_config.ssh_public_key)
                f.flush()
                ssh_public_key_file = f.name
                hypershift.create(
                    pull_secret_file=ps,
                    agent_namespace=spoke_namespace,
                    provider_image=os.environ.get("PROVIDER_IMAGE", ""),
                    hypershift_cpo_image=os.environ.get("HYPERSHIFT_IMAGE", ""),
                    release_image=os.environ.get("OPENSHIFT_INSTALL_RELEASE_IMAGE", ""),
                    ssh_key=ssh_public_key_file,
                )

        hypershift.wait_for_control_plane_ready()
        # WORKAROUND for ovn on minikube
        secret = Secret(api_client, "ovn-master-metrics-cert", hypershift.namespace)
        secret.create_with_data(secret_data={"ca_cert": "dummy data, we only need this secret to exists"})

        cluster_deployment = ClusterDeployment(api_client, cluster_name, f"clusters-{cluster_name}")

        def _cluster_deployment_installed() -> bool:
            return cluster_deployment.get().get("spec", {}).get("installed")

        waiting.wait(
            _cluster_deployment_installed,
            sleep_seconds=1,
            timeout_seconds=60,
            waiting_for="clusterDeployment to get created",
            expected_exceptions=Exception,
        )
        hypershift.wait_for_control_plane_ready()
        self.set_node_count_and_wait_for_ready_nodes(cluster_deployment, hypershift, spoke_namespace, node_count=1)
        self.set_node_count_and_wait_for_ready_nodes(cluster_deployment, hypershift, spoke_namespace, node_count=2)
        self.scale_down_nodepool_and_wait_for_unbounded_agent(
            cluster_deployment, hypershift, spoke_namespace, node_count=1
        )
示例#8
0
def kube_api_test(
    kube_api_context,
    nodes: Nodes,
    cluster_config: ClusterConfig,
    proxy_server=None,
    *,
    is_ipv4=True,
    is_disconnected=False,
):
    cluster_name = cluster_config.cluster_name.get()

    # TODO resolve it from the service if the node controller doesn't have this information
    #  (please see cluster.get_primary_machine_cidr())
    machine_cidr = nodes.controller.get_primary_machine_cidr()

    agent_cluster_install = AgentClusterInstall(
        kube_api_client=kube_api_context.api_client,
        name=f"{cluster_name}-agent-cluster-install",
        namespace=global_variables.spoke_namespace,
    )

    secret = Secret(
        kube_api_client=kube_api_context.api_client,
        name=f"{cluster_name}-secret",
        namespace=global_variables.spoke_namespace,
    )
    secret.create(pull_secret=cluster_config.pull_secret)

    cluster_deployment = ClusterDeployment(
        kube_api_client=kube_api_context.api_client,
        name=cluster_name,
        namespace=global_variables.spoke_namespace,
    )
    cluster_deployment.create(
        agent_cluster_install_ref=agent_cluster_install.ref,
        secret=secret,
    )

    agent_cluster_install.create(
        cluster_deployment_ref=cluster_deployment.ref,
        image_set_ref=deploy_image_set(cluster_name, kube_api_context),
        cluster_cidr=cluster_config.cluster_networks[0].cidr,
        host_prefix=cluster_config.cluster_networks[0].host_prefix,
        service_network=cluster_config.service_networks[0].cidr,
        ssh_pub_key=cluster_config.ssh_public_key,
        hyperthreading=cluster_config.hyperthreading,
        control_plane_agents=nodes.controller.params.master_count,
        worker_agents=nodes.controller.params.worker_count,
        machine_cidr=machine_cidr,
    )
    agent_cluster_install.wait_to_be_ready(False)

    if is_disconnected:
        log.info("getting igntion and install config override for disconected install")
        ca_bundle = get_ca_bundle_from_hub()
        patch_install_config_with_ca_bundle(cluster_deployment, ca_bundle)
        ignition_config_override = get_ignition_config_override(ca_bundle)
    else:
        ignition_config_override = None

    proxy = setup_proxy(cluster_config, machine_cidr, cluster_name, proxy_server)

    infra_env = InfraEnv(
        kube_api_client=kube_api_context.api_client,
        name=f"{cluster_name}-infra-env",
        namespace=global_variables.spoke_namespace,
    )
    infra_env.create(
        cluster_deployment=cluster_deployment,
        ignition_config_override=ignition_config_override,
        secret=secret,
        proxy=proxy,
        ssh_pub_key=cluster_config.ssh_public_key,
    )
    infra_env.status()
    download_iso_from_infra_env(infra_env, cluster_config.iso_download_path)

    log.info("iso downloaded, starting nodes")
    nodes.start_all()

    log.info("waiting for host agent")
    agents = cluster_deployment.wait_for_agents(len(nodes))
    for agent in agents:
        agent.approve()
        set_agent_hostname(nodes[0], agent, is_ipv4)  # Currently only supports single node

    if len(nodes) == 1:
        set_single_node_ip(cluster_deployment, nodes, is_ipv4)

    log.info("Waiting for agent status verification")
    Agent.wait_for_agents_to_install(agents)

    agent_cluster_install.wait_to_be_ready(True)

    log.info("waiting for agent-cluster-install to be in installing state")
    agent_cluster_install.wait_to_be_installing()

    try:
        log.info("installation started, waiting for completion")
        agent_cluster_install.wait_to_be_installed()
        log.info("installation completed successfully")
    except Exception:
        log.exception("Failure during kube-api installation flow:")
        collect_debug_info_from_cluster(cluster_deployment, agent_cluster_install)
示例#9
0
def capi_test(
    kube_api_context,
    nodes: Nodes,
    cluster_config: ClusterConfig,
    proxy_server=None,
    *,
    is_ipv4=True,
    is_disconnected=False,
):
    cluster_name = cluster_config.cluster_name.get()
    cluster_config
    # TODO resolve it from the service if the node controller doesn't have this information
    #  (please see cluster.get_primary_machine_cidr())
    machine_cidr = nodes.controller.get_primary_machine_cidr()

    secret = Secret(
        kube_api_client=kube_api_context.api_client,
        name=f"{cluster_name}-secret",
        namespace=global_variables.spoke_namespace,
    )
    secret.create(pull_secret=cluster_config.pull_secret)

    if is_disconnected:
        log.info("getting igntion and install config override for disconected install")
        ca_bundle = get_ca_bundle_from_hub()
        ignition_config_override = get_ignition_config_override(ca_bundle)
    else:
        ignition_config_override = None

    proxy = setup_proxy(cluster_config, machine_cidr, cluster_name, proxy_server)

    infra_env = InfraEnv(
        kube_api_client=kube_api_context.api_client,
        name=f"{cluster_name}-infra-env",
        namespace=global_variables.spoke_namespace,
    )
    infra_env.create(
        cluster_deployment=None,
        ignition_config_override=ignition_config_override,
        secret=secret,
        proxy=proxy,
        ssh_pub_key=cluster_config.ssh_public_key,
    )
    infra_env.status()
    download_iso_from_infra_env(infra_env, cluster_config.iso_download_path)

    log.info("iso downloaded, starting nodes")
    nodes.start_all()

    log.info("waiting for host agent")
    agents = infra_env.wait_for_agents(len(nodes))
    for agent in agents:
        agent.approve()
        set_agent_hostname(nodes[0], agent, is_ipv4)

    hypershift = HyperShift(name=cluster_name)

    with utils.pull_secret_file() as ps:
        with tempfile.NamedTemporaryFile(mode="w") as f:
            f.write(cluster_config.ssh_public_key)
            f.flush()
            ssh_public_key_file = f.name
            hypershift.create(pull_secret_file=ps, ssh_key=ssh_public_key_file)

    cluster_deployment = ClusterDeployment(
        kube_api_client=kube_api_context.api_client, name=cluster_name, namespace=f"clusters-{cluster_name}"
    )

    def _cluster_deployment_installed() -> bool:
        return cluster_deployment.get().get("spec", {}).get("installed")

    waiting.wait(
        _cluster_deployment_installed,
        sleep_seconds=1,
        timeout_seconds=60,
        waiting_for="clusterDeployment to get created",
        expected_exceptions=Exception,
    )
    set_node_count_and_wait_for_ready_nodes(cluster_deployment, hypershift, kube_api_context, 1)
    set_node_count_and_wait_for_ready_nodes(cluster_deployment, hypershift, kube_api_context, 2)
def execute_kube_api_flow():
    log.info("Executing kube-api flow")
    cluster_name = f'{args.cluster_name or consts.CLUSTER_PREFIX}-{args.namespace}'
    utils.recreate_folder(consts.IMAGE_FOLDER, force_recreate=False)
    machine_net = MachineNetwork(args.ipv4, args.ipv6, args.vm_network_cidr, args.vm_network_cidr6, args.ns_index)
    kube_client = create_kube_api_client()
    cluster_deployment = ClusterDeployment(
        kube_api_client=kube_client,
        name=cluster_name,
        namespace=args.namespace
    )
    set_tf_config(cluster_name)

    secret = Secret(
        kube_api_client=kube_client,
        name=cluster_name,
        namespace=args.namespace,
    )
    secret.apply(pull_secret=args.pull_secret)

    imageSet=ClusterImageSet(
        kube_api_client=kube_client,
        name=f"{cluster_name}-image-set",
        namespace=args.namespace
    )
    releaseImage = utils.get_openshift_release_image()
    imageSet.apply(releaseImage=releaseImage)

    ipv4 = args.ipv4 and args.ipv4.lower() in MachineNetwork.YES_VALUES
    ipv6 = args.ipv6 and args.ipv6.lower() in MachineNetwork.YES_VALUES
    api_vip, ingress_vip = "", ""
    if args.master_count > 1:
        api_vip, ingress_vip = _get_vips_ips(machine_net)

    agent_cluster_install = AgentClusterInstall(
        kube_api_client=kube_client,
        name=f'{cluster_name}-agent-cluster-install',
        namespace=args.namespace
    )

    image_set_ref = ClusterImageSetReference(name=f'{cluster_name}-image-set')
    cluster_deployment.apply(
        secret=secret,
        base_domain=args.base_dns_domain,
        agent_cluster_install_ref=agent_cluster_install.ref,
    )

    agent_cluster_install.apply(
        cluster_deployment_ref=cluster_deployment.ref,
        api_vip=api_vip,
        ingress_vip=ingress_vip,
        image_set_ref=image_set_ref,
        cluster_cidr=args.cluster_network if ipv4 else args.cluster_network6,
        host_prefix=args.host_prefix if ipv4 else args.host_prefix6,
        service_network=args.service_network if ipv4 else args.service_network6,
        ssh_pub_key=args.ssh_key,
        control_plane_agents=args.master_count,
        worker_agents=args.number_of_workers,
        machine_cidr=get_machine_cidr_from_machine_net(machine_net),
        hyperthreading=args.hyperthreading,
    )
    agent_cluster_install.wait_to_be_ready(False)

    apply_static_network_config(
        cluster_name=cluster_name,
        kube_client=kube_client,
    )

    image_path = os.path.join(
        consts.IMAGE_FOLDER,
        f'{args.namespace}-installer-image.iso'
    )

    log.info("Creating infraEnv")
    http_proxy, https_proxy, no_proxy = _get_http_proxy_params(ipv4=ipv4, ipv6=ipv6)
    infra_env = InfraEnv(
        kube_api_client=kube_client,
        name=f"{cluster_name}-infra-env",
        namespace=args.namespace
    )
    infra_env.apply(
        cluster_deployment=cluster_deployment,
        secret=secret,
        proxy=Proxy(
            http_proxy=http_proxy,
            https_proxy=https_proxy,
            no_proxy=no_proxy
        ),
        ssh_pub_key=args.ssh_key,
        nmstate_label=cluster_name,
    )
    infra_env.status()
    image_url = infra_env.get_iso_download_url()
    utils.download_iso(image_url, image_path)
    try:
        nodes_flow_kube_api(cluster_name, machine_net, cluster_deployment, agent_cluster_install)
    finally:
        if not image_path or args.keep_iso:
            return
        log.info('deleting iso: %s', image_path)
        os.unlink(image_path)
    def capi_test(
        self,
        kube_api_context: KubeAPIContext,
        nodes: Nodes,
        cluster_config: ClusterConfig,
        proxy_server: Optional[Callable] = None,
        *,
        is_disconnected: bool = False,
    ):
        cluster_name = cluster_config.cluster_name.get()
        api_client = kube_api_context.api_client
        spoke_namespace = kube_api_context.spoke_namespace

        secret = Secret(api_client, f"{cluster_name}-secret", spoke_namespace)
        secret.create(pull_secret=cluster_config.pull_secret)

        if is_disconnected:
            log.info("getting igntion and install config override for disconected install")
            ca_bundle = self.get_ca_bundle_from_hub(spoke_namespace)
            ignition_config_override = self.get_ignition_config_override(ca_bundle)
        else:
            ignition_config_override = None

        proxy = self.setup_proxy(nodes, cluster_config, proxy_server)

        infra_env = InfraEnv(api_client, f"{cluster_name}-infra-env", spoke_namespace)
        infra_env.create(
            cluster_deployment=None,
            ignition_config_override=ignition_config_override,
            secret=secret,
            proxy=proxy,
            ssh_pub_key=cluster_config.ssh_public_key,
        )
        self.start_nodes(nodes, infra_env, cluster_config)
        hypershift = HyperShift(name=cluster_name, kube_api_client=api_client)

        with utils.pull_secret_file() as ps:
            with tempfile.NamedTemporaryFile(mode="w") as f:
                f.write(cluster_config.ssh_public_key)
                f.flush()
                ssh_public_key_file = f.name
                hypershift.create(
                    pull_secret_file=ps,
                    agent_namespace=spoke_namespace,
                    provider_image=os.environ.get("PROVIDER_IMAGE", ""),
                    hypershift_cpo_image=os.environ.get("HYPERSHIFT_IMAGE", ""),
                    ssh_key=ssh_public_key_file,
                )

        hypershift.wait_for_control_plane_ready()

        cluster_deployment = ClusterDeployment(api_client, cluster_name, f"clusters-{cluster_name}")

        def _cluster_deployment_installed() -> bool:
            return cluster_deployment.get().get("spec", {}).get("installed")

        waiting.wait(
            _cluster_deployment_installed,
            sleep_seconds=1,
            timeout_seconds=60,
            waiting_for="clusterDeployment to get created",
            expected_exceptions=Exception,
        )
        hypershift.wait_for_control_plane_ready()
        self.set_node_count_and_wait_for_ready_nodes(cluster_deployment, hypershift, spoke_namespace, node_count=1)
        self.set_node_count_and_wait_for_ready_nodes(cluster_deployment, hypershift, spoke_namespace, node_count=2)