I'm taking my first programming course so please pardon if questions are too naive. I'm using Python Boto3 module and 'Click' library to build a Command Line Interface that manages EC2 instances. Code:
@click.group()
@cli.group('instances')
def instances():
pass
@instances.command('list')
@click.option('--project', default=None,help='List instances by project tag, e.g. -project = <project name>')
def list_instances(project):
'List EC2 instances'
instances = filter_project_instances(project)
for i in instances:
print(', '.join((
i.id,
i.instance_type,
)))
return
@cli.group('volumes')
#Details of this 'volumes' command are omitted for simplification
Basically, 'Click' allows me to wrap my functions with commands (e.g. instances, volumes), subcommands(list) and option (--project). Such a command line: shotty.py instances list --project Valkyrie can list instances that are tagged with the name 'Valkyrie'
Now, I'm required to add an option to this command line to specify the AWS profile I wanna use to log in. The profile was created with 'aws configure --profile [profile name]' command (profile names can be Dan, Kyle, etc.):
shotty.py --profile [profile name] instances list
Initially, I hardcoded the profile name and used session and ec2 as global variables that any other functions can use.
import boto3
import botocore
import click
session = boto3.Session(profile_name='Dan')
ec2 = session.resource('ec2')
Though implementing the above requirement, based on 'Click' documents, I had to do the following to add such a '--profile' option:
@click.group()
@click.option('--profile', default=None,help='Select the AWS profile')
def cli(profile):
session = boto3.Session(profile_name=profile)
ec2 = session.resource('ec2')
But now, session and ec2 are not available to other functions any more. This cli() function is like an entry point of the script and is revoked in the main() function:
if __name__ == '__main__':
cli()
My only approach I could think of was creating a separate function
def session(profile):
session = boto3.Session(profile_name=profile)
ec2 = session.resource('ec2')
return ec2
But now this brings another issue that I have to add profile as a parameter to all other functions, e.g.
def filter_project_instances(project, profile):
'Filter EC2 instances'
ec2 = session(profile)
instances = ec2.instances.all()
return instances
This means I have to define profile again somehow in this filter_project_instances function. It does not make much sense to me. Any help would be appreciated! Update: I had a look at the global keyword before posting but most searches told me that having global variable was mostly a sign of a bad design so I was thinking that I was lacking something pythonically to make it work here 😅