From 5e14b84626652c506843a38e6b5d0a917a05ad05 Mon Sep 17 00:00:00 2001 From: Anurag Sharma Date: Mon, 21 Oct 2024 18:12:39 +0530 Subject: [PATCH] Added ResourceRequirements, VolumeAttachments models in AWS EG --- CHANGELOG.md | 5 ++ .../elastigroup/elastigroup_aws_client.md | 34 +++++-- docs/models/elastigroup/aws.md | 89 ++++++++++++++++++- spotinst_sdk2/clients/elastigroup/__init__.py | 51 +++++++++-- .../models/elastigroup/aws/__init__.py | 85 +++++++++++++++++- spotinst_sdk2/models/elastigroup/aws/asg.py | 34 ++++++- spotinst_sdk2/version.py | 2 +- 7 files changed, 282 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfaf1019..c3c2a565 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [3.16.0] - 2024-10-21 +### Added +- Import EC2 instance API support added in the AWS Elastigroup Client. +- Added `VolumeAttachments` and `ResourceRequirements` models for AWS Elastigroup. + ## [3.15.1] - 2024-09-19 ### Fixed - Create/Update rightsizing rule APIs fixed for optional parameters. diff --git a/docs/clients/elastigroup/elastigroup_aws_client.md b/docs/clients/elastigroup/elastigroup_aws_client.md index c1259abe..33f3131c 100644 --- a/docs/clients/elastigroup/elastigroup_aws_client.md +++ b/docs/clients/elastigroup/elastigroup_aws_client.md @@ -580,7 +580,8 @@ ElastigroupAwsClient.beanstalk_import(region, env_name=None) ``` -Import beanstalk attributes into JSON. Either env_id or env_name is required, both cannot be null +Import beanstalk attributes into JSON. Either env_id or env_name is +required, both cannot be null __Arguments__ @@ -608,13 +609,35 @@ __Returns__ `(Object)`: Elastigroup API response +

import_instance

+ +```python +ElastigroupAwsClient.import_instance(region, instance_id, + instance: ImportInstanceConfig) +``` + +Import an EC2 instance into a new Elastigroup + +__Arguments__ + +- __region (String)__: Instance Region +- __instance_id (String)__: Instance ID +- __instance (ImportInstanceConfig)__: Import Configuration + +__Returns__ + +`(Object)`: Elastigroup API response +

import_asg

