#!/usr/bin/env python

# Copyright 2012 AMG.lab, a Bull Group Company
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#    http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import random
import commands
import json
import os

CLI_DIR = os.path.dirname(os.path.abspath(__file__))+'/'

RAND_NUMBER = str(random.randint(0,10000))
ADMIN_LOGIN = 'xlcadmin'
ADMIN_PASS = 'admin123'

LOG_FILE = CLI_DIR+"test_cli.log"

TEST_ACCOUNT_NAME = 'qACCOUNT'+RAND_NUMBER
TEST_USER_NAME = 'qUSER'+RAND_NUMBER
TEST_USER_PASS = '12345678'
TEST_GROUP_NAME = 'qGROUP'+RAND_NUMBER
TEST_PROJECT_NAME = 'qPROJECT'+RAND_NUMBER
TEST_STACK_NAME = 'qSTACK'+RAND_NUMBER

TEST_PUBLIC_KEY = \
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZpFEQ473E1reiJ9TlSF" +\
"pmXu4ZIEbFWQXDYBHNwF3dKFMu75Mq0yKCADc2aaN/W4YCAE4oAQBQFNKR" +\
"AaaI9hUgmWvi48yPmFS4eZ5MqjkoB3NnmFFO22/G7Zk90khJdOAy99Jbp4" +\
"llYx9o53DOhyFYU27mqkFkDFw4IhEiaHcZwZoCFQLB/Jn1wYjYtsE3x37U" +\
"Uu/sGQNM4UUpCoXfaqv8gtJRq68gvLjNdQsnjsMqOy7G7VJg8XsboYx1yj" +\
"pRlo52DmDM6DQ5Qxp/drEHtWglyTQtlbmzWbAL1VFkOKHq1NTG2J7B6Mjh" +\
"yAoACbMK0FEwcHKPRfmvF4cseuKjPAw7 Generated by Nova"

xauth_token = None

class Logger:
    @staticmethod
    def open(filename):
        Logger.logfile = open(filename,'w')
        
    @staticmethod
    def log(string):
        Logger.logfile.write(string+'\n')
        
    @staticmethod
    def close():
        Logger.logfile.close()

def exe(command,noToken=False):
    global xauth_token
    auth_param = '-x %s '%xauth_token if not noToken and xauth_token else ''
    command = CLI_DIR+'main.py -s '+auth_param+command
    print command
    response = commands.getoutput(command)
    Logger.log(20*'-')
    Logger.log('COMMAND> '+command)
    Logger.log('RESPONSE< '+response)
    return response

def jexe(command):
    return json.loads(exe(command));

def loginToken(token):
    global xauth_token
    xauth_token = token
    return token

def login(username,password):
    token = exe('authenticate -u %s -p %s' % (username,password),noToken=True)
    return loginToken(token)

def loginXlcadmin():
    return login(ADMIN_LOGIN,ADMIN_PASS)

def createAccount():
    response = jexe('create-account -n '+TEST_ACCOUNT_NAME)
    return response['id']

def createUser(accId,username=TEST_USER_NAME,password=TEST_USER_PASS):
    response = jexe('create-user -n %s -p %s -a %d'%(username,password,accId))
    return response['id']

def createGroup(accId):
    response = jexe('create-group -n %s -a %d'%(TEST_GROUP_NAME,accId))
    return response['id']

def createProject(accId):
    response = jexe('create-project -n %s -a %d'%(TEST_PROJECT_NAME,accId))
    return response['id']

def createStackFromBlueprint(stackBlueprintId,projectId):
    response = jexe('create-stack -n %s -p %d -v %d'%(TEST_STACK_NAME,projectId,stackBlueprintId))
    return response['id']


def listAccountsHas(id,many=1):
    response = jexe('list-accounts')
    account = filter(lambda x:x['id']==id,response['account'])
    assert len(account)==many

def listAUsersHas(accId,id):
    response = jexe('list-users -a %d'%accId)
    user = filter(lambda x:x['id']==id,response['user'])
    assert len(user)==1

def listAGroupsHas(accId,id):
    response = jexe('list-groups -a %d'%accId)
    group = filter(lambda x:x['id']==id,response['group'])
    assert len(group)==1

def listGUsersHas(gId,id,many=1):
    response = jexe('list-users -g %d'%gId)
    user = filter(lambda x:x['id']==id,response['user'])
    assert len(user)==many

def listAProjectsHas(aId,id):
    response = jexe('list-projects -a %d'%aId)
    project = filter(lambda x:x['id']==id,response['project'])
    assert len(project)==1

def listAStacksHas(aId,id):
    response = jexe('list-stacks -a %d'%aId)
    stack = filter(lambda x:x['id']==id,response['stack'])
    assert len(stack)==1

