#!/usr/bin/env python
import boto3
import json, os
from yac.lib.config import get_config_path

# returns the url to the location in s3 to an app's backup configuration
# file 
def get_backup_config_s3_url(app, env, s3_bucket):

    url = 's3://%s/%s/%s/%s-backup.json'%(s3_bucket,app,env,app)

    return url

# get constants associated with yac apps
def get_app_constants():

    app_const_file = os.path.join( get_config_path(),'app','yac-app-const.json')

    app_constants = {}
    if (app_const_file and os.path.exists(app_const_file)):

        # use the default naming standard
        with open(app_const_file) as app_const_fp:
            app_constants = json.load(app_const_fp)
                            
    return app_constants

# create a new task definition, or create a new revision of an existing 
# task definition
# returns taskdef revision number, as generated by ECS
def _create_task_definition(client, 
                            task_definition_name, 
                            task_definitions,
                            dry_run = False):

    revision = 0

    family = task_definition_name

    if not dry_run:
        
        # register task definition
        response = client.register_task_definition(family=family,
                      containerDefinitions=task_definitions['containerDefinitions'],
                      volumes=task_definitions['volumes'])

        # get the new revision number from ECS response
        revision = response['taskDefinition']['revision']

    else:
        
        # this is a dry run, so just print the task definition deets to stdout
        print 'Taskdef family: %s'%family

        print 'Taskdefs: %s'%json.dumps(task_definitions, 
                                    sort_keys=True,
                                    indent=4, separators=(',', ': '))

    return revision

def _new_cluster_needed(client, cluster_name):

    # first see if this cluster exists
    response = client.describe_clusters(clusters=[cluster_name])

    cluster_exists = response['clusters'] and len(response['clusters'])>0

    # a new cluster is need if the cluster doesn't already exist
    return not cluster_exists

# print a new stack
def create_or_update_cluster( cluster_name , 
                    task_definitions,
                    dry_run=False,
                    desired_count=1):

    client = boto3.client('ecs')

    # A new task definition is need for all updates to cluster software
    # Create the task definition.
    # Task definition name should match cluster name
    revision = _create_task_definition(client, 
                                       cluster_name, 
                                       task_definitions,
                                       dry_run)

    # determine if a new cluster is needed
    new_cluster_needed = _new_cluster_needed(client, cluster_name)

    if (new_cluster_needed and not dry_run):

        print 'Creating %s cluster with %s:%s service with count=%s ...'%(cluster_name,
                          cluster_name,revision ,desired_count)
        # Cluster does not yet exist and this is not a dry run, so
        # create the cluster
        response = client.create_cluster(clusterName=cluster_name)

        # Associate the new task definition with the cluster.
        # Service name, cluster name, and task def name should all match
        response = client.create_service(
                        cluster=cluster_name,
                        serviceName=cluster_name,
                        taskDefinition='%s:%s'%(cluster_name,revision),
                        desiredCount=desired_count)

    elif (not new_cluster_needed and not dry_run):

        # Cluster already exists and this is not a dry run

        print 'Updating %s cluster with %s:%s service with count=%s ...'%(cluster_name,
                          cluster_name,revision ,desired_count)

        # Update the cluster with the latest rev of the task definition.
        # Service name, cluster name, and task def name should all match
        response = client.update_service(
                        cluster=cluster_name,
                        service=cluster_name,
                        taskDefinition='%s:%s'%(cluster_name,revision),
                        desiredCount=desired_count)                

    elif dry_run:

        # if this is a dry run, indicate if a new cluster is needed
        print "New cluster needed?: %s"%new_cluster_needed

        print 'Dry run print of %s cluster with %s:%s service with count=%s'%(cluster_name,
                          cluster_name,revision ,desired_count)

# stop a cluster
def stop_cluster( cluster_name ):

    client = boto3.client('ecs')

    # get the services on this cluster
    services = client.describe_services(cluster=cluster_name,services=[cluster_name])

    if (len(services['services'])==1 and services['services'][0]['taskDefinition']):

        # get the task definition for this service in this cluster
        task_definition=str(services['services'][0]['taskDefinition'])

        print 'Stopping %s cluster with %s service ...'%(cluster_name,
                          cluster_name )

        # stop the cluster by setting desiredCount to 0
        response = client.update_service(
                        cluster=cluster_name,
                        service=cluster_name,
                        taskDefinition=task_definition,
                        desiredCount=0) 

# start a cluster
def start_cluster( cluster_name ):

    client = boto3.client('ecs')

    # get the services on this cluster
    services = client.describe_services(cluster=cluster_name,services=[cluster_name])

    if (len(services['services'])==1 and services['services'][0]['taskDefinition']):

        # get the task definition for this service in this cluster
        task_definition=str(services['services'][0]['taskDefinition'])

        print 'Stopping %s cluster with %s service ...'%(cluster_name,
                          cluster_name )

        # start the cluster by setting desiredCount to 1
        response = client.update_service(
                        cluster=cluster_name,
                        service=cluster_name,
                        taskDefinition=task_definition,
                        desiredCount=1)                                   