blob: 75a35ebc143943bd2c0b21c43e8f8cf7e1c40663 [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright 2015-2016 IBM Corporation
#
# 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.
#
##
# Whisk command line interface
##
import os
import sys
from functools import partial
import traceback
import argparse
import json
import httplib
try:
import argcomplete
except ImportError:
argcomplete = False
import wskprop
from wskaction import Action
from wskactivation import Activation
from wsktrigger import Trigger
from wskrule import Rule
from wskpackage import Package
from wsknamespace import Namespace
from wsksdk import Sdk
from wskutil import addAuthenticatedCommand, apiBase, chooseFromArray, resolveNamespace, request, responseError
def main():
userpropsLocation = os.getenv('WSK_CONFIG_FILE', '%s/.wskprops' % os.path.expanduser('~'))
userprops = wskprop.importPropsIfAvailable(userpropsLocation)
whiskprops = wskprop.importDefaultProps()
# if the default properties failed to load (because file does not exist) then create a stub
if whiskprops is None:
whiskprops = { 'CLI_API_HOST': None, 'WHISK_VERSION_DATE': None }
exitCode = 0
try:
args = parseArgs(userprops)
apihost = resolveOverrides(whiskprops['CLI_API_HOST'], userprops.get('APIHOST'), args.apihostOverride)
apiversion = resolveOverrides('v1', userprops.get('APIVERSION'), args.apiversionOverride)
props = {
'apihost' : apihost,
'apiversion': apiversion,
'namespace': resolveNamespace(userprops, 'NAMESPACE'),
'clibuild' : whiskprops['WHISK_VERSION_DATE']
}
if (args.verbose):
print props
if apihost is None and (args.cmd != 'property' or args.cmd == 'property' and args.subcmd != 'set'):
print 'error: API host is not set. Set it with "wsk property set --apihost <host>".'
return 2
exitCode = {
'list' : Namespace().listEntitiesInNamespace,
'action' : Action().cmd,
'trigger' : Trigger().cmd,
'rule' : Rule().cmd,
'activation' : Activation().cmd,
'package' : Package().cmd,
'sdk' : Sdk().cmd,
'namespace' : Namespace().cmd,
'property' : partial(propCmd, userprops = userprops, propsLocation = userpropsLocation)
}[args.cmd](args, props)
except Exception as e:
print 'Exception: ', e
if 'verbose' in args and args.verbose:
traceback.print_exc()
exitCode = 1
sys.exit(exitCode)
def parseArgs(props):
description = 'OpenWhisk is a distributed compute service to add event-driven logic to your apps.'
epilog = """Learn more at https://developer.ibm.com/openwhisk fork on GitHub https://github.com/openwhisk.
All trademarks are the property of their respective owners."""
parser = argparse.ArgumentParser(description=description, epilog=epilog)
parser.add_argument('-v', '--verbose', help='verbose output', action='store_true')
subparsers = parser.add_subparsers(title='available commands', dest='cmd')
parser.add_argument('--apihost', help='whisk API host', dest='apihostOverride', metavar='hostname')
parser.add_argument('--apiversion', help='whisk API version', dest='apiversionOverride', metavar='version')
Action().getCommands(subparsers, props)
Activation().getCommands(subparsers, props)
Namespace().getCommands(subparsers, props)
Package().getCommands(subparsers, props)
Rule().getCommands(subparsers, props)
Trigger().getCommands(subparsers, props)
Sdk().getCommands(subparsers, props)
# work with whisk properties: set or get property
propmenu = subparsers.add_parser('property', help='work with whisk properties')
subparser = propmenu.add_subparsers(title='available commands', dest='subcmd')
subcmd = subparser.add_parser('set', help='set property')
subcmd.add_argument('-u', '--auth', help='authorization key')
subcmd.add_argument('--apihost', help='whisk API host')
subcmd.add_argument('--apiversion', help='whisk API version')
subcmd.add_argument('--namespace', help='whisk namespace', nargs='?', const='*')
subcmd = subparser.add_parser('unset', help='unset property')
subcmd.add_argument('-u', '--auth', help='authorization key', action='store_true')
subcmd.add_argument('--apihost', help='whisk API host', action='store_true')
subcmd.add_argument('--apiversion', help='whisk API version', action='store_true')
subcmd.add_argument('--namespace', help='namespace', action='store_true')
subcmd = subparser.add_parser('get', help='get property')
subcmd.add_argument('-a', '--all', help='all properties (default)', action='store_true')
subcmd.add_argument('-u', '--auth', help='authorization key', action='store_true')
subcmd.add_argument('--apihost', help='whisk API host', action='store_true')
subcmd.add_argument('--apiversion', help='whisk API version', action='store_true')
subcmd.add_argument('--namespace', help='namespace', action='store_true')
subcmd.add_argument('--cliversion', help='whisk CLI version', action='store_true')
subcmd.add_argument('--apibuild', help='whisk API build version', action='store_true')
subcmd.add_argument('--apibuildno', help='whisk API build number', action='store_true')
listmenu = subparsers.add_parser('list', help='list all triggers, actions, and rules in the registry')
listmenu.add_argument('name', nargs='?', help='the namespace to list')
addAuthenticatedCommand(listmenu, props)
if argcomplete:
argcomplete.autocomplete(parser)
return parser.parse_args()
def propCmd(args, props, userprops, propsLocation):
if args.subcmd == 'set':
if args.verbose:
print 'ok: whisk property file %s' % propsLocation
if args.auth:
wskprop.updateProps('AUTH', args.auth, propsLocation)
print 'ok: whisk auth set'
if args.apihost:
wskprop.updateProps('APIHOST', args.apihost, propsLocation)
print 'ok: whisk API host set'
if args.apiversion:
wskprop.updateProps('APIVERSION', args.apiversion, propsLocation)
print 'ok: whisk API version set'
if args.namespace:
if args.apihost is not None:
props['apihost'] = args.apihost
url = 'https://%(apibase)s/namespaces/' % { 'apibase': apiBase(props) }
if args.auth:
auth = args.auth
else:
auth = userprops.get('AUTH')
if auth is None:
print 'error: cannot set namespace without an authentication key'
return 1
res = request('GET', url, auth=auth, verbose=args.verbose)
namespaces = None
if res.status == httplib.OK:
result = json.loads(res.read())
namespaces = result
if namespaces != None:
choice = None
if args.namespace == '*':
choice = chooseFromArray(namespaces)
elif args.namespace in namespaces:
choice = args.namespace
if choice == -1:
return 0
elif choice != None:
wskprop.updateProps('NAMESPACE', '%s' % choice, propsLocation)
print 'ok: namespace set to %s' % choice
return 0
print 'error: you are either not entitled to a namespace or you made an invalid choice'
return 1
else:
return responseError(res)
return 0
if args.subcmd == 'unset':
if args.verbose:
print 'ok: whisk property file %s' % propsLocation
if args.auth:
wskprop.updateProps('AUTH', '', propsLocation)
print 'ok: whisk auth unset'
if args.apihost:
wskprop.updateProps('APIHOST', '', propsLocation)
print 'ok: whisk API host unset'
if args.apiversion:
wskprop.updateProps('APIVERSION', '', propsLocation)
print 'ok: whisk API version unset'
if args.namespace:
wskprop.updateProps('NAMESPACE', '', propsLocation)
print 'ok: whisk namespace unset'
return 0
elif args.subcmd == 'get':
args.all = args.auth == args.apihost == args.apiversion == args.namespace == args.cliversion == args.apibuild == args.apibuildno == False
if args.all or args.auth:
print 'whisk auth\t\t%s' % userprops.get('AUTH')
if args.all or args.apihost:
print 'whisk API host\t\t%s' % props['apihost']
if args.all or args.apiversion:
print 'whisk API version\t%s' % props['apiversion']
if args.all or args.namespace:
print 'whisk namespace\t\t%s' % props['namespace']
if args.all or args.cliversion:
print 'whisk CLI version\t%s' % props['clibuild']
if args.all or args.apibuild:
if props['apihost'] is not None:
url = 'https://%(apibase)s' % { 'apibase' : apiBase(props) }
res = request('GET', url, verbose=args.verbose)
if res.status == httplib.OK:
result = json.loads(res.read())
print 'whisk API build\t\t%s' % result['build']
else:
print 'whisk API build\t\tCannot determine API build:',
return responseError(res, prefix=None)
else:
print 'whisk API build\t\tNone',
if args.all or args.apibuildno:
if props['apihost'] is not None:
url = 'https://%(apibase)s' % { 'apibase' : apiBase(props) }
res = request('GET', url, verbose=args.verbose)
if res.status == httplib.OK:
result = json.loads(res.read())
print 'whisk API buildno\t%s' % result['buildno']
else:
print 'whisk API build\t\tCannot determine API buildno:',
return responseError(res, prefix=None)
else:
print 'whisk API buildno\t\tNone',
return 0
return 2
def resolveOverrides(defaultVal, userOverride, cmdOverride):
val = defaultVal
if userOverride and userOverride.strip() != '':
val = userOverride.strip()
if cmdOverride and cmdOverride.strip() != '':
val = cmdOverride
return val
if __name__ == '__main__':
main()