From 11465af7bb0dd56473f68d2eb2699705a143c4ed Mon Sep 17 00:00:00 2001 From: Luuk van Venrooij <11056665+seriva@users.noreply.github.com> Date: Tue, 8 Feb 2022 12:53:33 +0100 Subject: [PATCH] Changed autoscaling_group to plain EC2 VMs on AWS. (#2939) - Replaced AWS auto_scaling_groups with plain EC2 VM creation. - Added proper host sorting how it was implemented for the any and azure providers: #1076 - Sync up features with Azure Terraform implementation - Added support for use_network_security_groups flag #959 - Updated DoD for bugs to reflect changes made for #2832 --- .github/ISSUE_TEMPLATE/bug-report.md | 33 +++- cli/engine/providers/aws/APIProxy.py | 23 ++- .../providers/aws/InfrastructureBuilder.py | 178 ++++++++---------- .../providers/azure/InfrastructureBuilder.py | 14 +- docs/changelogs/CHANGELOG-2.0.md | 6 +- docs/home/ARM.md | 34 +--- docs/home/howto/SECURITY_GROUPS.md | 13 +- docs/home/howto/UPGRADE.md | 71 +------ schema/aws/defaults/epiphany-cluster.yml | 39 ++-- .../infrastructure/default-security-group.yml | 2 +- .../defaults/infrastructure/efs-storage.yml | 1 + .../infrastructure/launch-configuration.yml | 14 -- schema/aws/defaults/infrastructure/subnet.yml | 1 - .../infrastructure/virtual-machine.yml | 17 +- .../infrastructure/default-security-group.yml | 2 + .../validation/infrastructure/efs-storage.yml | 2 + .../infrastructure/launch-configuration.yml | 52 ----- .../aws/validation/infrastructure/subnet.yml | 2 - .../infrastructure/virtual-machine.yml | 39 ++-- terraform/aws/epiphany-cluster.j2 | 2 +- .../infrastructure/default-security-group.j2 | 8 +- terraform/aws/infrastructure/efs-storage.j2 | 6 +- .../aws/infrastructure/internet-gateway.j2 | 2 +- .../infrastructure/launch-configuration.j2 | 42 ----- terraform/aws/infrastructure/public-key.j2 | 2 +- .../aws/infrastructure/resource-group.j2 | 2 +- .../infrastructure/route-table-association.j2 | 2 +- terraform/aws/infrastructure/route-table.j2 | 4 +- .../aws/infrastructure/security-group-rule.j2 | 2 +- .../aws/infrastructure/security-group.j2 | 3 +- terraform/aws/infrastructure/subnet.j2 | 3 +- .../aws/infrastructure/virtual-machine.j2 | 73 +++---- terraform/aws/infrastructure/vpc.j2 | 2 +- terraform/azure/epiphany-cluster.j2 | 2 +- .../azure/infrastructure/availability-set.j2 | 2 +- ...rk-interface-security-group-association.j2 | 2 +- .../azure/infrastructure/network-interface.j2 | 2 +- .../infrastructure/network-security-group.j2 | 2 +- terraform/azure/infrastructure/public-ip.j2 | 2 +- .../azure/infrastructure/resource-group.j2 | 2 +- .../azure/infrastructure/storage-share.j2 | 2 +- ...bnet-network-security-group-association.j2 | 2 +- terraform/azure/infrastructure/subnet.j2 | 2 +- .../azure/infrastructure/virtual-machine.j2 | 2 +- terraform/azure/infrastructure/vnet.j2 | 2 +- .../engine/providers/aws/test_APIProxy.py | 31 +++ .../providers/aws/test_AWSConfigBuilder.py | 66 +------ .../azure/test_AzureConfigBuilder.py | 3 +- .../engine/providers/data/APIProxy_data.py | 24 ++- 49 files changed, 315 insertions(+), 529 deletions(-) delete mode 100644 schema/aws/defaults/infrastructure/launch-configuration.yml delete mode 100644 schema/aws/validation/infrastructure/launch-configuration.yml delete mode 100644 terraform/aws/infrastructure/launch-configuration.j2 create mode 100644 tests/unit/engine/providers/aws/test_APIProxy.py diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index c0c37939d8..8ef7b7a381 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -35,13 +35,26 @@ Add any other context about the problem here. **DoD checklist** -* [ ] Changelog updated (if affected version was released) -* [ ] COMPONENTS.md updated / doesn't need to be updated -* [ ] Automated tests passed (QA pipelines) - * [ ] apply - * [ ] upgrade -* [ ] Case covered by automated test (if possible) -* [ ] Idempotency tested -* [ ] Documentation updated / doesn't need to be updated -* [ ] All conversations in PR resolved -* [ ] Backport tasks created / doesn't need to be backported +- Changelog + - [ ] updated + - [ ] not needed +- COMPONENTS.md + - [ ] updated + - [ ] not needed +- Schema + - [ ] updated + - [ ] not needed +- Backport tasks + - [ ] created + - [ ] not needed +- Documentation + - [ ] added + - [ ] updated + - [ ] not needed +- [ ] Feature has automated tests +- [ ] Automated tests passed (QA pipelines) + - [ ] apply + - [ ] upgrade + - [ ] backup/restore +- [ ] Idempotency tested +- [ ] All conversations in PR resolved diff --git a/cli/engine/providers/aws/APIProxy.py b/cli/engine/providers/aws/APIProxy.py index 153ab99d0f..ae7e4678be 100644 --- a/cli/engine/providers/aws/APIProxy.py +++ b/cli/engine/providers/aws/APIProxy.py @@ -2,7 +2,7 @@ from cli.helpers.doc_list_helpers import select_single from cli.helpers.objdict_helpers import dict_to_objdict -from cli.models.AnsibleHostModel import AnsibleHostModel +from cli.models.AnsibleHostModel import AnsibleOrderedHostModel class APIProxy: @@ -26,9 +26,7 @@ def get_ips_for_feature(self, component_key): cluster_name = self.cluster_model.specification.name.lower() look_for_public_ip = self.cluster_model.specification.cloud.use_public_ips vpc_id = self.get_vpc_id() - - ec2 = self.session.resource('ec2') - running_instances = ec2.instances.filter( + running_instances = self.session.resource('ec2').instances.filter( Filters=[{ 'Name': 'instance-state-name', 'Values': ['running'] @@ -37,8 +35,8 @@ def get_ips_for_feature(self, component_key): 'Values': [vpc_id] }, { - 'Name': 'tag:'+component_key, - 'Values': [''] + 'Name': 'tag:component_key', + 'Values': [component_key] }, { 'Name': 'tag:cluster_name', @@ -46,12 +44,19 @@ def get_ips_for_feature(self, component_key): }] ) - result = [] + result: List[AnsibleOrderedHostModel] = [] + for instance in running_instances: + hostname = '' + for tag in instance.tags: + if tag['Key'] == 'Name': + hostname = tag['Value'] if look_for_public_ip: - result.append(AnsibleHostModel(instance.public_dns_name, instance.public_ip_address)) + result.append(AnsibleOrderedHostModel(hostname, instance.public_ip_address)) else: - result.append(AnsibleHostModel(instance.private_dns_name, instance.private_ip_address)) + result.append(AnsibleOrderedHostModel(hostname, instance.private_ip_address)) + + result.sort() return result def get_image_id(self, os_full_name): diff --git a/cli/engine/providers/aws/InfrastructureBuilder.py b/cli/engine/providers/aws/InfrastructureBuilder.py index 8bd7752ad4..9ea182a6d9 100644 --- a/cli/engine/providers/aws/InfrastructureBuilder.py +++ b/cli/engine/providers/aws/InfrastructureBuilder.py @@ -22,9 +22,15 @@ def __init__(self, docs, manifest_docs=[]): self.cluster_name = self.cluster_model.specification.name.lower() self.cluster_prefix = self.cluster_model.specification.prefix.lower() self.use_network_security_groups = self.cluster_model.specification.cloud.network.use_network_security_groups + self.use_public_ips = self.cluster_model.specification.cloud.use_public_ips self.docs = docs self.manifest_docs = manifest_docs + # If there are no security groups Ansible provisioning will fail because + # SSH is not allowed then with public IPs on AWS. + if not(self.use_network_security_groups) and self.use_public_ips: + self.logger.warning('Use of security groups has been disabled and public IPs are used. Ansible run will fail because SSH will not be allowed.') + def run(self): infrastructure = [] @@ -49,62 +55,52 @@ def run(self): efs_config = self.get_efs_config() - if not(self.use_network_security_groups): - self.logger.warning('The "use_network_security_groups" flag is currently ignored on AWS') - for component_key, component_value in self.cluster_model.specification.components.items(): - if component_value['count'] < 1: + vm_count = component_value['count'] + if vm_count < 1: continue - subnets_to_create = [] - security_groups_to_create = [] - subnet_index = 0 - asg_index = 0 - for subnet_definition in component_value.subnets: # todo extract to another method or class - subnet = select_first(infrastructure, lambda item: item.kind == 'infrastructure/subnet' and - item.specification.cidr_block == subnet_definition['address_pool']) - security_group = select_first(infrastructure, lambda item: item.kind == 'infrastructure/security-group' and - item.specification.cidr_block == subnet_definition['address_pool']) - - if subnet is None: - subnet = self.get_subnet(subnet_definition, component_key, vpc_name, subnet_index) - infrastructure.append(subnet) - - security_group = self.get_security_group(subnet, component_key, vpc_name, subnet_index) - infrastructure.append(security_group) - - route_table_association = self.get_route_table_association(route_table.specification.name, - component_key, - subnet.specification.name, subnet_index) - infrastructure.append(route_table_association) - subnet_index += 1 - - subnets_to_create.append(subnet) - security_groups_to_create.append(security_group) + # The vm config also contains some other stuff we use for network and security config. + # So get it here and pass it allong. + vm_config = self.get_virtual_machine(component_value) - autoscaling_group = self.get_autoscaling_group(component_key, component_value, subnets_to_create, asg_index) + # For now only one subnet per component. + if (len(component_value.subnets) > 1): + self.logger.warning('On AWS only one subnet per component is supported for now. Taking first and ignoring others.') - for security_group in security_groups_to_create: - for rule in autoscaling_group.specification.security.rules: - if not self.rule_exists_in_list(security_group.specification.rules, rule): - security_group.specification.rules.append(rule) + subnet_definition = component_value.subnets[0] + subnet = select_first(infrastructure, lambda item: item.kind == 'infrastructure/subnet' and + item.specification.cidr_block == subnet_definition['address_pool']) + security_group = select_first(infrastructure, lambda item: item.kind == 'infrastructure/security-group' and + item.specification.cidr_block == subnet_definition['address_pool']) - launch_configuration = self.get_launch_configuration(autoscaling_group, component_key, - security_groups_to_create) + if subnet is None: + subnet = self.get_subnet(subnet_definition, component_key, vpc_name, 0) + infrastructure.append(subnet) - launch_configuration.specification.key_name = public_key_config.specification.key_name + if vm_config.specification.mount_efs: + self.efs_add_mount_target_config(efs_config, subnet) - self.set_image_id_for_launch_configuration(self.cluster_model, self.docs, launch_configuration, - autoscaling_group) - autoscaling_group.specification.launch_configuration = launch_configuration.specification.name + route_table_association = self.get_route_table_association(route_table.specification.name, + component_key, + subnet.specification.name, 0) + infrastructure.append(route_table_association) - if autoscaling_group.specification.mount_efs: - for subnet in subnets_to_create: - self.efs_add_mount_target_config(efs_config, subnet) + if self.use_network_security_groups: + security_group = self.get_security_group(subnet, component_key, vpc_name, 0) + for rule in vm_config.specification.security.rules: + if not self.rule_exists_in_list(security_group.specification.rules, rule): + security_group.specification.rules.append(rule) + infrastructure.append(security_group) - infrastructure.append(autoscaling_group) - infrastructure.append(launch_configuration) - asg_index += 1 + for index in range(vm_count): + vm = self.get_vm(component_key, + vm_config, + subnet, + public_key_config, + security_group, + index) + infrastructure.append(vm) if self.has_efs_any_mounts(efs_config): infrastructure.append(efs_config) @@ -128,40 +124,36 @@ def get_vpc_config(self): def get_default_security_group_config(self, vpc_config): sg_config = self.get_config_or_default(self.docs, 'infrastructure/default-security-group') sg_config.specification.vpc_name = vpc_config.specification.name + sg_config.specification.cluster_name = self.cluster_name return sg_config def get_efs_config(self): efs_config = self.get_config_or_default(self.docs, 'infrastructure/efs-storage') efs_config.specification.token = "aws-efs-token-" + self.cluster_name efs_config.specification.name = resource_name(self.cluster_prefix, self.cluster_name, 'efs') + efs_config.specification.cluster_name = self.cluster_name return efs_config - def get_autoscaling_group(self, component_key, component_value, subnets_to_create, index): - autoscaling_group = dict_to_objdict(deepcopy(self.get_virtual_machine(component_value))) - autoscaling_group.specification.cluster_name = self.cluster_name - autoscaling_group.specification.name = resource_name(self.cluster_prefix, self.cluster_name, 'asg' + '-' + str(index), component_key) - autoscaling_group.specification.count = component_value.count - autoscaling_group.specification.subnet_names = [s.specification.name for s in subnets_to_create] - autoscaling_group.specification.availability_zones = [s.specification.availability_zone for s in subnets_to_create] - autoscaling_group.specification.tags.append({'cluster_name': self.cluster_name}) - autoscaling_group.specification.tags.append({component_key: ''}) - return autoscaling_group - - def get_launch_configuration(self, autoscaling_group, component_key, security_groups_to_create): - launch_configuration = self.get_config_or_default(self.docs, 'infrastructure/launch-configuration') - launch_configuration.specification.name = resource_name(self.cluster_prefix, self.cluster_name, 'launch-config', component_key) - launch_configuration.specification.size = autoscaling_group.specification.size - launch_configuration.specification.security_groups = [s.specification.name for s in security_groups_to_create] - launch_configuration.specification.disks = autoscaling_group.specification.disks - launch_configuration.specification.ebs_optimized = autoscaling_group.specification.ebs_optimized - launch_configuration.specification.associate_public_ip = self.cluster_model.specification.cloud.use_public_ips - return launch_configuration + def get_vm(self, component_key, vm_config, subnet, public_key_config, security_group, index): + vm = dict_to_objdict(deepcopy(vm_config)) + vm.specification.name = resource_name(self.cluster_prefix, self.cluster_name, 'vm' + '-' + str(index), component_key) + vm.specification.cluster_name = self.cluster_name + vm.specification.component_key = component_key + vm.specification.subnet_name = subnet.specification.name + vm.specification.key_name = public_key_config.specification.key_name + vm.specification.use_network_security_groups = self.use_network_security_groups + if self.use_network_security_groups: + vm.specification.security_groups = [security_group.specification.name] + vm.specification.associate_public_ip = self.cluster_model.specification.cloud.use_public_ips + with APIProxy(self.cluster_model, []) as proxy: + vm.specification.image_id = proxy.get_image_id(vm.specification.os_full_name) + return vm def get_subnet(self, subnet_definition, component_key, vpc_name, index): subnet = self.get_config_or_default(self.docs, 'infrastructure/subnet') subnet.specification.vpc_name = vpc_name subnet.specification.cidr_block = subnet_definition['address_pool'] - subnet.specification.availability_zone = subnet_definition['availability_zone'] + subnet.specification.name = resource_name(self.cluster_prefix, self.cluster_name, 'subnet' + '-' + str(index), component_key) subnet.specification.cluster_name = self.cluster_name return subnet @@ -220,26 +212,25 @@ def get_public_key(self): return public_key_config def add_security_rules_inbound_efs(self, infrastructure, security_group): - ags_allowed_to_efs = select_all(infrastructure, lambda item: item.kind == 'infrastructure/virtual-machine' and + vms_allowed_to_efs = select_all(infrastructure, lambda item: item.kind == 'infrastructure/virtual-machine' and item.specification.authorized_to_efs) - for asg in ags_allowed_to_efs: - for subnet_in_asg in asg.specification.subnet_names: - subnet = select_single(infrastructure, lambda item: item.kind == 'infrastructure/subnet' and - item.specification.name == subnet_in_asg) - - rule_defined = select_first(security_group.specification.rules, lambda item: item.source_address_prefix == subnet.specification.cidr_block - and item.destination_port_range == 2049) - if rule_defined is None: - rule = self.get_config_or_default(self.docs, 'infrastructure/security-group-rule') - rule.specification.name = 'sg-rule-nfs-default-from-'+subnet.specification.name - rule.specification.description = 'NFS inbound for '+subnet.specification.name - rule.specification.direction = 'ingress' - rule.specification.protocol = 'tcp' - rule.specification.destination_port_range = "2049" - rule.specification.source_address_prefix = subnet.specification.cidr_block - rule.specification.destination_address_prefix = '*' - security_group.specification.rules.append(rule.specification) + for vm in vms_allowed_to_efs: + subnet = select_single(infrastructure, lambda item: item.kind == 'infrastructure/subnet' and + item.specification.name == vm.specification.subnet_name) + + rule_defined = select_first(security_group.specification.rules, lambda item: item.source_address_prefix == subnet.specification.cidr_block + and item.destination_port_range == 2049) + if rule_defined is None: + rule = self.get_config_or_default(self.docs, 'infrastructure/security-group-rule') + rule.specification.name = 'sg-rule-nfs-default-from-'+subnet.specification.name + rule.specification.description = 'NFS inbound for '+subnet.specification.name + rule.specification.direction = 'ingress' + rule.specification.protocol = 'tcp' + rule.specification.destination_port_range = "2049" + rule.specification.source_address_prefix = subnet.specification.cidr_block + rule.specification.destination_address_prefix = '*' + security_group.specification.rules.append(rule.specification) rules = [] for rule in security_group.specification.rules: @@ -287,13 +278,10 @@ def get_virtual_machine(self, component_value): @staticmethod def efs_add_mount_target_config(efs_config, subnet): - target = select_first(efs_config.specification.mount_targets, - lambda item: item['availability_zone'] == subnet.specification.availability_zone) - if target is None: - efs_config.specification.mount_targets.append( - {'name': 'efs-'+subnet.specification.name+'-mount', - 'subnet_name': subnet.specification.name, - 'availability_zone': subnet.specification.availability_zone}) + efs_config.specification.mount_targets.append( + {'name': 'efs-'+subnet.specification.name+'-mount', + 'subnet_name': subnet.specification.name}) + @staticmethod def has_efs_any_mounts(efs_config): @@ -301,11 +289,6 @@ def has_efs_any_mounts(efs_config): return True return False - @staticmethod - def set_image_id_for_launch_configuration(cluster_model, docs, launch_configuration, autoscaling_group): - with APIProxy(cluster_model, docs) as proxy: - image_id = proxy.get_image_id(autoscaling_group.specification.os_full_name) - launch_configuration.specification.image_id = image_id @staticmethod def get_config_or_default(docs, kind): @@ -315,6 +298,7 @@ def get_config_or_default(docs, kind): config['version'] = VERSION return config + @staticmethod def rule_exists_in_list(rule_list, rule_to_check): for rule in rule_list: diff --git a/cli/engine/providers/azure/InfrastructureBuilder.py b/cli/engine/providers/azure/InfrastructureBuilder.py index 2fa8564044..b78fdf45fc 100644 --- a/cli/engine/providers/azure/InfrastructureBuilder.py +++ b/cli/engine/providers/azure/InfrastructureBuilder.py @@ -24,6 +24,11 @@ def __init__(self, docs, manifest_docs=[]): self.docs = docs self.manifest_docs = manifest_docs + # If there are no security groups Ansible provisioning will fail because + # SSH is not allowed then with public IPs on Azure. + if not(self.use_network_security_groups) and self.use_public_ips: + self.logger.warning('Use of security groups has been disabled and public IPs are used. Ansible run will fail because SSH will not be allowed.') + # Check if there is a hostname_domain_extension we already applied and we want to retain. # The same as VM images we want to preserve hostname_domain_extension over versions. self.hostname_domain_extension = self.cluster_model.specification.cloud.hostname_domain_extension @@ -61,19 +66,10 @@ def run(self): # Set property that controls cloud-init. vm_config.specification['use_cloud_init_custom_data'] = cloud_init_custom_data.specification.enabled - # If there are no security groups Ansible provisioning will fail because - # SSH is not allowed then with public IPs on Azure. - if not(self.use_network_security_groups) and self.use_public_ips: - self.logger.warning('Use of security groups has been disabled and public IP are used. Ansible run will fail because SSH will not be allowed.') - # For now only one subnet per component. if (len(component_value.subnets) > 1): self.logger.warning('On Azure only one subnet per component is supported for now. Taking first and ignoring others.') - # Add message for ignoring availabiltity zones if present. - if 'availability_zone' in component_value.subnets[0]: - self.logger.warning('On Azure availability_zones are not supported yet. Ignoring definition.') - subnet_definition = component_value.subnets[0] subnet = select_first(infrastructure, lambda item: item.kind == 'infrastructure/subnet' and item.specification.address_prefix == subnet_definition['address_pool']) diff --git a/docs/changelogs/CHANGELOG-2.0.md b/docs/changelogs/CHANGELOG-2.0.md index c7670963f7..42ab425350 100644 --- a/docs/changelogs/CHANGELOG-2.0.md +++ b/docs/changelogs/CHANGELOG-2.0.md @@ -4,6 +4,7 @@ ### Added +- [#959](https://github.com/epiphany-platform/epiphany/issues/959) - Add usage of use_network_security_groups to disable NSG on AWS - [#2701](https://github.com/epiphany-platform/epiphany/issues/2701) - Epicli prepare - generate files in separate directory - [#2812](https://github.com/epiphany-platform/epiphany/issues/2812) - Extend K8s config validation @@ -12,6 +13,7 @@ - [#2653](https://github.com/epiphany-platform/epiphany/issues/2653) - Epicli is failing in air-gapped infra mode - [#1569](https://github.com/epiphany-platform/epiphany/issues/1569) - Azure unmanaged disks not supported by Epiphany but there is misleading setting in the default configuration - [#2832](https://github.com/epiphany-platform/epiphany/issues/2832) - Make the DoD checklist clear +- [#2853](https://github.com/epiphany-platform/epiphany/issues/2853) - Change autoscaling_group approach in AWS provider in favor of plain VM creation. - [#2669](https://github.com/epiphany-platform/epiphany/issues/2669) - Restarting the installation process can cause certificate problems if K8s was not fully configured @@ -41,8 +43,6 @@ ### Breaking changes -- Upgrade of Terraform components in issue [#2825](https://github.com/epiphany-platform/epiphany/issues/2825) will make running re-apply with infrastructure break on existing 1.x clusters. The advice is to deploy a new cluster and migrate data. If needed a manual upgrade path is described [here.](../home/howto/UPGRADE.md#terraform-upgrade-from-epiphany-1.x-to-2.x) -- Kubernetes container runtime changed. Dockershim and Docker are no longer on Kubernetes hosts. -- Filebeat docker input replaced by container input with new fields. +- Upgrade of Terraform components in issue [#2825](https://github.com/epiphany-platform/epiphany/issues/2825) and [#2853](https://github.com/epiphany-platform/epiphany/issues/2853) will make running re-apply with infrastructure break on existing 1.x clusters. The advice is to deploy a new cluster and migrate data. If needed a manual upgrade path is described [here.](../home/howto/UPGRADE.md#terraform-upgrade-from-epiphany-1.x-to-2.x) ### Known issues diff --git a/docs/home/ARM.md b/docs/home/ARM.md index c53945efd7..94466f141b 100644 --- a/docs/home/ARM.md +++ b/docs/home/ARM.md @@ -279,66 +279,52 @@ specification: count: 2 machine: kafka-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.5.0/24 + - address_pool: 10.1.5.0/24 kubernetes_master: count: 1 machine: kubernetes-master-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.1.0/24 - - availability_zone: eu-west-1b - address_pool: 10.1.2.0/24 + - address_pool: 10.1.1.0/24 kubernetes_node: count: 3 machine: kubernetes-node-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.1.0/24 - - availability_zone: eu-west-1b - address_pool: 10.1.2.0/24 + - address_pool: 10.1.1.0/24 load_balancer: count: 1 machine: lb-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.7.0/24 + - address_pool: 10.1.7.0/24 logging: count: 2 machine: logging-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.3.0/24 + - address_pool: 10.1.3.0/24 monitoring: count: 1 machine: monitoring-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.4.0/24 + - address_pool: 10.1.4.0/24 postgresql: count: 1 machine: postgresql-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.6.0/24 + - address_pool: 10.1.6.0/24 rabbitmq: count: 2 machine: rabbitmq-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.8.0/24 + - address_pool: 10.1.8.0/24 opendistro_for_elasticsearch: count: 1 machine: opendistro-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.10.0/24 + - address_pool: 10.1.10.0/24 repository: count: 1 machine: repository-machine-arm subnets: - - availability_zone: eu-west-1a - address_pool: 10.1.11.0/24 + - address_pool: 10.1.11.0/24 --- kind: infrastructure/virtual-machine title: "Virtual Machine Infra" diff --git a/docs/home/howto/SECURITY_GROUPS.md b/docs/home/howto/SECURITY_GROUPS.md index f3e0b56855..d9f84a09f3 100644 --- a/docs/home/howto/SECURITY_GROUPS.md +++ b/docs/home/howto/SECURITY_GROUPS.md @@ -253,26 +253,19 @@ specification: machine: repository-machine configuration: default subnets: - - availability_zone: eu-central-1a - address_pool: 10.1.11.0/24 + - address_pool: 10.1.11.0/24 kubernetes_master: count: 1 machine: kubernetes-master-machine configuration: default subnets: - - availability_zone: eu-central-1a - address_pool: 10.1.1.0/24 - - availability_zone: eu-central-1b - address_pool: 10.1.2.0/24 + - address_pool: 10.1.1.0/24 kubernetes_node: count: 2 machine: kubernetes-node-machine configuration: default subnets: - - availability_zone: eu-central-1a - address_pool: 10.1.1.0/24 - - availability_zone: eu-central-1b - address_pool: 10.1.2.0/24 + - address_pool: 10.1.1.0/24 logging: count: 0 monitoring: diff --git a/docs/home/howto/UPGRADE.md b/docs/home/howto/UPGRADE.md index efec99b4bb..ca64f5a12e 100644 --- a/docs/home/howto/UPGRADE.md +++ b/docs/home/howto/UPGRADE.md @@ -428,6 +428,7 @@ From Epiphany 1.x to 2.x the Terraform stack received the following major update - Terraform 0.12.6 to 1.1.3 - Azurerm provider 1.38.0 to 2.91.0 - AWS provider 2.26 to 3.71.0 +- Removal of auto-scaling-groups in favor of plain EC2 instances on AWS. These introduce some breaking changes which will require manual steps for upgrading an existing 1.x clusters. As this is not straight forward we recommend deploying a new cluster on 2.x and migrating data instead. @@ -521,72 +522,4 @@ General steps: ### AWS -Notes: -- If you made any manual changes to your cluster infrastructure outside of Terraform this might cause issues. -- Only run `terraform apply` if `terraform plan` shows your infrastructure does not match the configuration. -- Manual Terraform ugrade up to v1.0.x should be completed before running `epicli apply` command with Epiphany 2.x. -- Terraform can be installed as a binary package or by using package managers, see more: https://learn.hashicorp.com/tutorials/terraform/install-cli - -#### v0.12.6 => v0.13.x - -The official documentation can be found here: https://www.terraform.io/language/upgrade-guides/0-13 - -General steps: -- Download the latest Terraform v0.13.x: https://releases.hashicorp.com/terraform/ -- Run the following sets of commands in the `build/clustername/terraform` folder and follow the steps if asked: - ```shell - terraform init - terraform 0.13upgrade - terraform plan - terraform apply (if needed) - ``` - -#### v0.13.x => v0.14.x - -The official documentation can be found here: https://www.terraform.io/language/upgrade-guides/0-14 - -General steps: -- Download the latest Terraform v0.14.x: https://releases.hashicorp.com/terraform/ -- Run the following sets of commands in the `build/clustername/terraform` folder and follow the steps if asked: - ```shell - terraform init - terraform plan - terraform apply (if needed) - ``` - -#### v0.14.x => v1.0.x - -Note: From v0.14.x we can upgrade straight to v1.0.x. No need to upgrade to v0.15.x first. - -The official documentation can be found here: https://www.terraform.io/language/upgrade-guides/1-0 - -General steps: -- Download the latest Terraform v1.0.x: https://releases.hashicorp.com/terraform/ -- Run the following sets of commands in the `build/clustername/terraform` folder and follow the steps if asked: - ```shell - terraform init - terraform plan - terraform apply (if needed) - ``` -#### v1.0.x => v1.1.3 - -In this step we also force the upgrade from AWS provider 2.26 to 3.71.0 which requires a few more steps to resolve some pending issues. -At this point, the steps assume that you are already running Epiphany 2.x image. - -The official documentation can be found here: https://www.terraform.io/language/upgrade-guides/1-1 - -General steps: -- Run epicli to generate the new AWS provider Terraform scripts: - ```shell - epicli apply -f data.yml - ``` - After the Terraform scripts generation `terraform init ...` will result in the following error: - `Error: Failed to query available provider packages` -- To fix the issue from previous step manually run from the epicli container in `build/clustername/terraform`: - ```shell - terraform init -upgrade - ``` -- Now re-run epicli again: - ```shell - epicli apply -f data.yml - ``` +The Terraform for AWS deployments between Epiphany 1.x and 2.x is not compatible and migration is not possible without destruction of the enviroment. The only options is to deploy a new cluster and migrate the data. diff --git a/schema/aws/defaults/epiphany-cluster.yml b/schema/aws/defaults/epiphany-cluster.yml index f1dbd958a2..b7038b4249 100644 --- a/schema/aws/defaults/epiphany-cluster.yml +++ b/schema/aws/defaults/epiphany-cluster.yml @@ -25,81 +25,64 @@ specification: machine: kubernetes-master-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.1.0/24 - - availability_zone: eu-west-2b - address_pool: 10.1.2.0/24 + - address_pool: 10.1.1.0/24 kubernetes_node: count: 2 machine: kubernetes-node-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.1.0/24 - - availability_zone: eu-west-2b - address_pool: 10.1.2.0/24 + - address_pool: 10.1.1.0/24 logging: count: 1 machine: logging-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.3.0/24 + - address_pool: 10.1.3.0/24 monitoring: count: 1 machine: monitoring-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.4.0/24 + - address_pool: 10.1.4.0/24 kafka: count: 2 machine: kafka-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.5.0/24 + - address_pool: 10.1.5.0/24 postgresql: count: 0 machine: postgresql-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.6.0/24 + - address_pool: 10.1.6.0/24 load_balancer: count: 1 machine: load-balancer-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.7.0/24 + - address_pool: 10.1.7.0/24 rabbitmq: count: 0 machine: rabbitmq-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.8.0/24 + - address_pool: 10.1.8.0/24 opendistro_for_elasticsearch: count: 0 machine: logging-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.10.0/24 + - address_pool: 10.1.10.0/24 repository: count: 1 machine: repository-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.11.0/24 + - address_pool: 10.1.11.0/24 single_machine: count: 0 machine: single-machine configuration: default subnets: - - availability_zone: eu-west-2a - address_pool: 10.1.1.0/24 - - availability_zone: eu-west-2b - address_pool: 10.1.2.0/24 + - address_pool: 10.1.1.0/24 diff --git a/schema/aws/defaults/infrastructure/default-security-group.yml b/schema/aws/defaults/infrastructure/default-security-group.yml index 5674505ff7..d3676a9b96 100644 --- a/schema/aws/defaults/infrastructure/default-security-group.yml +++ b/schema/aws/defaults/infrastructure/default-security-group.yml @@ -4,6 +4,7 @@ provider: aws name: default-security-group specification: name: default-security-group + cluster_name: SET_BY_AUTOMATION vpc_name: SET_BY_AUTOMATION rules: [] # - name: ssh @@ -13,4 +14,3 @@ specification: # destination_port_range: "22" # source_address_prefix: "10.1.0.0/22" # destination_address_prefix: "*" - diff --git a/schema/aws/defaults/infrastructure/efs-storage.yml b/schema/aws/defaults/infrastructure/efs-storage.yml index bcd27b23d1..56e62d5ccf 100644 --- a/schema/aws/defaults/infrastructure/efs-storage.yml +++ b/schema/aws/defaults/infrastructure/efs-storage.yml @@ -4,6 +4,7 @@ provider: aws name: default specification: name: SET_BY_AUTOMATION + cluster_name: SET_BY_AUTOMATION token: SET_BY_AUTOMATION encrypted: true performance_mode: "generalPurpose" diff --git a/schema/aws/defaults/infrastructure/launch-configuration.yml b/schema/aws/defaults/infrastructure/launch-configuration.yml deleted file mode 100644 index e2c4924ca7..0000000000 --- a/schema/aws/defaults/infrastructure/launch-configuration.yml +++ /dev/null @@ -1,14 +0,0 @@ -kind: infrastructure/launch-configuration -title: "Launch configuration" -provider: aws -name: default -specification: - name: SET_BY_AUTOMATION - image_id: SET_BY_AUTOMATION - size: SET_BY_AUTOMATION - key_name: SET_BY_AUTOMATION - disks: SET_BY_AUTOMATION - ebs_optimized: SET_BY_AUTOMATION - associate_public_ip: SET_BY_AUTOMATION - security_groups: [] # SET_BY_AUTOMATION - enable_monitoring: true diff --git a/schema/aws/defaults/infrastructure/subnet.yml b/schema/aws/defaults/infrastructure/subnet.yml index 84406b72af..7b41befa1f 100644 --- a/schema/aws/defaults/infrastructure/subnet.yml +++ b/schema/aws/defaults/infrastructure/subnet.yml @@ -7,4 +7,3 @@ specification: vpc_name: SET_BY_AUTOMATION cidr_block: SET_BY_AUTOMATION cluster_name: SET_BY_AUTOMATION - availability_zone: SET_BY_AUTOMATION diff --git a/schema/aws/defaults/infrastructure/virtual-machine.yml b/schema/aws/defaults/infrastructure/virtual-machine.yml index 49150661ae..7619d316c6 100644 --- a/schema/aws/defaults/infrastructure/virtual-machine.yml +++ b/schema/aws/defaults/infrastructure/virtual-machine.yml @@ -4,15 +4,16 @@ provider: aws name: default specification: name: SET_BY_AUTOMATION - count: SET_BY_AUTOMATION - subnet_names: [] - availability_zones: [] # specified automatically - based on subnet az's - launch_configuration: SET_BY_AUTOMATION cluster_name: SET_BY_AUTOMATION + component_key: SET_BY_AUTOMATION + image_id: SET_BY_AUTOMATION + key_name: SET_BY_AUTOMATION + subnet_name: SET_BY_AUTOMATION + associate_public_ip: SET_BY_AUTOMATION + use_network_security_groups: SET_BY_AUTOMATION + security_groups: [] # SET_BY_AUTOMATION authorized_to_efs: false mount_efs: false - tags: - - version: 0.4.2 size: t2.micro os_full_name: ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-20220110 os_type: linux @@ -58,8 +59,6 @@ title: "Virtual Machine Infra" provider: aws name: rabbitmq-machine specification: - tags: - - version: 0.4.2 size: t3.micro os_type: linux security: @@ -99,8 +98,6 @@ title: "Virtual Machine Infra" provider: aws name: load-balancer-machine specification: - tags: - - version: 0.4.2 size: t3.micro os_type: linux security: diff --git a/schema/aws/validation/infrastructure/default-security-group.yml b/schema/aws/validation/infrastructure/default-security-group.yml index 5507882c89..d1c291a417 100644 --- a/schema/aws/validation/infrastructure/default-security-group.yml +++ b/schema/aws/validation/infrastructure/default-security-group.yml @@ -5,6 +5,8 @@ type: object properties: name: type: string + cluster_name: + type: string vpc_name: type: string rules: diff --git a/schema/aws/validation/infrastructure/efs-storage.yml b/schema/aws/validation/infrastructure/efs-storage.yml index fdff13864f..d69719885d 100644 --- a/schema/aws/validation/infrastructure/efs-storage.yml +++ b/schema/aws/validation/infrastructure/efs-storage.yml @@ -5,6 +5,8 @@ type: object properties: name: type: string + cluster_name: + type: string token: type: string encrypted: diff --git a/schema/aws/validation/infrastructure/launch-configuration.yml b/schema/aws/validation/infrastructure/launch-configuration.yml deleted file mode 100644 index 6aa06495fe..0000000000 --- a/schema/aws/validation/infrastructure/launch-configuration.yml +++ /dev/null @@ -1,52 +0,0 @@ -"$id": "#/specification" -title: "Launch-configuration specification schema" -description: "Launch-configuration specification schema" -type: object -properties: - name: - type: string - image_id: - type: string - size: - type: string - key_name: - type: string - disks: - type: object - properties: - root: - type: object - properties: - volume_type: - type: string - volume_size: - type: integer - delete_on_termination: - type: boolean - encrypted: - type: boolean - additional_disks: - type: array - items: - type: object - properties: - device_name: - type: string - volume_type: - type: string - volume_size: - type: integer - delete_on_termination: - type: boolean - encrypted: - type: boolean - ebs_optimized: - type: boolean - associate_public_ip: - type: boolean - security_groups: - type: array - items: - - type: string - enable_monitoring: - type: boolean diff --git a/schema/aws/validation/infrastructure/subnet.yml b/schema/aws/validation/infrastructure/subnet.yml index 0d49f682cd..9fb94851f9 100644 --- a/schema/aws/validation/infrastructure/subnet.yml +++ b/schema/aws/validation/infrastructure/subnet.yml @@ -11,5 +11,3 @@ properties: type: string cluster_name: type: string - availability_zone: - type: string diff --git a/schema/aws/validation/infrastructure/virtual-machine.yml b/schema/aws/validation/infrastructure/virtual-machine.yml index f22bd40a68..b166ae2889 100644 --- a/schema/aws/validation/infrastructure/virtual-machine.yml +++ b/schema/aws/validation/infrastructure/virtual-machine.yml @@ -1,35 +1,32 @@ "$id": "#/specification" -title: "Virtual-machine specification schema" -description: "Virtual-machine specification schema" +title: "Virtual machine specification schema" +description: "Virtual machine specification schema" type: object properties: name: type: string - count: - type: integer - subnet_names: - type: array - items: - type: string - availability_zones: + cluster_name: + type: string + component_key: + type: string + image_id: + type: string + key_name: + type: string + subnet_name: + type: string + associate_public_ip: + type: boolean + use_network_security_groups: + type: boolean + security_groups: type: array items: type: string - launch_configuration: - type: string - cluster_name: - type: string authorized_to_efs: type: boolean mount_efs: type: boolean - tags: - type: array - items: - type: object - properties: - version: - type: string size: type: string os_full_name: @@ -89,3 +86,5 @@ properties: type: string destination_address_prefix: type: string + enum: + - 0.0.0.0/0 diff --git a/terraform/aws/epiphany-cluster.j2 b/terraform/aws/epiphany-cluster.j2 index 4007fd7ad2..152e2aee0c 100644 --- a/terraform/aws/epiphany-cluster.j2 +++ b/terraform/aws/epiphany-cluster.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/aws/infrastructure/default-security-group.j2 b/terraform/aws/infrastructure/default-security-group.j2 index c8db3a2586..adc9aca59c 100644 --- a/terraform/aws/infrastructure/default-security-group.j2 +++ b/terraform/aws/infrastructure/default-security-group.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### @@ -13,6 +13,12 @@ resource "aws_default_security_group" "{{ specification.name }}" { vpc_id = aws_vpc.{{ specification.vpc_name }}.id + tags = { + cluster_name = "{{ specification.cluster_name }}" + cluster_version = "{{ version }}" + Name = "{{ specification.name }}" + } + {% for rule in specification.rules %} {%- if rule.direction | lower in ["inbound", "ingress"] %} ingress { diff --git a/terraform/aws/infrastructure/efs-storage.j2 b/terraform/aws/infrastructure/efs-storage.j2 index 1ce5640213..87d474e430 100644 --- a/terraform/aws/infrastructure/efs-storage.j2 +++ b/terraform/aws/infrastructure/efs-storage.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### @@ -21,7 +21,9 @@ resource "aws_efs_file_system" "{{ specification.name }}" { {% endif %} tags = { - Name = "{{ specification.name }}" + cluster_name = "{{ specification.cluster_name }}" + cluster_version = "{{ version }}" + Name = "{{ specification.name }}" } } diff --git a/terraform/aws/infrastructure/internet-gateway.j2 b/terraform/aws/infrastructure/internet-gateway.j2 index 18db73db62..42286363e4 100644 --- a/terraform/aws/infrastructure/internet-gateway.j2 +++ b/terraform/aws/infrastructure/internet-gateway.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/aws/infrastructure/launch-configuration.j2 b/terraform/aws/infrastructure/launch-configuration.j2 deleted file mode 100644 index 0b5462f9a1..0000000000 --- a/terraform/aws/infrastructure/launch-configuration.j2 +++ /dev/null @@ -1,42 +0,0 @@ -##################################################### -# DO NOT Modify by hand - Managed by Automation -##################################################### -##################################################### -# This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline -# this approach provides an easier way to do creative looping, fetch IDs of created resources etc. -##################################################### -##################################################### -# {{ specification.name }} -##################################################### - -resource "aws_launch_configuration" "{{ specification.name }}" { - name = "{{ specification.name }}" - image_id = "{{ specification.image_id }}" - instance_type = "{{ specification.size }}" - associate_public_ip_address = "{{ specification.associate_public_ip | lower }}" - - # Security group - security_groups = [{% for security_group in specification.security_groups %}aws_security_group.{{ security_group }}.id{% if not loop.last %}, {% endif %}{% endfor %}] - enable_monitoring = "{{ specification.enable_monitoring | lower }}" - key_name = "{{ specification.key_name }}" - - ebs_optimized = "{{ specification.ebs_optimized | lower }}" - root_block_device { - volume_type = "{{ specification.disks.root.volume_type }}" - volume_size = "{{ specification.disks.root.volume_size }}" - delete_on_termination = "{{ specification.disks.root.delete_on_termination | lower }}" - encrypted = "{{ specification.disks.root.encrypted | lower }}" - } - -{% for disk in specification.disks.additional_disks %} - ebs_block_device { - device_name = "{{ disk.device_name }}" - volume_type = "{{ disk.volume_type }}" - volume_size = "{{ disk.volume_size }}" - encrypted = "{{ disk.encrypted | lower }}" - delete_on_termination = "{{ disk.delete_on_termination | lower }}" - } -{%- endfor %} - -} diff --git a/terraform/aws/infrastructure/public-key.j2 b/terraform/aws/infrastructure/public-key.j2 index de2b65182c..96028411ba 100644 --- a/terraform/aws/infrastructure/public-key.j2 +++ b/terraform/aws/infrastructure/public-key.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/aws/infrastructure/resource-group.j2 b/terraform/aws/infrastructure/resource-group.j2 index e8bc250119..f5c245d159 100644 --- a/terraform/aws/infrastructure/resource-group.j2 +++ b/terraform/aws/infrastructure/resource-group.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/aws/infrastructure/route-table-association.j2 b/terraform/aws/infrastructure/route-table-association.j2 index 635f6f5abc..9036f98986 100644 --- a/terraform/aws/infrastructure/route-table-association.j2 +++ b/terraform/aws/infrastructure/route-table-association.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/aws/infrastructure/route-table.j2 b/terraform/aws/infrastructure/route-table.j2 index c2c373f846..998684cebc 100644 --- a/terraform/aws/infrastructure/route-table.j2 +++ b/terraform/aws/infrastructure/route-table.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### @@ -18,8 +18,8 @@ resource "aws_route_table" "{{ specification.name }}" { } tags = { - Name = "web-table" cluster_name = "{{ specification.cluster_name }}" cluster_version = "{{ version }}" + Name = "{{ specification.name }}" } } diff --git a/terraform/aws/infrastructure/security-group-rule.j2 b/terraform/aws/infrastructure/security-group-rule.j2 index 0f8d83ad7f..2a205bac86 100644 --- a/terraform/aws/infrastructure/security-group-rule.j2 +++ b/terraform/aws/infrastructure/security-group-rule.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/aws/infrastructure/security-group.j2 b/terraform/aws/infrastructure/security-group.j2 index 7d9ded05a8..71b58bcd37 100644 --- a/terraform/aws/infrastructure/security-group.j2 +++ b/terraform/aws/infrastructure/security-group.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### @@ -17,6 +17,7 @@ resource "aws_security_group" "{{ specification.name }}" { tags = { cluster_name = "{{ specification.cluster_name }}" cluster_version = "{{ version }}" + Name = "{{ specification.name }}" } {% for rule in specification.rules %} {%- if rule.direction | lower in ["inbound", "ingress"] %} diff --git a/terraform/aws/infrastructure/subnet.j2 b/terraform/aws/infrastructure/subnet.j2 index 8dad89161d..af0bbeeecd 100644 --- a/terraform/aws/infrastructure/subnet.j2 +++ b/terraform/aws/infrastructure/subnet.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### @@ -13,7 +13,6 @@ resource "aws_subnet" "{{ specification.name }}" { vpc_id = aws_vpc.{{ specification.vpc_name }}.id cidr_block = "{{ specification.cidr_block }}" - availability_zone = "{{ specification.availability_zone }}" tags = { cluster_name = "{{ specification.cluster_name }}" diff --git a/terraform/aws/infrastructure/virtual-machine.j2 b/terraform/aws/infrastructure/virtual-machine.j2 index f464a68849..0a1821eafe 100644 --- a/terraform/aws/infrastructure/virtual-machine.j2 +++ b/terraform/aws/infrastructure/virtual-machine.j2 @@ -10,45 +10,50 @@ # {{ specification.name }} ##################################################### -resource "aws_autoscaling_group" "{{ specification.name }}" { - name = "{{ specification.name }}" - max_size = "{{ specification.count }}" - min_size = "{{ specification.count }}" - desired_capacity = "{{ specification.count }}" - force_delete = "true" - launch_configuration = aws_launch_configuration.{{ specification.launch_configuration }}.name +resource "aws_instance" "{{ specification.name }}" { + ami = "{{ specification.image_id }}" + instance_type = "{{ specification.size }}" + associate_public_ip_address = "{{ specification.associate_public_ip | lower }}" + key_name = "{{ specification.key_name }}" + subnet_id = aws_subnet.{{ specification.subnet_name }}.id + {%- if specification.use_network_security_groups == true %} + vpc_security_group_ids = [{% for security_group in specification.security_groups %}aws_security_group.{{ security_group }}.id{% if not loop.last %}, {% endif %}{% endfor %}] + {%- endif %} - vpc_zone_identifier = [ - {%- for name in specification.subnet_names %} - aws_subnet.{{ name }}.id, - {%- endfor %} - ] - - tag { - key = "cluster_name" - value = "{{ specification.cluster_name }}" - propagate_at_launch = "true" + # storage + ebs_optimized = "{{ specification.ebs_optimized | lower }}" + root_block_device { + volume_type = "{{ specification.disks.root.volume_type }}" + volume_size = "{{ specification.disks.root.volume_size }}" + delete_on_termination = "{{ specification.disks.root.delete_on_termination | lower }}" + encrypted = "{{ specification.disks.root.encrypted | lower }}" + tags = { + cluster_name = "{{ specification.cluster_name }}" + cluster_version = "{{ version }}" + Name = "{{ specification.name }}-os-disk" + } } - tag { - key = "cluster_version" - value = "{{ version }}" - propagate_at_launch = "true" - } +{% for disk in specification.disks.additional_disks %} + ebs_block_device { + device_name = "{{ disk.device_name }}" + volume_type = "{{ disk.volume_type }}" + volume_size = "{{ disk.volume_size }}" + encrypted = "{{ disk.encrypted | lower }}" + delete_on_termination = "{{ disk.delete_on_termination | lower }}" - tag { - key = "Name" - value = "{{ specification.name }}" - propagate_at_launch = "true" + tags = { + cluster_name = "{{ specification.cluster_name }}" + cluster_version = "{{ version }}" + Name = "{{ specification.name }}-data-disk-{{ loop.index0 }}" + } } +{%- endfor %} - {%- for tag in specification.tags %} - tag { - {%- for tag_key, tag_value in tag.items() %} - key = "{{ tag_key }}" - value = "{{ tag_value }}" - {%- endfor %} - propagate_at_launch = "true" + tags = { + cluster_name = "{{ specification.cluster_name }}" + cluster_version = "{{ version }}" + component_key = "{{ specification.component_key }}" + Name = "{{ specification.name }}" } - {%- endfor %} } diff --git a/terraform/aws/infrastructure/vpc.j2 b/terraform/aws/infrastructure/vpc.j2 index 5d893af7af..5ad4142d97 100644 --- a/terraform/aws/infrastructure/vpc.j2 +++ b/terraform/aws/infrastructure/vpc.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/epiphany-cluster.j2 b/terraform/azure/epiphany-cluster.j2 index a38391b2a5..1f17718f07 100644 --- a/terraform/azure/epiphany-cluster.j2 +++ b/terraform/azure/epiphany-cluster.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/availability-set.j2 b/terraform/azure/infrastructure/availability-set.j2 index 04924216da..3c55c63585 100644 --- a/terraform/azure/infrastructure/availability-set.j2 +++ b/terraform/azure/infrastructure/availability-set.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/network-interface-security-group-association.j2 b/terraform/azure/infrastructure/network-interface-security-group-association.j2 index af71e0c2ef..80dff42110 100644 --- a/terraform/azure/infrastructure/network-interface-security-group-association.j2 +++ b/terraform/azure/infrastructure/network-interface-security-group-association.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/network-interface.j2 b/terraform/azure/infrastructure/network-interface.j2 index 925de01ac8..ba6b824985 100644 --- a/terraform/azure/infrastructure/network-interface.j2 +++ b/terraform/azure/infrastructure/network-interface.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/network-security-group.j2 b/terraform/azure/infrastructure/network-security-group.j2 index 94ffbc97a2..411a6d9d6f 100644 --- a/terraform/azure/infrastructure/network-security-group.j2 +++ b/terraform/azure/infrastructure/network-security-group.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/public-ip.j2 b/terraform/azure/infrastructure/public-ip.j2 index be746d7ae5..dbe87e0a89 100644 --- a/terraform/azure/infrastructure/public-ip.j2 +++ b/terraform/azure/infrastructure/public-ip.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/resource-group.j2 b/terraform/azure/infrastructure/resource-group.j2 index 5cd2f55c65..f237963f9a 100644 --- a/terraform/azure/infrastructure/resource-group.j2 +++ b/terraform/azure/infrastructure/resource-group.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/storage-share.j2 b/terraform/azure/infrastructure/storage-share.j2 index e4cbe16db8..5e74605f34 100644 --- a/terraform/azure/infrastructure/storage-share.j2 +++ b/terraform/azure/infrastructure/storage-share.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/subnet-network-security-group-association.j2 b/terraform/azure/infrastructure/subnet-network-security-group-association.j2 index 1b4842edb2..a26701b0fb 100644 --- a/terraform/azure/infrastructure/subnet-network-security-group-association.j2 +++ b/terraform/azure/infrastructure/subnet-network-security-group-association.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/subnet.j2 b/terraform/azure/infrastructure/subnet.j2 index 9c12989db2..9738f9443b 100644 --- a/terraform/azure/infrastructure/subnet.j2 +++ b/terraform/azure/infrastructure/subnet.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/virtual-machine.j2 b/terraform/azure/infrastructure/virtual-machine.j2 index 3d8f22316b..dec4e7eb8b 100644 --- a/terraform/azure/infrastructure/virtual-machine.j2 +++ b/terraform/azure/infrastructure/virtual-machine.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/terraform/azure/infrastructure/vnet.j2 b/terraform/azure/infrastructure/vnet.j2 index 2e8d7b685d..c8ecbc4a02 100644 --- a/terraform/azure/infrastructure/vnet.j2 +++ b/terraform/azure/infrastructure/vnet.j2 @@ -3,7 +3,7 @@ ##################################################### ##################################################### # This file can be used as a base template to build other Terraform files. It attempts to use as much -# Terraform interprolation as possible by creating Terraform variables instead of changing inline +# Terraform interpolation as possible by creating Terraform variables instead of changing inline # this approach provides an easier way to do creative looping, fetch IDs of created resources etc. ##################################################### ##################################################### diff --git a/tests/unit/engine/providers/aws/test_APIProxy.py b/tests/unit/engine/providers/aws/test_APIProxy.py new file mode 100644 index 0000000000..27c8adb46b --- /dev/null +++ b/tests/unit/engine/providers/aws/test_APIProxy.py @@ -0,0 +1,31 @@ +from pytest_mock import MockerFixture + +from cli.engine.providers.aws.APIProxy import APIProxy +from cli.models.AnsibleHostModel import AnsibleOrderedHostModel +from tests.unit.engine.providers.data.APIProxy_data import CLUSTER_MODEL, RUNNING_INSTANCES_AWS + + +def test_get_ips_for_feature(mocker: MockerFixture): + """ + Make sure that hostnames in inventory are sorted. + """ + + mocker.patch('cli.engine.providers.azure.APIProxy.Log') + mocker.patch('boto3.session.Session') + + # mock proxy with prepared data + proxy = APIProxy(CLUSTER_MODEL('aws'), []) + proxy.get_vpc_id = (lambda *args: 'vpc_id') + proxy.session.resource('ec2').instances.filter = (lambda Filters = []: RUNNING_INSTANCES_AWS) + + EXPECTED_RESULT = [ + AnsibleOrderedHostModel('prefix-cluster-service-vm-0', '20.73.105.240'), + AnsibleOrderedHostModel('prefix-cluster-service-vm-1', '20.73.105.188'), + AnsibleOrderedHostModel('prefix-cluster-service-vm-2', '20.73.105.18'), + AnsibleOrderedHostModel('prefix-cluster-service-vm-3', '20.73.105.33'), + AnsibleOrderedHostModel('prefix-cluster-service-vm-4', '20.73.105.54') + ] + + result = proxy.get_ips_for_feature('service') + + assert EXPECTED_RESULT == result diff --git a/tests/unit/engine/providers/aws/test_AWSConfigBuilder.py b/tests/unit/engine/providers/aws/test_AWSConfigBuilder.py index 1afc366256..93eff3cad7 100644 --- a/tests/unit/engine/providers/aws/test_AWSConfigBuilder.py +++ b/tests/unit/engine/providers/aws/test_AWSConfigBuilder.py @@ -36,7 +36,7 @@ def test_get_default_security_group_config_should_set_proper_values_to_model(): def test_get_efs_config_should_set_proper_values_to_model(): - cluster_model = get_cluster_model(cluster_name='TestCluster', address_pool='10.20.0.0/22') + cluster_model = get_cluster_model(cluster_name='TestCluster', address_pool='10.20.0.0/22') builder = InfrastructureBuilder([cluster_model]) actual = builder.get_efs_config() @@ -45,70 +45,10 @@ def test_get_efs_config_should_set_proper_values_to_model(): assert actual.specification.name == 'prefix-testcluster-efs' -def test_get_autoscaling_group_should_set_proper_values_to_model(): - cluster_model = get_cluster_model(cluster_name='TestCluster') - component_value = dict_to_objdict({ - 'machine': 'default', - 'count': 4 - }) - subnets = [ - dict_to_objdict({'specification': { - 'name': 'subnet1', - 'availability_zone': 'availabilityzone1' - }}), - dict_to_objdict({'specification': { - 'name': 'subnet2', - 'availability_zone': 'availabilityzone2' - }}) - ] - - builder = InfrastructureBuilder([cluster_model]) - - actual = builder.get_autoscaling_group('TestComponent', component_value, subnets, 1) - - assert actual.specification.cluster_name == 'testcluster' - assert actual.specification.name == 'prefix-testcluster-testcomponent-asg-1' - assert actual.specification.count == 4 - assert actual.specification.subnet_names == ['subnet1', 'subnet2'] - assert actual.specification.availability_zones == ['availabilityzone1', 'availabilityzone2'] - assert {'cluster_name': 'testcluster'} in actual.specification.tags - assert {'TestComponent': ''} in actual.specification.tags - - -def test_get_launch_configuration_should_set_proper_values_to_model(): - cluster_model = get_cluster_model(cluster_name='TestCluster') - autoscaling_group = dict_to_objdict({ - 'specification': { - 'size': 't2.micro.test', - 'disks': [], - 'ebs_optimized': True - } - }) - security_groups_to_create = [ - dict_to_objdict({'specification': { - 'name': 'aws-security-group-test1', - }}), - dict_to_objdict({'specification': { - 'name': 'aws-security-group-test2', - }}) - ] - builder = InfrastructureBuilder([cluster_model]) - - actual = builder.get_launch_configuration(autoscaling_group, 'TestComponent', security_groups_to_create) - - assert actual.specification.name == 'prefix-testcluster-testcomponent-launch-config' - assert actual.specification.size == 't2.micro.test' - assert actual.specification.security_groups == ['aws-security-group-test1', 'aws-security-group-test2'] - assert actual.specification.disks == [] - assert actual.specification.ebs_optimized is True - assert actual.specification.associate_public_ip is True - - def test_get_subnet_config_should_set_proper_values_to_model(): cluster_model = get_cluster_model(cluster_name='TestCluster') component_value = dict_to_objdict({ - 'address_pool': '10.20.0.0/24', - 'availability_zone': 'eu-west-2a' + 'address_pool': '10.20.0.0/24' }) builder = InfrastructureBuilder([cluster_model]) @@ -117,7 +57,6 @@ def test_get_subnet_config_should_set_proper_values_to_model(): assert actual.specification.name == 'prefix-testcluster-component-subnet-1' assert actual.specification.vpc_name == 'my-test-vpc' assert actual.specification.cidr_block == '10.20.0.0/24' - assert actual.specification.availability_zone == 'eu-west-2a' def test_get_security_group_should_set_proper_values_to_model(): @@ -188,4 +127,3 @@ def get_cluster_model(address_pool='10.22.0.0/22', cluster_name='EpiphanyTestClu } }) return cluster_model - diff --git a/tests/unit/engine/providers/azure/test_AzureConfigBuilder.py b/tests/unit/engine/providers/azure/test_AzureConfigBuilder.py index 7805b85d15..b884b1adba 100644 --- a/tests/unit/engine/providers/azure/test_AzureConfigBuilder.py +++ b/tests/unit/engine/providers/azure/test_AzureConfigBuilder.py @@ -34,8 +34,7 @@ def test_get_network_security_group_should_set_proper_values_to_model(): def test_get_subnet_should_set_proper_values_to_model(): cluster_model = get_cluster_model(cluster_name='TestCluster') subnet_definition = dict_to_objdict({ - 'address_pool': '10.20.0.0/24', - 'availability_zone': 'eu-west-2a' + 'address_pool': '10.20.0.0/24' }) builder = InfrastructureBuilder([cluster_model]) actual = builder.get_subnet(subnet_definition, 'component', 1) diff --git a/tests/unit/engine/providers/data/APIProxy_data.py b/tests/unit/engine/providers/data/APIProxy_data.py index 29a110d72e..d1b73c8b95 100644 --- a/tests/unit/engine/providers/data/APIProxy_data.py +++ b/tests/unit/engine/providers/data/APIProxy_data.py @@ -86,7 +86,11 @@ def CLUSTER_MODEL(provider: str) -> ObjDict: 'region': 'West Europe', 'network': {'use_network_security_groups': True}, 'default_os_image': 'default', - 'hostname_domain_extension': '' + 'hostname_domain_extension': '', + 'credentials': { + 'key': 'key', + 'secret': 'secret' + } }, 'components': { 'service': { @@ -192,3 +196,21 @@ def CLUSTER_MODEL(provider: str) -> ObjDict: } ] ] + +class AWSMockInstance: + def __init__(self, name, ip): + self.tags = [] + self.tags.append({ + 'Key': 'Name', + 'Value': name, + }) + self.private_ip_address = ip + self.public_ip_address = ip + +RUNNING_INSTANCES_AWS: List[Dict] = [ + AWSMockInstance('prefix-cluster-service-vm-4', '20.73.105.54'), + AWSMockInstance('prefix-cluster-service-vm-1', '20.73.105.188'), + AWSMockInstance('prefix-cluster-service-vm-3', '20.73.105.33'), + AWSMockInstance('prefix-cluster-service-vm-0', '20.73.105.240'), + AWSMockInstance('prefix-cluster-service-vm-2', '20.73.105.18') +]