Skip to content

Commit

Permalink
Issue #11: Load AWS creds from env, pass as http headers
Browse files Browse the repository at this point in the history
  • Loading branch information
machristie committed Apr 30, 2018
1 parent 7cd5b20 commit 8d201e0
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 13 deletions.
11 changes: 7 additions & 4 deletions cloudlaunch_cli/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@

class APIConfig:
"""Config object with needed config values for accessing API."""
def __init__(self, url, token):
def __init__(self, url, token, cloud_credentials=None):
self.url = url
self.token = token
# cloud_credentials is a dict
self.cloud_credentials = cloud_credentials


class APIClient:

def __init__(self, url=None, token=None):
# create config object from url and token
config = APIConfig(url=url, token=token)
def __init__(self, url=None, token=None, cloud_credentials=None):
# create config object from url and token (and optionally, credentials)
config = APIConfig(url=url, token=token,
cloud_credentials=cloud_credentials)
self.deployments = endpoints.Deployments(config)
self.applications = endpoints.Applications(config)
self.auth = types.SimpleNamespace()
Expand Down
48 changes: 48 additions & 0 deletions cloudlaunch_cli/api/cloud_credentials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Utilities for handling cloud credentials."""
import abc
import os


class CloudCredentials(abc.ABC):
"""Base class representing cloud credentials."""

@staticmethod
def load_from_environment(cloud_type):
"""Load a CloudCredentials subclass instance from env vars."""
if cloud_type == 'aws':
return AWSCredentials.from_environment()
return None

@staticmethod
@abc.abstractmethod
def from_environment():
"""Load and return an instance of CloudCredentials using env vars."""
pass

@abc.abstractmethod
def to_http_headers(self):
"""Convert credentials to dict of http header name/values."""
pass


class AWSCredentials(CloudCredentials):
"""CloudCredentials subclass representing AWS credentials."""

def __init__(self, aws_access_key, aws_secret_key):
self.aws_access_key = aws_access_key
self.aws_secret_key = aws_secret_key

@staticmethod
def from_environment():
aws_access_key = os.environ.get('AWS_ACCESS_KEY')
aws_secret_key = os.environ.get('AWS_SECRET_KEY')
if aws_access_key and aws_secret_key:
return AWSCredentials(aws_access_key, aws_secret_key)
else:
return None

def to_http_headers(self):
return {
'cl-aws-access-key': self.aws_access_key,
'cl-aws-secret-key': self.aws_secret_key
}
6 changes: 5 additions & 1 deletion cloudlaunch_cli/api/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,13 @@ def _create_client(self):
if not auth_token or not url:
raise Exception("Auth token and url are required.")
hostname = urlparse(url).netloc.split(":")[0]
http_headers = {}
if self.api_config.cloud_credentials:
http_headers = self.api_config.cloud_credentials.to_http_headers()
custom_transports = [
coreapi.transports.HTTPTransport(
credentials={hostname: 'Token {}'.format(auth_token)})
credentials={hostname: 'Token {}'.format(auth_token)},
headers=http_headers)
]
self._client = coreapi.Client(transports=custom_transports)
return self._client.get('{url}/schema/'.format(url=url))
Expand Down
37 changes: 29 additions & 8 deletions cloudlaunch_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,24 @@
import click

from .api.client import APIClient
from .api.cloud_credentials import CloudCredentials
from .config import Configuration

conf = Configuration()
cloudlaunch_client = APIClient(url=conf.url, token=conf.token)


def create_api_client(cloud=None, cloud_credentials_json=None):

cloudlaunch_client = APIClient(url=conf.url, token=conf.token)
# Recreate client with cloud credentials if available
if cloud:
cloud_resource = cloudlaunch_client.infrastructure.clouds.get(cloud)
cloud_creds = CloudCredentials.load_from_environment(
cloud_resource.cloud_type)
if cloud_creds:
return APIClient(url=conf.url, token=conf.token,
cloud_credentials=cloud_creds)
return cloudlaunch_client


@click.group()
Expand Down Expand Up @@ -67,17 +81,24 @@ def create_deployment(name, application, cloud, application_version,
# TODO: if application_version not specified then fetch the default version
# and use that instead
config_app = json.loads(config_app.read()) if config_app else None
new_deployment = cloudlaunch_client.deployments.create(
name=name, application=application, target_cloud=cloud,
application_version=application_version, config_app=config_app)
cloudlaunch_client = create_api_client(cloud)
params = {
'name': name,
'application': application,
'target_cloud': cloud,
'application_version': application_version
}
if config_app:
params['config_app'] = config_app
new_deployment = cloudlaunch_client.deployments.create(**params)
_print_deployments([new_deployment])


@click.command()
@click.option('--archived', is_flag=True,
help='Show only archived deployments')
def list_deployments(archived):
deployments = cloudlaunch_client.deployments.list(archived=archived)
deployments = create_api_client().deployments.list(archived=archived)
_print_deployments(deployments)


Expand Down Expand Up @@ -115,15 +136,15 @@ def applications():
@click.option('--maintainer', help='Maintainer of app')
@click.option('--description', help='Description of app')
def create_application(name, summary, maintainer, description):
new_app = cloudlaunch_client.applications.create(
new_app = create_api_client().applications.create(
name=name, summary=summary, maintainer=maintainer,
description=description)
_print_applications([new_app])


@click.command()
def list_applications():
applications = cloudlaunch_client.applications.list()
applications = create_api_client().applications.list()
_print_applications(applications)


Expand All @@ -148,7 +169,7 @@ def clouds():

@click.command()
def list_clouds():
clouds = cloudlaunch_client.infrastructure.clouds.list()
clouds = create_api_client().infrastructure.clouds.list()
_print_clouds(clouds)


Expand Down

0 comments on commit 8d201e0

Please sign in to comment.