diff --git a/plugins/modules/lke_cluster.py b/plugins/modules/lke_cluster.py index d40164fa..0f7c6ea7 100644 --- a/plugins/modules/lke_cluster.py +++ b/plugins/modules/lke_cluster.py @@ -369,6 +369,18 @@ def _get_cluster_by_name(self, name: str) -> Optional[LKECluster]: msg="failed to get lke cluster {0}: {1}".format(name, exception) ) + def _get_node_pools(self, tier: str, params: dict) -> Optional[List[dict]]: + nodepools = [] + if "node_pools" in params: + nodepools = params.pop("node_pools") + + if not nodepools and (not tier or tier == "standard"): + # throw error if no node pools specified for standard clusters + self.fail( + msg="At least one node pool must be specified when creating a standard LKE cluster." + ) + return nodepools + def _wait_for_all_nodes_ready( self, cluster: LKECluster, timeout: int ) -> None: @@ -417,11 +429,13 @@ def _create_cluster(self) -> Optional[LKECluster]: self.register_action("Created LKE cluster {0}".format(label)) # This is necessary to use fields not yet supported by linode_api4 + nodepools = self._get_node_pools(tier, params) + result = self.client.lke.cluster_create( - params.pop("region"), - label, - params.pop("node_pools"), - params.pop("k8s_version"), + region=params.pop("region"), + label=label, + node_pools=nodepools, + kube_version=params.pop("k8s_version"), **params, ) @@ -514,8 +528,7 @@ def _update_cluster(self, cluster: LKECluster) -> None: copy.deepcopy(self.module.params) ) new_params = {k: v for k, v in new_params.items() if k in CREATE_FIELDS} - - pools = new_params.pop("node_pools") + pools = self._get_node_pools(cluster.tier, new_params) # This is handled separately new_params.pop("k8s_version") @@ -803,7 +816,9 @@ def _populate_results(self, cluster: LKECluster) -> None: return self._populate_kubeconfig_poll(cluster) - self._populate_dashboard_url_poll(cluster) + # enterprise clusters don't have dashboards. + if cluster.tier != "enterprise": + self._populate_dashboard_url_poll(cluster) def _handle_present(self) -> None: params = self.module.params diff --git a/tests/integration/targets/lke_cluster_enterprise_no_pools/tasks/main.yaml b/tests/integration/targets/lke_cluster_enterprise_no_pools/tasks/main.yaml new file mode 100644 index 00000000..fbde6d11 --- /dev/null +++ b/tests/integration/targets/lke_cluster_enterprise_no_pools/tasks/main.yaml @@ -0,0 +1,61 @@ +- name: lke_cluster_enterprise_no_pools + block: + - set_fact: + r: "{{ 1000000000 | random }}" + + - name: Resolve an enterprise K8s version + linode.cloud.lke_version_list: + api_version: v4beta + tier: "enterprise" + register: get_lke_versions_enterprise + + - set_fact: + lke_versions: '{{ get_lke_versions_enterprise.lke_versions|sort(attribute="id", reverse=True) }}' + + - set_fact: + kube_version: '{{ lke_versions[0].id }}' + + - name: List regions that support LKE Enterprise + linode.cloud.region_list: + register: all_regions + + - set_fact: + lke_e_region: >- + {{ all_regions.regions + | selectattr("site_type", "equalto", "core") + | selectattr("capabilities", "search", "Kubernetes Enterprise") + | map(attribute="id") + | first }} + + - name: Create a Linode LKE Enterprise cluster without node pools + linode.cloud.lke_cluster: + api_version: v4beta + tier: 'enterprise' + label: 'ansible-test-{{ r }}' + region: '{{ lke_e_region }}' + k8s_version: '{{ kube_version }}' + skip_polling: true + state: present + register: create_enterprise_cluster + + - name: Assert LKE cluster is created + assert: + that: + - create_enterprise_cluster.cluster.k8s_version == kube_version + - create_enterprise_cluster.cluster.region == lke_e_region + - create_enterprise_cluster.cluster.tier == 'enterprise' + + always: + - ignore_errors: yes + block: + - name: Delete the LKE cluster + linode.cloud.lke_cluster: + label: '{{ create_enterprise_cluster.cluster.label }}' + state: absent + + environment: + LINODE_UA_PREFIX: '{{ ua_prefix }}' + LINODE_API_TOKEN: '{{ api_token }}' + LINODE_API_URL: '{{ api_url }}' + LINODE_API_VERSION: '{{ api_version }}' + LINODE_CA: '{{ ca_file or "" }}' diff --git a/tests/integration/targets/lke_cluster_standard_no_pools/tasks/main.yaml b/tests/integration/targets/lke_cluster_standard_no_pools/tasks/main.yaml new file mode 100644 index 00000000..2a4bd763 --- /dev/null +++ b/tests/integration/targets/lke_cluster_standard_no_pools/tasks/main.yaml @@ -0,0 +1,40 @@ +- name: lke_cluster_standard_no_pools + block: + - set_fact: + r: "{{ 1000000000 | random }}" + + - name: Resolve the latest K8s version + linode.cloud.lke_version_list: {} + register: get_lke_versions + + - set_fact: + lke_versions: '{{ get_lke_versions.lke_versions|sort(attribute="id", reverse=True) }}' + + - set_fact: + kube_version: '{{ lke_versions[0].id }}' + + - name: Create a Linode LKE cluster without node_pools (should fail) + linode.cloud.lke_cluster: + label: 'ansible-test-{{ r }}' + region: us-southeast + k8s_version: '{{ kube_version }}' + skip_polling: true + state: present + register: create_cluster + ignore_errors: yes + + - name: Verify that cluster creation failed as expected + assert: + that: + - create_cluster.changed == false + - "'At least one node pool must be specified when creating a standard LKE cluster.' in create_cluster.msg" + fail_msg: "Expected cluster creation to fail without node_pools, but got: {{ create_cluster }}" + success_msg: "Test passed: Cluster creation properly failed without node_pools" + + environment: + LINODE_UA_PREFIX: '{{ ua_prefix }}' + LINODE_API_TOKEN: '{{ api_token }}' + LINODE_API_URL: '{{ api_url }}' + LINODE_API_VERSION: '{{ api_version }}' + LINODE_CA: '{{ ca_file or "" }}' +