import json import unittest from copy import deepcopy import pytest import moto.server as server from moto import mock_aws, settings from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID from moto.eks.exceptions import ResourceInUseException, ResourceNotFoundException from moto.eks.models import ( CLUSTER_EXISTS_MSG, CLUSTER_IN_USE_MSG, CLUSTER_NOT_FOUND_MSG, NODEGROUP_EXISTS_MSG, NODEGROUP_NOT_FOUND_MSG, ) from moto.eks.responses import DEFAULT_MAX_RESULTS, DEFAULT_NEXT_TOKEN from tests.test_eks.test_eks import all_arn_values_should_be_valid from tests.test_eks.test_eks_constants import ( DEFAULT_ENCODING, DEFAULT_HTTP_HEADERS, NODEROLE_ARN_KEY, NODEROLE_ARN_VALUE, PARTITIONS, ROLE_ARN_KEY, ROLE_ARN_VALUE, SERVICE, SUBNETS_KEY, SUBNETS_VALUE, AddonAttributes, ClusterAttributes, Endpoints, FargateProfileAttributes, HttpHeaders, NodegroupAttributes, RegExTemplates, ResponseAttributes, StatusCodes, ) """ Test the different server responses """ NAME_LIST = ["foo", "bar", "baz", "qux"] DEFAULT_REGION = "us-east-1" class TestCluster: cluster_name = "example_cluster" data = {ClusterAttributes.NAME: cluster_name, ROLE_ARN_KEY: ROLE_ARN_VALUE} endpoint = Endpoints.CREATE_CLUSTER expected_arn_values = [ PARTITIONS, DEFAULT_REGION, ACCOUNT_ID, cluster_name, ] class TestNodegroup: cluster_name = TestCluster.cluster_name nodegroup_name = "example_nodegroup" data = { ClusterAttributes.CLUSTER_NAME: cluster_name, NodegroupAttributes.NODEGROUP_NAME: nodegroup_name, NODEROLE_ARN_KEY: NODEROLE_ARN_VALUE, SUBNETS_KEY: SUBNETS_VALUE, } endpoint = Endpoints.CREATE_NODEGROUP.format(clusterName=cluster_name) expected_arn_values = [ PARTITIONS, DEFAULT_REGION, ACCOUNT_ID, cluster_name, nodegroup_name, None, ] @pytest.fixture(autouse=True, name="test_client") def fixture_test_client(): if settings.TEST_SERVER_MODE: raise unittest.SkipTest("No point in testing this in ServerMode") backend = server.create_backend_app(service=SERVICE) yield backend.test_client() @pytest.fixture(scope="function", name="create_cluster") def fixtue_create_cluster(test_client): def create_and_verify_cluster(client, name): """Creates one valid cluster and verifies return status code 200.""" data = deepcopy(TestCluster.data) data.update(name=name) response = client.post( TestCluster.endpoint, data=json.dumps(data), headers=DEFAULT_HTTP_HEADERS ) assert response.status_code == StatusCodes.OK return json.loads(response.data.decode(DEFAULT_ENCODING))[ ResponseAttributes.CLUSTER ] def _execute(name=TestCluster.cluster_name): return create_and_verify_cluster(test_client, name=name) yield _execute @pytest.fixture(scope="function", autouse=True, name="create_nodegroup") def fixture_create_nodegroup(test_client): def create_and_verify_nodegroup(client, name): """Creates one valid nodegroup and verifies return status code 200.""" data = deepcopy(TestNodegroup.data) data.update(nodegroupName=name) response = client.post( TestNodegroup.endpoint, data=json.dumps(data), headers=DEFAULT_HTTP_HEADERS ) assert response.status_code == StatusCodes.OK return json.loads(response.data.decode(DEFAULT_ENCODING))[ ResponseAttributes.NODEGROUP ] def _execute(name=TestNodegroup.nodegroup_name): return create_and_verify_nodegroup(test_client, name=name) yield _execute @mock_aws def test_eks_create_single_cluster(create_cluster): result_cluster = create_cluster() assert result_cluster[ClusterAttributes.NAME] == TestCluster.cluster_name all_arn_values_should_be_valid( expected_arn_values=TestCluster.expected_arn_values, pattern=RegExTemplates.CLUSTER_ARN, arn_under_test=result_cluster[ClusterAttributes.ARN], ) @mock_aws def test_eks_create_multiple_clusters_with_same_name(test_client, create_cluster): create_cluster() expected_exception = ResourceInUseException expected_msg = CLUSTER_EXISTS_MSG.format(clusterName=TestCluster.cluster_name) expected_data = { ClusterAttributes.CLUSTER_NAME: TestCluster.cluster_name, NodegroupAttributes.NODEGROUP_NAME: None, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } response = test_client.post( TestCluster.endpoint, data=json.dumps(TestCluster.data), headers=DEFAULT_HTTP_HEADERS, ) should_return_expected_exception(response, expected_exception, expected_data) @mock_aws def test_eks_create_nodegroup_without_cluster(test_client): expected_exception = ResourceNotFoundException expected_msg = CLUSTER_NOT_FOUND_MSG.format(clusterName=TestCluster.cluster_name) expected_data = { ClusterAttributes.CLUSTER_NAME: None, NodegroupAttributes.NODEGROUP_NAME: None, FargateProfileAttributes.FARGATE_PROFILE_NAME: None, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } endpoint = Endpoints.CREATE_NODEGROUP.format(clusterName=TestCluster.cluster_name) response = test_client.post( endpoint, data=json.dumps(TestNodegroup.data), headers=DEFAULT_HTTP_HEADERS ) should_return_expected_exception(response, expected_exception, expected_data) @mock_aws def test_eks_create_nodegroup_on_existing_cluster(create_cluster, create_nodegroup): create_cluster() result_data = create_nodegroup() assert ( result_data[NodegroupAttributes.NODEGROUP_NAME] == TestNodegroup.nodegroup_name ) all_arn_values_should_be_valid( expected_arn_values=TestNodegroup.expected_arn_values, pattern=RegExTemplates.NODEGROUP_ARN, arn_under_test=result_data[NodegroupAttributes.ARN], ) @mock_aws def test_eks_create_multiple_nodegroups_with_same_name( test_client, create_cluster, create_nodegroup ): create_cluster() create_nodegroup() expected_exception = ResourceInUseException expected_msg = NODEGROUP_EXISTS_MSG.format( clusterName=TestNodegroup.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) expected_data = { ClusterAttributes.CLUSTER_NAME: TestNodegroup.cluster_name, NodegroupAttributes.NODEGROUP_NAME: TestNodegroup.nodegroup_name, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } response = test_client.post( TestNodegroup.endpoint, data=json.dumps(TestNodegroup.data), headers=DEFAULT_HTTP_HEADERS, ) should_return_expected_exception(response, expected_exception, expected_data) @mock_aws def test_eks_list_clusters(test_client, create_cluster): [create_cluster(name) for name in NAME_LIST] response = test_client.get( Endpoints.LIST_CLUSTERS.format( maxResults=DEFAULT_MAX_RESULTS, nextToken=DEFAULT_NEXT_TOKEN ) ) result_data = json.loads(response.data.decode(DEFAULT_ENCODING))[ ResponseAttributes.CLUSTERS ] assert response.status_code == StatusCodes.OK assert len(result_data) == len(NAME_LIST) assert sorted(result_data) == sorted(NAME_LIST) @mock_aws def test_eks_list_nodegroups(test_client, create_cluster, create_nodegroup): create_cluster() [create_nodegroup(name) for name in NAME_LIST] response = test_client.get( Endpoints.LIST_NODEGROUPS.format( clusterName=TestCluster.cluster_name, maxResults=DEFAULT_MAX_RESULTS, nextToken=DEFAULT_NEXT_TOKEN, ) ) result_data = json.loads(response.data.decode(DEFAULT_ENCODING))[ ResponseAttributes.NODEGROUPS ] assert response.status_code == StatusCodes.OK assert sorted(result_data) == sorted(NAME_LIST) assert len(result_data) == len(NAME_LIST) @mock_aws def test_eks_describe_existing_cluster(test_client, create_cluster): create_cluster() response = test_client.get( Endpoints.DESCRIBE_CLUSTER.format(clusterName=TestCluster.cluster_name) ) result_data = json.loads(response.data.decode(DEFAULT_ENCODING))[ ResponseAttributes.CLUSTER ] assert response.status_code == StatusCodes.OK assert result_data[ClusterAttributes.NAME] == TestCluster.cluster_name assert result_data[ClusterAttributes.ENCRYPTION_CONFIG] == [] all_arn_values_should_be_valid( expected_arn_values=TestCluster.expected_arn_values, pattern=RegExTemplates.CLUSTER_ARN, arn_under_test=result_data[ClusterAttributes.ARN], ) @mock_aws def test_eks_describe_nonexisting_cluster(test_client): expected_exception = ResourceNotFoundException expected_msg = CLUSTER_NOT_FOUND_MSG.format(clusterName=TestCluster.cluster_name) expected_data = { ClusterAttributes.CLUSTER_NAME: None, NodegroupAttributes.NODEGROUP_NAME: None, FargateProfileAttributes.FARGATE_PROFILE_NAME: None, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } response = test_client.get( Endpoints.DESCRIBE_CLUSTER.format(clusterName=TestCluster.cluster_name) ) should_return_expected_exception(response, expected_exception, expected_data) @mock_aws def test_eks_describe_existing_nodegroup(test_client, create_cluster, create_nodegroup): create_cluster() create_nodegroup() response = test_client.get( Endpoints.DESCRIBE_NODEGROUP.format( clusterName=TestNodegroup.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) ) result_data = json.loads(response.data.decode(DEFAULT_ENCODING))[ ResponseAttributes.NODEGROUP ] assert response.status_code == StatusCodes.OK assert result_data[ClusterAttributes.CLUSTER_NAME] == TestNodegroup.cluster_name assert ( result_data[NodegroupAttributes.NODEGROUP_NAME] == TestNodegroup.nodegroup_name ) all_arn_values_should_be_valid( expected_arn_values=TestNodegroup.expected_arn_values, pattern=RegExTemplates.NODEGROUP_ARN, arn_under_test=result_data[NodegroupAttributes.ARN], ) @mock_aws def test_eks_describe_nonexisting_nodegroup(test_client, create_cluster): create_cluster() expected_exception = ResourceNotFoundException expected_msg = NODEGROUP_NOT_FOUND_MSG.format( clusterName=TestNodegroup.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) expected_data = { ClusterAttributes.CLUSTER_NAME: TestNodegroup.cluster_name, NodegroupAttributes.NODEGROUP_NAME: TestNodegroup.nodegroup_name, FargateProfileAttributes.FARGATE_PROFILE_NAME: None, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } response = test_client.get( Endpoints.DESCRIBE_NODEGROUP.format( clusterName=TestCluster.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) ) should_return_expected_exception(response, expected_exception, expected_data) @mock_aws def test_eks_describe_nodegroup_nonexisting_cluster(test_client): expected_exception = ResourceNotFoundException expected_msg = CLUSTER_NOT_FOUND_MSG.format(clusterName=TestNodegroup.cluster_name) expected_data = { ClusterAttributes.CLUSTER_NAME: TestNodegroup.cluster_name, NodegroupAttributes.NODEGROUP_NAME: TestNodegroup.nodegroup_name, FargateProfileAttributes.FARGATE_PROFILE_NAME: None, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } response = test_client.get( Endpoints.DESCRIBE_NODEGROUP.format( clusterName=TestCluster.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) ) should_return_expected_exception(response, expected_exception, expected_data) @mock_aws def test_eks_delete_cluster(test_client, create_cluster): create_cluster() response = test_client.delete( Endpoints.DELETE_CLUSTER.format(clusterName=TestCluster.cluster_name) ) result_data = json.loads(response.data.decode(DEFAULT_ENCODING))[ ResponseAttributes.CLUSTER ] assert response.status_code == StatusCodes.OK assert result_data[ClusterAttributes.NAME] == TestCluster.cluster_name all_arn_values_should_be_valid( expected_arn_values=TestCluster.expected_arn_values, pattern=RegExTemplates.CLUSTER_ARN, arn_under_test=result_data[ClusterAttributes.ARN], ) @mock_aws def test_eks_delete_nonexisting_cluster(test_client): expected_exception = ResourceNotFoundException expected_msg = CLUSTER_NOT_FOUND_MSG.format(clusterName=TestCluster.cluster_name) expected_data = { ClusterAttributes.CLUSTER_NAME: None, NodegroupAttributes.NODEGROUP_NAME: None, FargateProfileAttributes.FARGATE_PROFILE_NAME: None, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } response = test_client.delete( Endpoints.DELETE_CLUSTER.format(clusterName=TestCluster.cluster_name) ) should_return_expected_exception(response, expected_exception, expected_data) @mock_aws def test_eks_delete_cluster_with_nodegroups( test_client, create_cluster, create_nodegroup ): create_cluster() create_nodegroup() expected_exception = ResourceInUseException expected_msg = CLUSTER_IN_USE_MSG.format(clusterName=TestCluster.cluster_name) expected_data = { ClusterAttributes.CLUSTER_NAME: TestCluster.cluster_name, NodegroupAttributes.NODEGROUP_NAME: TestNodegroup.nodegroup_name, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } response = test_client.delete( Endpoints.DELETE_CLUSTER.format(clusterName=TestCluster.cluster_name) ) should_return_expected_exception(response, expected_exception, expected_data) @mock_aws def test_eks_delete_nodegroup(test_client, create_cluster, create_nodegroup): create_cluster() create_nodegroup() response = test_client.delete( Endpoints.DELETE_NODEGROUP.format( clusterName=TestNodegroup.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) ) result_data = json.loads(response.data.decode(DEFAULT_ENCODING))[ ResponseAttributes.NODEGROUP ] assert response.status_code == StatusCodes.OK assert result_data[ClusterAttributes.CLUSTER_NAME] == TestNodegroup.cluster_name assert ( result_data[NodegroupAttributes.NODEGROUP_NAME] == TestNodegroup.nodegroup_name ) all_arn_values_should_be_valid( expected_arn_values=TestNodegroup.expected_arn_values, pattern=RegExTemplates.NODEGROUP_ARN, arn_under_test=result_data[NodegroupAttributes.ARN], ) @mock_aws def test_eks_delete_nonexisting_nodegroup(test_client, create_cluster): create_cluster() expected_exception = ResourceNotFoundException expected_msg = NODEGROUP_NOT_FOUND_MSG.format( clusterName=TestNodegroup.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) expected_data = { ClusterAttributes.CLUSTER_NAME: TestNodegroup.cluster_name, NodegroupAttributes.NODEGROUP_NAME: TestNodegroup.nodegroup_name, FargateProfileAttributes.FARGATE_PROFILE_NAME: None, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } response = test_client.delete( Endpoints.DELETE_NODEGROUP.format( clusterName=TestNodegroup.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) ) should_return_expected_exception(response, expected_exception, expected_data) @mock_aws def test_eks_delete_nodegroup_nonexisting_cluster(test_client): expected_exception = ResourceNotFoundException expected_msg = CLUSTER_NOT_FOUND_MSG.format( clusterName=TestNodegroup.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) expected_data = { ClusterAttributes.CLUSTER_NAME: None, NodegroupAttributes.NODEGROUP_NAME: None, FargateProfileAttributes.FARGATE_PROFILE_NAME: None, AddonAttributes.ADDON_NAME: None, ResponseAttributes.MESSAGE: expected_msg, } response = test_client.delete( Endpoints.DELETE_NODEGROUP.format( clusterName=TestNodegroup.cluster_name, nodegroupName=TestNodegroup.nodegroup_name, ) ) should_return_expected_exception(response, expected_exception, expected_data) def should_return_expected_exception(response, expected_exception, expected_data): result_data = json.loads(response.data.decode(DEFAULT_ENCODING)) assert response.status_code == expected_exception.STATUS assert response.headers.get(HttpHeaders.ErrorType) == expected_exception.TYPE assert result_data == expected_data