def listPStacksHas(pId,id):
    response = jexe('list-stacks -p %d'%pId)
    stack = filter(lambda x:x['id']==id,response['stack'])
    assert len(stack)==1


def getAccount(aId):
    response = jexe('get-account -i %d'%aId)
    assert response['id']==aId

def getUser(uId):
    response = jexe('get-user -i %d'%uId)
    assert response['id']==uId

def getGroup(gId):
    response = jexe('get-group -i %d'%gId)
    assert response['id']==gId

def getProject(pId):
    response = jexe('get-project -i %d'%pId)
    print response
    assert response['id']==pId

def getStack(sId):
    response = jexe('get-stack -i %d'%sId)
    print response
    assert response['id']==sId

def setUserPassword(uId,newPass):
    exe('update-user -i %d -p %s'%(uId,newPass))


def addUserToGroup(uId,gId):
    exe('update-group -i %d -a %d'%(gId,uId))

def removeUserFromGroup(uId,gId):
    exe('update-group -i %d -r %d'%(gId,uId))


def deleteGroup(id):
    exe('delete-group -i %d'%id)

def deleteUser(id):
    exe('delete-user -i %d'%id)

def deleteAccount(id):
    exe('delete-account -i %d'%id)

def deleteProject(id):
    exe('delete-project -i %d'%id)

def deleteStack(id):
    exe('delete-stack -i %d'%id)


def listStackBlueprintsGetFirst():
    responseBody = jexe('list-stack-blueprints')['stackBlueprint']
    assert len(responseBody)>0
    return responseBody[0]['id']

def getStackBlueprint(sbId):
    response = jexe('get-stack-blueprint -i %d'%sbId)
    assert response['id']==sbId

def listRepositoriesGetFirst():
    responseBody = jexe('list-repositories')['repository']
    assert len(responseBody)>0
    return responseBody[0]['id']

def getRepository(rId):
    response = jexe('get-repository -i %d'%rId)
    assert response['id']==rId

def listCookbooksGetFirst(rId):
    responseBody = jexe('list-cookbooks -r %d'%rId)['cookbook']
    assert len(responseBody)>0
    return responseBody[0]['id']

def getCookbook(cId):
    response = jexe('get-cookbook -i %d'%cId)
    assert response['id']==cId

def listRecipesGetFirst(cId):
    responseBody = jexe('list-recipes -c %d'%cId)['recipe']
    assert len(responseBody)>0
    return responseBody[0]['id']

def getRecipe(rId):
    response = jexe('get-recipe -i %d'%rId)
    assert response['id']==rId

def listImagesGetFirst():
    responseBody = jexe('list-images')['image']
    assert len(responseBody)>0
    return responseBody[0]['id']

def getImage(iId):
    response = jexe('get-image -i %d'%iId)
    assert response['id']==iId
###

def createUEntitlement(userId,ent):
    response = jexe('create-entitlement -u %d -r %s -c %s'%(userId,ent['resource'],ent['action']))
    return response['id']

def listUEntitlementsSize(userId,size):
    response = jexe('list-entitlements -u %d'%userId)
    assert len(response['entitlement'])==size

def deleteUEntitlement(userId,eId):
    exe('delete-entitlement -u %d -i %d'%(userId,eId))

def updateUEntitlements(userId,ents):
    eParam = ' '.join(map(lambda e:e["resource"]+","+e["action"],ents))
    exe('update-entitlements -u %d -e %s'%(userId,eParam))

def listUTokensHas(uId,token,many=1):
    response = jexe('list-tokens -u %d'%uId)
    token = filter(lambda x:x['token']==token,response['accessToken'])
    assert len(token)==many

def getToken(token):
    response = jexe('get-token -i %s'%token)
    assert response['token']==token

def deleteToken(token):
    exe('delete-token -i %s'%token)

def generateUKeypair(userId,name):
    keypair = jexe('generate-keypair -u %d -n %s'%(userId,name))
    assert keypair['name']==name

def getUKeypair(userId,name):
    keypair = jexe('get-keypair -u %d -n %s'%(userId,name))
    assert keypair['name']==name

def importUKeypair(userId,name):
    tmp_filename = "/tmp/test_keypair"+RAND_NUMBER
    with open(tmp_filename,"w") as f:
        f.write(TEST_PUBLIC_KEY)
    keypair = jexe('import-keypair -u %d -n %s -k %s'%(userId,name,tmp_filename))
    assert keypair['name']==name
    assert keypair['publicKey']==TEST_PUBLIC_KEY
    os.remove(tmp_filename)

def listUKeypairsSize(userId,many):
    response = jexe('list-keypairs -u %d'%userId)
    assert len(response['keypair'])==many

def deleteUKeypair(userId,name):
    exe('delete-keypair -u %d -n %s'%(userId,name))



def test1():
    Logger.log("Test 1")
    loginXlcadmin()
    accountId = createAccount()
    listAccountsHas(accountId)
    userId = createUser(accountId)
    listAUsersHas(accountId,userId)
    groupId = createGroup(accountId)
    listAGroupsHas(accountId,groupId)

    addUserToGroup(userId,groupId)
    listGUsersHas(groupId,userId)
    removeUserFromGroup(userId,groupId)
    listGUsersHas(groupId,userId,0)

    getAccount(accountId)
    getUser(userId)
    getGroup(groupId)

    deleteGroup(groupId)
    deleteUser(userId)
    deleteAccount(accountId)
    listAccountsHas(accountId,0)

def test2():
    Logger.log("Test 2")
    loginXlcadmin()
    stackBlueprintId = listStackBlueprintsGetFirst()
    getStackBlueprint(stackBlueprintId)
    imageId = listImagesGetFirst()
    #getImage(imageId)
    repositoryId = listRepositoriesGetFirst()
    getRepository(repositoryId)
    cookbookId = listCookbooksGetFirst(repositoryId)
    getCookbook(cookbookId)
    recipeId = listRecipesGetFirst(cookbookId)
    getRecipe(recipeId)

def test3():
    Logger.log("Test 3")
    loginXlcadmin()
    stackBlueprintId = listStackBlueprintsGetFirst()
    accountId = createAccount()
    userId = createUser(accountId,'MYUSER'+RAND_NUMBER,'12345678')
    createUEntitlement(userId,{"resource":"accounts/%d/projects"%accountId,"action":"POST"})
    createUEntitlement(userId,{"resource":"accounts/%d/projects"%accountId,"action":"GET"})
    createUEntitlement(userId,{"resource":"accounts/%d/projects"%accountId,"action":"DELETE"})
    login('MYUSER'+RAND_NUMBER,'12345678')
    projectId = createProject(accountId)
    loginXlcadmin()
    getProject(projectId)
    listAProjectsHas(accountId,projectId)

    stackId = createStackFromBlueprint(stackBlueprintId,projectId)
    getStack(stackId)
    listAStacksHas(accountId,stackId)
    listPStacksHas(projectId,stackId)

    deleteStack(stackId)
    deleteProject(projectId)
    deleteUser(userId)
    deleteAccount(accountId)
    listAccountsHas(accountId,0)

def testEntitlements():
    Logger.log("Test entitlements")
    loginXlcadmin()
    accountId = createAccount()
    userId = createUser(accountId)
    entitlement1 = {"resource":"accounts/%d/projects"%accountId,"action":"GET"}
    entitlement2 = {"resource":"accounts/%d/groups"%accountId,"action":"POST"}
    listUEntitlementsSize(userId,0)
    entitlementId = createUEntitlement(userId,entitlement1)
    listUEntitlementsSize(userId,1)
    deleteUEntitlement(userId,entitlementId)
    listUEntitlementsSize(userId,0)
    updateUEntitlements(userId,[entitlement1,entitlement2])
    listUEntitlementsSize(userId,2)

    deleteUser(userId)
    deleteAccount(accountId)

def testTokens():
    Logger.log("Test tokens")
    myusername = 'MYUSER'+RAND_NUMBER
    xlctoken = loginXlcadmin()
    accountId = createAccount()
    userId = createUser(accountId,myusername,'12345678')
    token = login('MYUSER'+RAND_NUMBER,'12345678')
    loginToken(xlctoken)
    listUTokensHas(userId,token)
    getToken(token)
    deleteToken(token)
    listUTokensHas(userId,token,0)

    newPass = 'password1'
    setUserPassword(userId,newPass)
    login(myusername,newPass)
    loginToken(xlctoken)

    deleteUser(userId)
    deleteAccount(accountId)

def testKeypairs():
    Logger.log("Test keypairs")
    loginXlcadmin()
    accountId = createAccount()
    userId = createUser(accountId)
    generateUKeypair(userId,'key1')
    getUKeypair(userId,'key1')
    importUKeypair(userId,'key2')
    listUKeypairsSize(userId,2)
    deleteUKeypair(userId,'key1')
    listUKeypairsSize(userId,1)
    deleteUser(userId)
    deleteAccount(accountId)


    

if __name__=='__main__':
    Logger.open(LOG_FILE)
    test1()
    #test2()
    #test3()
    #testEntitlements()
    #testTokens()
    #testKeypairs()
    Logger.close()