```python -ElastigroupAwsClient.import_asg(region, asg_name, asg, dry_run=None) +ElastigroupAwsClient.import_asg(region, + asg_name, + asg: ASG, + dry_run=None) ``` -import asg attributes as JSON +Create a new Elastigroup using the configuration of an existing Autoscaling group __Arguments__ @@ -886,8 +909,9 @@ __Arguments__ - __group_id(String)__: Elastigroup ID - __to_date (String)__: to date - __from_date (String)__: to date -- __severity(String) (Optional)__: Log level severity -- __resource_id(String) (Optional)__: Filter log extracted entires related to a specific resource id +- __severity (String) (Optional)__: Log level severity +- __resource_id (String) (Optional)__: Filter log extracted entires related to a + specific resource id - __limit(String) (Optional)__: Maximum number of lines to extract in a response __Returns__ diff --git a/docs/models/elastigroup/aws.md b/docs/models/elastigroup/aws.md index 09cc33c1..8b71e066 100644 --- a/docs/models/elastigroup/aws.md +++ b/docs/models/elastigroup/aws.md @@ -35,10 +35,12 @@ __Arguments__ Strategy( self, availability_vs_cost='d3043820717d74d9a17694c176d39733', + consider_o_d_pricing='d3043820717d74d9a17694c176d39733', risk='d3043820717d74d9a17694c176d39733', utilize_commitments='d3043820717d74d9a17694c176d39733', utilize_reserved_instances='d3043820717d74d9a17694c176d39733', fallback_to_od='d3043820717d74d9a17694c176d39733', + max_replacements_percentage='d3043820717d74d9a17694c176d39733', on_demand_count='d3043820717d74d9a17694c176d39733', draining_timeout='d3043820717d74d9a17694c176d39733', spin_up_time='d3043820717d74d9a17694c176d39733', @@ -54,10 +56,12 @@ Strategy( __Arguments__ - __availability_vs_cost__: str +- __consider_o_d_pricing__: bool - __risk__: int - __utilize_commitments__: bool - __utilize_reserved_instances__: bool - __fallback_to_od__: bool +- __max_replacements_percentage__: int - __on_demand_count__: int - __draining_timeout__: int - __spin_up_time__: int @@ -67,6 +71,7 @@ __Arguments__ - __persistence__: Persistence - __revert_to_spot__: RevertToSpot - __restrict_single_az__: bool +- __immediate_o_d_recover_threshold__: int

Signal

@@ -941,7 +946,8 @@ Compute(self, elastic_ips='d3043820717d74d9a17694c176d39733', private_ips='d3043820717d74d9a17694c176d39733', subnet_ids='d3043820717d74d9a17694c176d39733', - preferred_availability_zones='d3043820717d74d9a17694c176d39733') + preferred_availability_zones='d3043820717d74d9a17694c176d39733', + volume_attachments='d3043820717d74d9a17694c176d39733') ``` __Arguments__ @@ -954,6 +960,7 @@ __Arguments__ - __private_ips__: list[str] - __subnet_ids__: list[str] - __preferred_availability_zones__: list[str] +- __volume_attachments__: VolumeAttachments

AvailabilityZone

@@ -981,7 +988,8 @@ InstanceTypes(self, on_demand_types='d3043820717d74d9a17694c176d39733', spot='d3043820717d74d9a17694c176d39733', weights='d3043820717d74d9a17694c176d39733', - preferred_spot='d3043820717d74d9a17694c176d39733') + preferred_spot='d3043820717d74d9a17694c176d39733', + resource_requirements='d3043820717d74d9a17694c176d39733') ``` __Arguments__ @@ -991,6 +999,29 @@ __Arguments__ - __spot__: list[str] - __weights__: list[Weight] - __preferred_spot__: list[str] +- __resource_requirements__: ResourceRequirements + +

ResourceRequirements

+ +```python +ResourceRequirements( + self, + excluded_instance_families='d3043820717d74d9a17694c176d39733', + excluded_instance_generations='d3043820717d74d9a17694c176d39733', + excluded_instance_types='d3043820717d74d9a17694c176d39733', + required_v_cpu='d3043820717d74d9a17694c176d39733', + required_memory='d3043820717d74d9a17694c176d39733', + required_gpu='d3043820717d74d9a17694c176d39733') +``` + +__Arguments__ + +- __excluded_instance_families__: list[str] +- __excluded_instance_generations__: list[str] +- __excluded_instance_types__: list[str] +- __required_v_cpu__: RequiredMemoryVcpuGpu +- __required_memory__: RequiredMemoryVcpuGpu +- __required_gpu__: RequiredMemoryVcpuGpu

Weight

@@ -1005,6 +1036,19 @@ __Arguments__ - __instance_type__: str - __weighted_capacity__: int +

RequiredMemoryVcpuGpu

+ +```python +RequiredMemoryVcpuGpu(self, + minimum='d3043820717d74d9a17694c176d39733', + maximum='d3043820717d74d9a17694c176d39733') +``` + +__Arguments__ + +- __minimum__: int +- __maximum__: int +

TagSpecification

```python @@ -1292,6 +1336,29 @@ __Arguments__ - __http_tokens__: str - __instance_metadata_tags__: str +

VolumeAttachments

+ +```python +VolumeAttachments(self, volumes='d3043820717d74d9a17694c176d39733') +``` + +__Arguments__ + +- __volumes__: list[Volume] + +

Volume

+ +```python +Volume(self, + device_name='d3043820717d74d9a17694c176d39733', + volume_id='d3043820717d74d9a17694c176d39733') +``` + +__Arguments__ + +- __device_name__: str +- __volume_id__: str +

Roll

```python @@ -1392,12 +1459,28 @@ __Arguments__ ASG(self, product='d3043820717d74d9a17694c176d39733', spot_instance_types='d3043820717d74d9a17694c176d39733', - name='d3043820717d74d9a17694c176d39733') + name='d3043820717d74d9a17694c176d39733', + availability_vs_cost='d3043820717d74d9a17694c176d39733') ``` __Arguments__ - __product__: str +- __spot_instance_types__: List[str] +- __name__: str +- __availability_vs_cost__: str + +

ImportInstanceConfig

+ +```python +ImportInstanceConfig( + self, + spot_instance_types='d3043820717d74d9a17694c176d39733', + name='d3043820717d74d9a17694c176d39733') +``` + +__Arguments__ + - __spot_instance_types__: List[str] - __name__: str diff --git a/spotinst_sdk2/clients/elastigroup/__init__.py b/spotinst_sdk2/clients/elastigroup/__init__.py index 6c7c3263..34390778 100644 --- a/spotinst_sdk2/clients/elastigroup/__init__.py +++ b/spotinst_sdk2/clients/elastigroup/__init__.py @@ -7,7 +7,7 @@ import spotinst_sdk2.models.elastigroup.aws.stateful as aws_stateful import spotinst_sdk2.models.elastigroup.aws.deployment as aws_deployment import spotinst_sdk2.models.elastigroup.aws.deployment_action as aws_deployment_action -import spotinst_sdk2.models.elastigroup.aws.asg as aws_asg +import spotinst_sdk2.models.elastigroup.aws.asg as aws_import # endregion # region GCP imports @@ -931,9 +931,48 @@ def beanstalk_reimport(self, group_id): return ret_val - def import_asg(self, region, asg_name, asg, dry_run=None): + def import_instance(self, region, instance_id, instance: aws_import.ImportInstanceConfig): """ - import asg attributes as JSON + Import an EC2 instance into a new Elastigroup + + # Arguments + region (String): Instance Region + instance_id (String): Instance ID + instance (ImportInstanceConfig): Import Configuration + + # Returns + (Object): Elastigroup API response + """ + query_params = dict( + region=region, instanceId=instance_id) + + request = aws_import.ImportInstanceRequest(instance) + + excluded_group_dict = self.exclude_missing( + json.loads(request.toJSON())) + + formatted_group_dict = self.convert_json( + excluded_group_dict, self.underscore_to_camel) + + body_json = json.dumps(formatted_group_dict) + + response = self.send_post( + body=body_json, + url=self.__base_elastigroup_url + + "/instance/import", + query_params=query_params, + entity_name='import instance') + + formatted_response = self.convert_json( + response, self.camel_to_underscore) + + ret_val = formatted_response["response"]["items"][0] + + return ret_val + + def import_asg(self, region, asg_name, asg: aws_import.ASG, dry_run=None): + """ + Create a new Elastigroup using the configuration of an existing Autoscaling group # Arguments region (String): ASG region @@ -947,7 +986,7 @@ def import_asg(self, region, asg_name, asg, dry_run=None): query_params = dict( region=region, autoScalingGroupName=asg_name, dryRun=dry_run) - asg = aws_asg.ImportASGRequest(asg) + asg = aws_import.ImportASGRequest(asg) excluded_group_dict = self.exclude_missing(json.loads(asg.toJSON())) @@ -1343,8 +1382,8 @@ def get_elastilog(self, group_id, from_date, to_date, severity=None, resource_id group_id(String): Elastigroup ID to_date (String): to date from_date (String): to date - severity(String) (Optional): Log level severity - resource_id(String) (Optional): Filter log extracted entires related to a + severity (String) (Optional): Log level severity + resource_id (String) (Optional): Filter log extracted entires related to a specific resource id limit(String) (Optional): Maximum number of lines to extract in a response diff --git a/spotinst_sdk2/models/elastigroup/aws/__init__.py b/spotinst_sdk2/models/elastigroup/aws/__init__.py index eeae189e..b4b0ff99 100755 --- a/spotinst_sdk2/models/elastigroup/aws/__init__.py +++ b/spotinst_sdk2/models/elastigroup/aws/__init__.py @@ -48,10 +48,12 @@ class Strategy: """ # Arguments availability_vs_cost: str + consider_o_d_pricing: bool risk: int utilize_commitments: bool utilize_reserved_instances: bool fallback_to_od: bool + max_replacements_percentage: int on_demand_count: int draining_timeout: int spin_up_time: int @@ -61,15 +63,18 @@ class Strategy: persistence: Persistence revert_to_spot: RevertToSpot restrict_single_az: bool + immediate_o_d_recover_threshold: int """ def __init__( self, availability_vs_cost=none, + consider_o_d_pricing=none, risk=none, utilize_commitments=none, utilize_reserved_instances=none, fallback_to_od=none, + max_replacements_percentage=none, on_demand_count=none, draining_timeout=none, spin_up_time=none, @@ -82,9 +87,11 @@ def __init__( restrict_single_az: bool = none): self.risk = risk + self.consider_o_d_pricing = consider_o_d_pricing self.utilize_commitments = utilize_commitments self.utilize_reserved_instances = utilize_reserved_instances self.fallback_to_od = fallback_to_od + self.max_replacements_percentage = max_replacements_percentage self.on_demand_count = on_demand_count self.availability_vs_cost = availability_vs_cost self.draining_timeout = draining_timeout @@ -1105,6 +1112,7 @@ class Compute: private_ips: list[str] subnet_ids: list[str] preferred_availability_zones: list[str] + volume_attachments: VolumeAttachments """ def __init__( @@ -1116,7 +1124,8 @@ def __init__( elastic_ips=none, private_ips=none, subnet_ids=none, - preferred_availability_zones=none): + preferred_availability_zones=none, + volume_attachments=none): self.elastic_ips = elastic_ips self.private_ips = private_ips @@ -1126,6 +1135,7 @@ def __init__( self.product = product self.launch_specification = launch_specification self.preferred_availability_zones = preferred_availability_zones + self.volume_attachments = volume_attachments class AvailabilityZone: @@ -1158,6 +1168,7 @@ class InstanceTypes: spot: list[str] weights: list[Weight] preferred_spot: list[str] + resource_requirements: ResourceRequirements """ def __init__( @@ -1166,13 +1177,43 @@ def __init__( on_demand_types=none, spot=none, weights=none, - preferred_spot=none): + preferred_spot=none, + resource_requirements=none): self.ondemand = ondemand self.on_demand_types = on_demand_types self.spot = spot self.weights = weights self.preferred_spot = preferred_spot + self.resource_requirements = resource_requirements + + +class ResourceRequirements: + """ + # Arguments + excluded_instance_families: list[str] + excluded_instance_generations: list[str] + excluded_instance_types: list[str] + required_v_cpu: RequiredMemoryVcpuGpu + required_memory: RequiredMemoryVcpuGpu + required_gpu: RequiredMemoryVcpuGpu + """ + + def __init__( + self, + excluded_instance_families=none, + excluded_instance_generations=none, + excluded_instance_types=none, + required_v_cpu=none, + required_memory=none, + required_gpu=none): + + self.excluded_instance_families = excluded_instance_families + self.excluded_instance_generations = excluded_instance_generations + self.excluded_instance_types = excluded_instance_types + self.required_v_cpu = required_v_cpu + self.required_memory = required_memory + self.required_gpu = required_gpu class Weight: @@ -1188,6 +1229,19 @@ def __init__(self, instance_type=none, weighted_capacity=none): self.weighted_capacity = weighted_capacity +class RequiredMemoryVcpuGpu: + """ + # Arguments + minimum: int + maximum: int + """ + + def __init__(self, minimum=none, maximum=none): + + self.minimum = minimum + self.maximum = maximum + + class TagSpecification: """ # Arguments @@ -1535,6 +1589,33 @@ def __init__(self, self.http_tokens = http_tokens self.instance_metadata_tags = instance_metadata_tags + +class VolumeAttachments: + """ + # Arguments + volumes: list[Volume] + """ + + def __init__(self, + volumes=none): + + self.volumes = volumes + + +class Volume: + """ + # Arguments + device_name: str + volume_id: str + """ + + def __init__(self, + device_name=none, + volume_id=none): + + self.device_name = device_name + self.volume_id = volume_id + # endregion diff --git a/spotinst_sdk2/models/elastigroup/aws/asg.py b/spotinst_sdk2/models/elastigroup/aws/asg.py index b52b4e44..4582a3d0 100644 --- a/spotinst_sdk2/models/elastigroup/aws/asg.py +++ b/spotinst_sdk2/models/elastigroup/aws/asg.py @@ -11,17 +11,40 @@ class ASG: product: str spot_instance_types: List[str] name: str + availability_vs_cost: str """ def __init__( self, product=none, spot_instance_types=none, - name=none): + name=none, + availability_vs_cost=none): self.product = product self.spot_instance_types = spot_instance_types self.name = name + self.availability_vs_cost = availability_vs_cost + +# endregion + +# region Instance + + +class ImportInstanceConfig: + """ + # Arguments + spot_instance_types: List[str] + name: str + """ + + def __init__( + self, + spot_instance_types=none, + name=none): + + self.spot_instance_types = spot_instance_types + self.name = name # endregion @@ -33,3 +56,12 @@ def __init__(self, group): def toJSON(self): return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4) + + +class ImportInstanceRequest: + def __init__(self, group): + self.group = group + + def toJSON(self): + return json.dumps(self, default=lambda o: o.__dict__, + sort_keys=True, indent=4) diff --git a/spotinst_sdk2/version.py b/spotinst_sdk2/version.py index f3bb9e91..0c9d57a9 100644 --- a/spotinst_sdk2/version.py +++ b/spotinst_sdk2/version.py @@ -1 +1 @@ -__version__ = '3.15.1' +__version__ = '3.16.0'