def get_client(module): # Retrieve creds file variables creds_file_loaded_vars = dict() credentials_path = module.params.get('credentials_path') if credentials_path is not None: try: with open(credentials_path, "r") as creds: for line in creds: eq_index = line.find('=') var_name = line[:eq_index].strip() string_value = line[eq_index + 1:].strip() creds_file_loaded_vars[var_name] = string_value except IOError: pass # End of creds file retrieval token = module.params.get('token') if not token: token = creds_file_loaded_vars.get("token") account = module.params.get('account_id') if not account: account = creds_file_loaded_vars.get("account") client = spotinst.SpotinstClient(auth_token=token, print_output=False) if account is not None: client = spotinst.SpotinstClient(auth_token=token, account_id=account, print_output=False) return client
def launcher(api_token, account_id, group_id, app_name, deployment_group_name, timeout, github_repo, commit_id): unique_id = get_uuid()[2:-1] spot_client = spotinst_sdk.SpotinstClient(auth_token=api_token, account_id=account_id) green_tag = spotinst_blue_green_deployment.Tag() green_tag.tag_key = 'GreenIdentifier' green_tag.tag_value = unique_id deployment_group = spotinst_blue_green_deployment.DeploymentGroup() deployment_group.deployment_group_name = deployment_group_name deployment_group.application_name = app_name deployment = spotinst_blue_green_deployment.BlueGreenDeployment( tags=[green_tag], deployment_groups=[deployment_group], timeout=timeout) pre_deployment_count = len( spot_client.get_elastigroup_active_instances(group_id)) spot_client.create_blue_green_deployment(group_id, deployment) git_loc = gitHubLocation(github_repo, commit_id) revision = Revision('GitHub', git_loc) tags = Tags(Key='GreenIdentifier', Value=unique_id, Type='KEY_AND_VALUE') tag_filters = tagFilters([tags]) bg = BlueGreenDeployment(applicationName=app_name, deploymentGroupName=deployment_group_name, revision=revision, targetInstances=tag_filters) post_deployment_count = 0 while pre_deployment_count > post_deployment_count: print('Waiting for Green Deployment Instances') time.sleep(30) post_deployment_count = len( spot_client.get_elastigroup_active_instances(group_id)) print('Waiting for Green Deployment Instances Readiness') wait_ec2readiness(tags) codedeploy_client = boto3.client('codedeploy') codedeploy_client.create_deployment( applicationName=bg.applicationName, deploymentGroupName=bg.deploymentGroupName, revision=todict(bg.revision), targetInstances=todict(bg.targetInstances)) spot_deployment_state = spot_client.get_blue_green_deployment(group_id) print("Launcher function complete")
def connection(token_type): ''' Initialize connection with Spotinst API ''' try: account = netrc.netrc().authenticators(token_type)[0] token = netrc.netrc().authenticators(token_type)[2] except: netrc.NetrcParseError( "No authenticators for %s" %token_type) print ("Can't find .netrc file. Exiting") sys.exit(1) spotinst_client = spotinst_sdk.SpotinstClient(auth_token=token, account_id=account) return spotinst_client
def main(): fields = dict( account_id=dict(type='str'), availability_vs_cost=dict(type='str', required=True), availability_zones=dict(type='list', required=True), block_device_mappings=dict(type='list'), chef=dict(type='dict'), credentials_path=dict(type='path', default="~/.spotinst/credentials"), do_not_update=dict(default=[], type='list'), down_scaling_policies=dict(type='list'), draining_timeout=dict(type='int'), ebs_optimized=dict(type='bool'), ebs_volume_pool=dict(type='list'), ecs=dict(type='dict'), elastic_beanstalk=dict(type='dict'), elastic_ips=dict(type='list'), fallback_to_od=dict(type='bool'), id=dict(type='str'), health_check_grace_period=dict(type='int'), health_check_type=dict(type='str'), health_check_unhealthy_duration_before_replacement=dict(type='int'), iam_role_arn=dict(type='str'), iam_role_name=dict(type='str'), image_id=dict(type='str', required=True), key_pair=dict(type='str'), kubernetes=dict(type='dict'), lifetime_period=dict(type='int'), load_balancers=dict(type='list'), max_size=dict(type='int', required=True), mesosphere=dict(type='dict'), min_size=dict(type='int', required=True), monitoring=dict(type='str'), multai_load_balancers=dict(type='list'), multai_token=dict(type='str'), name=dict(type='str', required=True), network_interfaces=dict(type='list'), on_demand_count=dict(type='int'), on_demand_instance_type=dict(type='str'), opsworks=dict(type='dict'), persistence=dict(type='dict'), product=dict(type='str', required=True), rancher=dict(type='dict'), right_scale=dict(type='dict'), risk=dict(type='int'), roll_config=dict(type='dict'), scheduled_tasks=dict(type='list'), security_group_ids=dict(type='list', required=True), shutdown_script=dict(type='str'), signals=dict(type='list'), spin_up_time=dict(type='int'), spot_instance_types=dict(type='list', required=True), state=dict(default='present', choices=['present', 'absent']), tags=dict(type='list'), target=dict(type='int', required=True), target_group_arns=dict(type='list'), tenancy=dict(type='str'), terminate_at_end_of_billing_hour=dict(type='bool'), token=dict(type='str'), unit=dict(type='str'), user_data=dict(type='str'), utilize_reserved_instances=dict(type='bool'), uniqueness_by=dict(default='name', choices=['name', 'id']), up_scaling_policies=dict(type='list'), target_tracking_policies=dict(type='list'), wait_for_instances=dict(type='bool', default=False), wait_timeout=dict(type='int')) module = AnsibleModule(argument_spec=fields) if not HAS_SPOTINST_SDK: module.fail_json( msg= "the Spotinst SDK library is required. (pip install spotinst_sdk)") # Retrieve creds file variables creds_file_loaded_vars = dict() credentials_path = module.params.get('credentials_path') try: with open(credentials_path, "r") as creds: for line in creds: eq_index = line.find('=') var_name = line[:eq_index].strip() string_value = line[eq_index + 1:].strip() creds_file_loaded_vars[var_name] = string_value except IOError: pass # End of creds file retrieval token = module.params.get('token') if not token: token = os.environ.get('SPOTINST_TOKEN') if not token: token = creds_file_loaded_vars.get("token") account = module.params.get('account_id') if not account: account = os.environ.get('SPOTINST_ACCOUNT_ID') or os.environ.get( 'ACCOUNT') if not account: account = creds_file_loaded_vars.get("account") client = spotinst.SpotinstClient(auth_token=token, print_output=False) if account is not None: client = spotinst.SpotinstClient(auth_token=token, print_output=False, account_id=account) group_id, message, has_changed = handle_elastigroup(client=client, module=module) instances = retrieve_group_instances(client=client, module=module, group_id=group_id) module.exit_json(changed=has_changed, group_id=group_id, message=message, instances=instances)
def main(): ''' Apply functions based on the given arguments. ''' spotinst_parser = argparse.ArgumentParser( description=''' ** Managing Spotinst Elastigroup actions ** ''', epilog='Author: Aris Boutselis <*****@*****.**>') spotinst_parser.add_argument('--type','-t', action='store', dest='type', required=True, help='Type of the Organization, two possible \ values are magento, launches. This argument \ is required. e.g spotinst -t magento .') spotinst_parser.add_argument('--list','-l', action='store', dest='id', help='Show information about a single or all Elastigroups \ of the organization e.g spotinst -t magento --list all.') spotinst_parser.add_argument('--scaleup', action='store',dest='uparg',nargs=2, help='Scale up a number of instances for a given Elastigroup. \ Note: we heavily use autoscaling groups, scaling is done based on asg policy. \ e.g --scaleup <group_id> <number> .') spotinst_parser.add_argument('--scaledown', action='store',dest='downarg',nargs=2, help='Scale down a number of instances for a given \ Elastigroup. Note: we heavily use autoscaling groups,\ scaling is done based on asg policy. e.g --scaledown <group_id> <number> .') spotinst_parser.add_argument('--capacity',action='store',dest='caparg',nargs=4, help= 'Update capacity values for a given Elastigroup. \ e.g --capacity <group_id> <min> <max> <target> .') spotinst_parser.add_argument('--deploy','-d',action='store',dest='deparg',nargs=3, help= 'Roll new instances in a single Elastigroup. \ e.g --deploy <group_id> <batch_percentage> <grace_period>.') spotinst_parser.add_argument('--pipelines', action='store',dest='bbpipelines',nargs=2, help= 'Used only inside Bitbucket pipelines. This argument bypasses netrc auth mechanism \ e.g --pipelines <spotinst_account> <spotinst_account_token>.') spotinst_results = spotinst_parser.parse_args() # get the type to extract the appropriate account id and token type_values = ['magento','launches'] #Be sure that token type is specified, --type <launches|magento> if spotinst_results.type in type_values and len(sys.argv) > 4: # if this script is used in Bitbucket pipelines, will try to # authenticate via Bitbucket ENV variables for the account and token values if spotinst_results.bbpipelines: account = spotinst_results.bbpipelines[0] token = spotinst_results.bbpipelines[1] spotinst_client = spotinst_sdk.SpotinstClient(auth_token=token, account_id=account) else: token_type = spotinst_results.type+'-token' spotinst_client = connection(token_type) # --scaleup if spotinst_results.uparg: if "sig-" in spotinst_results.uparg[0] and len(spotinst_results.uparg[1]) <= 2: scaleup(spotinst_client,spotinst_results.uparg[0],spotinst_results.uparg[1]) else: print ("\n[ERROR] Wrong arguments for scale up function.Exiting...\n" ,spotinst_parser.print_help()) sys.exit(1) # --scaledown if spotinst_results.downarg: if "sig-" in spotinst_results.downarg[0] and len(spotinst_results.downarg[1]) <= 2: scaledown(spotinst_client,spotinst_results.downarg[0],spotinst_results.downarg[1]) else: print ("\n[ERROR] Wrong arguments for scale down function.Exiting...\n",spotinst_parser.print_help()) sys.exit(1) # --capacity X X X X if spotinst_results.caparg: oldtarget = showid(spotinst_results.caparg[0], spotinst_client)[1] oldmin = showid(spotinst_results.caparg[0], spotinst_client)[2] oldmax = showid(spotinst_results.caparg[0], spotinst_client)[3] print ("Existing Capacity is min: %s, max: %s, target: %s \n"%(oldmin,oldmax,oldtarget)) cmin = spotinst_results.caparg[1] cmax = spotinst_results.caparg[2] target = spotinst_results.caparg[3] if len(spotinst_results.caparg[1]) <= 2 and \ len(spotinst_results.caparg[2]) <= 2 and \ len(spotinst_results.caparg[3]) <= 2: print ("\nRequested capacity is min:%s, max:%s, target:%s \n" %(cmin,cmax,target)) answer = yes_no('Execute the request?\n') if answer: update_capac(spotinst_results.caparg[0], cmin, cmax, target, spotinst_client) else: print ("\nAborting..") sys.exit(1) else: print ("\n[ERROR]: Accepted values should be maximum 2 digit length.\n") # --list all|<group_id> if spotinst_results.id: if spotinst_results.id == 'all': showid(spotinst_results.id, spotinst_client) elif "sig-" in spotinst_results.id : capacity,cap_target,cap_min,cap_max,group_name,env,ami = showid(spotinst_results.id, spotinst_client) print ("Group name:%s \nEnvironment:%s \nAmi:%s \nCapacity is min:%s, max:%s and target:%s" %(group_name,env,ami,cap_min,cap_max,cap_target)) else: print ("\n[ERROR]: Accepted values should start with sig-xxxxxxxx \n",spotinst_parser.print_help()) sys.exit(1) # --deploy <group_id> <batch_perc> <grace_period> if spotinst_results.deparg: if "sig-" in spotinst_results.deparg[0] and \ len(spotinst_results.deparg[1]) <= 3 and \ len(spotinst_results.deparg[2]) <= 3: print ("\nRequested batch percentage is %s and grace period is %s \n" %(spotinst_results.deparg[1],spotinst_results.deparg[2])) if spotinst_results.bbpipelines: deploy(spotinst_results.deparg[0],spotinst_results.deparg[1],spotinst_results.deparg[2],spotinst_client) else: answer = yes_no('Execute the request?\n') if answer: deploy(spotinst_results.deparg[0],spotinst_results.deparg[1],spotinst_results.deparg[2],spotinst_client) else: print ("\n[ERROR]: Accepted values should start with sig-xxxxxxxx \n" ,spotinst_parser.print_help()) sys.exit(1) else: print ("\n[Error]: Nothing to do. Exiting..\n") sys.exit(1)
help='Name of the deployment to grab suggestions for.') parser.add_argument( '-r', '--ratio', default=2, help='The number between resource requests divided by the suggestions.') parser.add_argument('-t', '--auth_token', help='Spotinst API Token.') parser.add_argument('-a', '--account_id', help='ID of the Spotinst account.') parser.add_argument('-o', '--ocean_id', help='ID of the Ocean cluster.') parser.add_argument('-n', '--namespace', help='Namespace of the deployment in the cluster.') args = parser.parse_args() try: client = spotinst_sdk.SpotinstClient(auth_token=args.auth_token, account_id=args.account_id) except Exception as e: print('Failed client init.\n{}'.format(e)) sys.exit(1) try: sizing_suggestions = client.get_all_ocean_sizing(args.ocean_id, args.namespace) except Exception as e: print('Failed getting suggestions.\n{}'.format(e)) sys.exit(1) # credit: https://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size def sizeof_fmt(num, suffix='B'): for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']: if abs(num) < 1024.0: