diff --git a/.gitignore b/.gitignore index 5fe1c804ad..355fa34e7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/components/org.apache.stratos.python.cli/src/main/python/tests/scratch/.scripttest-test-dir.txt # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information diff --git a/components/org.apache.stratos.python.cli/README.md b/components/org.apache.stratos.python.cli/README.md new file mode 100644 index 0000000000..d1596d7e5a --- /dev/null +++ b/components/org.apache.stratos.python.cli/README.md @@ -0,0 +1 @@ +#Python based CLI for Apache Stratos diff --git a/components/org.apache.stratos.python.cli/src/main/python/.gitignore b/components/org.apache.stratos.python.cli/src/main/python/.gitignore new file mode 100644 index 0000000000..3d24c23997 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/.gitignore @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +build/ +dist/ +stratos.egg-info/ +.tox/ diff --git a/components/org.apache.stratos.python.cli/src/main/python/README.md b/components/org.apache.stratos.python.cli/src/main/python/README.md new file mode 100644 index 0000000000..4b523fe50d --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/README.md @@ -0,0 +1,36 @@ +Apache Stratos CLI +================== + +Build and install stratos CLI by, + +``` +$ python setup.py build +$ python setup.py install +``` + +or use +``` + $ python setup.py develop +``` + +instead `install` if developing + +To start the Python CLI issue, + +``` +$ stratos-cli +``` + +Install with Pip + +``` +pip install stratos +``` + +or to install a specific version use + +``` +pip install stratos==1.0 +``` + + diff --git a/components/org.apache.stratos.python.cli/src/main/python/README.rst b/components/org.apache.stratos.python.cli/src/main/python/README.rst new file mode 100644 index 0000000000..b3427906f4 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/README.rst @@ -0,0 +1,75 @@ +================================================================================ + Apache Stratos CLI +================================================================================ + +Welcome to the Apache Stratos CLI. + +The command line interface (CLI) is a powerful tool that clients can use +to communicate with Stratos services. The CLI distribution only includes one +jar file containing all dependent java libraries. + +The tenant can use the CLI tool on two separate modes if needed, which +are namely single command line mode and interactive mode. + +If the user executes with a command as an argument, the CLI tool +will execute that command and exit with a status code. + +However, if there is no command as an argument, the CLI tool will +enter into an interactive mode. + +A user will be able to carryout all the following functions via the +CLI, with the exception of registering tenants and viewing logs. + +The CLI tool also supports command history and auto-completing features +in the interactive mode. + +Configuring CLI Tool +================================== +Configuration guide can be found at https://cwiki.apache.org/confluence/display/STRATOS/4.1.0+Configuring+CLI+Tool + +Help +================================== +usage: stratos [-debug] [-h] [-p ] [-trace] [-u ] + -debug Enable debug logging + -h,--help Display this help + -p,--password Password + -trace Enable trace logging + -u,--username Username + + +Available Commands: +create-tenant Add new tenant +list-autoscale-policies List available autoscale policies +subscribe-cartridge Subscribe to a cartridge +exit Exit from Stratos Client Tool +list-available-cartridges List available cartridges +help Help for commands +list-available-partitions List available partitions +deploy-cartridge Add new cartridge deployment +unsubscribe-cartridge Unsubscribe from a subscribed cartridge +list-subscribe-cartridges List subscribed cartridges with details +deploy-partition Add new partition deployment +deploy-autoscaling-policy Add new autoscaling policy deployment +deploy-deployment-policy Add new deployment policy + + +Support +================================== + +Any problem with this release can be reported to Apache Stratos mailing list +or in the JIRA issue tracker. If you are sending an email to the mailing +list make sure to add the [Apache Stratos] prefix to the subject. + +Mailing list subscription: + dev-subscribe@stratos.apache.org + + +Issue Tracker +================================== + +Jira: + https://issues.apache.org/jira/browse/stratos + + +Thank you for using Apache Stratos! +The Stratos Team diff --git a/components/org.apache.stratos.python.cli/src/main/python/cli/CLI.py b/components/org.apache.stratos.python.cli/src/main/python/cli/CLI.py new file mode 100755 index 0000000000..ea66bd380f --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/cli/CLI.py @@ -0,0 +1,1530 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from cmd2 import * +from Utils import * +from Stratos import * +import Configs +from cli.exceptions import BadResponseError + + +class CLI(Cmd): + """Apache Stratos CLI""" + + prompt = Configs.stratos_prompt + # resolving the '-' issue + Cmd.legalChars = '-' + Cmd.legalChars + + def __init__(self): + # resolving the '-' issue + [Cmd.shortcuts.update({a[3:].replace('_', '-'): a[3:]}) for a in self.get_names() if a.startswith('do_')] + Cmd.__init__(self) + + def completenames(self, text, *ignored): + # resolving the '-' issue + return [a[3:].replace('_', '-') for a in self.get_names() if a.replace('_', '-').startswith('do-'+text)] + + """ + + Stratos CLI specific methods + ==================================================================================================================== + + # User + * list-users + * add-user + * update-user + * remove-user + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_users(self, line , opts=None): + """Retrieve details of all users.""" + try: + users = Stratos.list_users() + table = PrintableTable() + rows = [["Username", "Role"]] + for user in users: + rows.append([user['userName'], user['role']]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-s', '--username_user', type="str", help="Username of the user"), + make_option('-a', '--password_user', type="str", help="Password of the user"), + make_option('-r', '--role_name', type="str", help="Role name of the user"), + make_option('-f', '--first_name', type="str", help="First name of the user"), + make_option('-l', '--last_name', type="str", help="Last name of the user"), + make_option('-e', '--email', type="str", help="Email of the user"), + make_option('-o', '--profile_name', type="str", help="Profile name of the user") + ]) + @auth + def do_add_user(self, line , opts=None): + """Add a user.""" + try: + if not opts.username_user or not opts.password_user: + print("usage: add-user [-s ] [-a ] [-r ] [-e ] [-f ]" + + " [-l ] [-o ]") + return + else: + user = Stratos.add_users(opts.username_user, opts.password_user, opts.role_name, opts.first_name, + opts.last_name, opts.email, opts.profile_name) + if user: + print("User successfully created") + else: + print("Error creating the user") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-s', '--username_user', type="str", help="Username of the user to be created"), + make_option('-a', '--password_user', type="str", help="Password of the user to be created"), + make_option('-r', '--role_name', type="str", help="Role name of the user to be created"), + make_option('-f', '--first_name', type="str", help="First name of the user to be created"), + make_option('-l', '--last_name', type="str", help="Last name of the user to be created"), + make_option('-e', '--email', type="str", help="Email of the user to be created"), + make_option('-o', '--profile_name', type="str", help="Profile name of the user to be created") + ]) + @auth + def do_update_user(self, line , opts=None): + """Update a specific user.""" + try: + user = Stratos.update_user(opts.username_user, opts.password_user, opts.role_name, opts.first_name, + opts.last_name, opts.email, opts.profile_name) + if user: + print("User successfully updated") + else: + print("Error updating the user") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_user(self, name , opts=None): + """Delete a user.""" + try: + if not name: + print("usage: remove-user [username]") + else: + user_removed = Stratos.remove_user(name) + if user_removed: + print("You have successfully deleted user: "+name) + else: + print("Could not delete user: "+name) + except BadResponseError as e: + self.perror(str(e)) + + """ + # Applications + * list-applications + * describe-application + * add-application + * update-application + * remove-application + * describe-application-runtime + * deploy-application + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_applications(self, line , opts=None): + """Retrieve details of all the applications.""" + try: + applications = Stratos.list_applications() + if not applications: + print("No applications found") + else: + table = PrintableTable() + rows = [["Application ID", "Alias", "Status"]] + for application in applications: + rows.append([application['applicationId'], application['alias'], application['status']]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_application(self, application_id , opts=None): + """Describe an application.""" + try: + if not application_id: + print("usage: describe-application [cluster-id]") + return + application = Stratos.describe_application(application_id) + if not application: + print("Application not found in : "+application_id) + else: + print("Application : "+application_id) + PrintableTree(application).print_tree() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_application(self, line , opts=None): + """Add an application.""" + try: + if not opts.json_file_path: + print("usage: add-application [-f ]") + else: + add_application = Stratos.add_application(open(opts.json_file_path, 'r').read()) + if add_application: + print("Application added successfully") + else: + print("Error adding application") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_update_application(self, application , opts=None): + """Update an application.""" + try: + if not opts.json_file_path: + print("usage: update-application [-f ] [application]") + else: + update_application = Stratos.update_application(application, open(opts.json_file_path, 'r').read()) + if update_application: + print("Application updated successfully") + else: + print("Error updating application") + except BadResponseError as e: + self.perror(str(e)) + + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_application(self, application , opts=None): + """Delete an application.""" + try: + if not application: + print("usage: remove-application [application]") + else: + application_removed = Stratos.remove_application(application) + if application_removed: + print("You have successfully removed application: "+application) + else: + print("Could not delete application : "+application) + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-a', '--application_id', type="str", help="Unique ID of the application"), + make_option('-o', '--application_policy_id', type="str", help="Unique ID of the application policy") + ]) + @auth + def do_deploy_application(self, line , opts=None): + """Deploy an application.""" + try: + if not opts.application_id or not opts.application_policy_id: + print("usage: deploy-application [-a ] [-o ]") + else: + application_removed = Stratos.deploy_application(opts.application_id, opts.application_policy_id) + if application_removed: + print("You have successfully deployed application: "+opts.application_id) + else: + print("Could not deployed application : "+opts.application_id) + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-a', '--application_id', type="str", help="Unique ID of the application"), + make_option('-o', '--application_policy_id', type="str", help="Unique ID of the application policy") + ]) + @auth + def do_undeploy_application(self, line , opts=None): + """Undeploy an application.""" + try: + if not opts.application_id or not opts.application_policy_id: + print("usage: undeploy-application [-a ] [-o ]") + else: + application_removed = Stratos.undeploy_application(opts.application_id, opts.application_policy_id) + if application_removed: + print("You have successfully undeployed application: "+opts.application_id) + else: + print("Could not undeployed application : "+opts.application_id) + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_application_runtime(self, application_id , opts=None): + """Describe the runtime topology of an application.""" + try: + if not application_id: + print("usage: describe-application-runtime [application-id]") + return + application_runtime = Stratos.describe_application_runtime(application_id) + if not application_runtime: + print("Application runtime not found") + else: + print("Application : "+application_id) + PrintableJSON(application_runtime).pprint() + except BadResponseError as e: + self.perror(str(e)) + + """ + # Application signup + * describe-application-signup + * add-application-signup + * remove-application-signup + + """ + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_application_signup(self, application_id , opts=None): + """Retrieve details of a specific application signup.""" + try: + if not application_id: + print("usage: describe-application-signup [application-id]") + return + application_signup = Stratos.describe_application_signup(application_id) + if not application_signup: + print("Application signup not found") + else: + PrintableJSON(application_signup).pprint() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_application_signup(self, application_id, opts=None): + """Add a new application signup to the system""" + try: + if not opts.json_file_path: + print("usage: add-application-signup [-f ] [application_id]") + else: + application_signup = Stratos.add_application_signup(application_id, open(opts.json_file_path, 'r').read()) + if application_signup: + print("Application signup added successfully") + else: + print("Error creating application signup") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_application_signup(self, signup , opts=None): + """Delete an application sign up.""" + try: + if not signup: + print("usage: remove-application-signup [signup]") + else: + signup_removed = Stratos.remove_application_signup(signup) + if signup_removed: + print("You have successfully remove signup: "+signup) + else: + print("Could not delete application signup: "+signup) + except BadResponseError as e: + self.perror(str(e)) + + """ + # Tenants + * list-tenants + * list-tenants-by-partial-domain + * describe-tenant + * add-tenant + * activate-tenant + * deactivate-tenant + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_tenants(self, line , opts=None): + """Retrieve details of all tenants.""" + try: + tenants = Stratos.list_tenants() + table = PrintableTable() + rows = [["Domain", "Tenant ID", "Email", " State", "Created Date"]] + for tenant in tenants: + rows.append([tenant['tenantDomain'], tenant['tenantId'], tenant['email'], + "Active" if tenant['active'] else "De-Active", datetime.datetime.fromtimestamp(tenant['createdDate']/1000).strftime('%Y-%m-%d %H:%M:%S')]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_tenants_by_partial_domain(self, partial_domain , opts=None): + """Search for tenants based on the partial domain value entered.""" + try: + tenants = Stratos.list_tenants_by_partial_domain(partial_domain) + table = PrintableTable() + rows = [["Domain", "Tenant ID", "Email", " State", "Created Date"]] + for tenant in tenants: + rows.append([tenant['tenantDomain'], tenant['tenantId'], tenant['email'], + "Active" if tenant['active'] else "De-Active", datetime.datetime.fromtimestamp(tenant['createdDate']/1000).strftime('%Y-%m-%d %H:%M:%S')]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_tenant(self, tenant_domain_name, opts=None): + """Retrieve details of a specific tenant.""" + if not tenant_domain_name: + print("usage: describe-tenant [Domain-Name]") + else: + try: + tenant = Stratos.describe_tenant(tenant_domain_name) + if not tenant: + print("Tenant not found") + else: + print("-------------------------------------") + print("Tenant Information:") + print("-------------------------------------") + print("Tenant domain: "+tenant['tenantDomain']) + print("ID: "+str(tenant['tenantId'])) + print("Active: "+str(tenant['active'])) + print("Email: "+tenant['email']) + print("Created date: "+datetime.datetime.fromtimestamp(tenant['createdDate']/1000).strftime('%Y-%m-%d %H:%M:%S')) + print("-------------------------------------") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-s', '--username_user', type="str", help="Username of the tenant"), + make_option('-a', '--password_user', type="str", help="Password of the tenant"), + make_option('-d', '--domain_name', type="str", help="domain name of the tenant"), + make_option('-f', '--first_name', type="str", help="First name of the tenant"), + make_option('-l', '--last_name', type="str", help="Last name of the tenant"), + make_option('-e', '--email', type="str", help="Email of the tenant") + ]) + @auth + def do_add_tenant(self, line , opts=None): + """Add a tenant.""" + try: + tenant = Stratos.add_tenant(opts.username_user, opts.first_name, opts.last_name, opts.password_user, + opts.domain_name, opts.email) + if tenant: + print("Tenant added successfully : "+opts.domain_name) + else: + print("Error creating the tenant : "+opts.domain_name) + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-s', '--username_user', type="str", help="Username of the tenant"), + make_option('-a', '--password_user', type="str", help="Password of the tenant"), + make_option('-d', '--domain_name', type="str", help="domain name of the tenant"), + make_option('-f', '--first_name', type="str", help="First name of the tenant"), + make_option('-l', '--last_name', type="str", help="Last name of the tenant"), + make_option('-e', '--email', type="str", help="Email of the tenant"), + make_option('-i', '--tenant_id', type="str", help="ID of the tenant") + ]) + @auth + def do_update_tenant(self, line , opts=None): + """Update a specific tenant.""" + try: + tenant = Stratos.update_tenant(opts.username_user, opts.first_name, opts.last_name, opts.password_user, + opts.domain_name, opts.email, opts.tenant_id) + if tenant: + print("Tenant updated successfully : "+opts.domain_name) + else: + print("Error updating the tenant : "+opts.domain_name) + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_activate_tenant(self, tenant_domain, opts=None): + """Activate a tenant.""" + try: + if not tenant_domain: + print("usage: activate-tenant ") + else: + activate_tenant = Stratos.activate_tenant(tenant_domain) + if activate_tenant: + print("You have successfully activated the tenant : "+tenant_domain) + else: + print("Could not activate tenant : "+tenant_domain) + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_deactivate_tenant(self, tenant_domain, opts=None): + """Deactivate a tenant.""" + try: + if not tenant_domain: + print("usage: deactivate-tenant ") + else: + activate_tenant = Stratos.deactivate_tenant(tenant_domain) + if activate_tenant: + print("You have successfully deactivated the tenant : "+tenant_domain) + else: + print("Could not deactivate tenant : "+tenant_domain) + except BadResponseError as e: + self.perror(str(e)) + + """ + # Cartridges + * list-cartridges + * list-cartridges-by-filter + * describe-cartridge + * add-cartridge + * remove-cartridge + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_cartridges(self, line , opts=None): + """Retrieve details of available cartridges.""" + try: + cartridges = Stratos.list_cartridges() + table = PrintableTable() + rows = [["Type", "Category", "Name", "Description", "Version", "Multi-Tenant"]] + for cartridge in cartridges: + rows.append([cartridge['type'], cartridge['category'], cartridge['displayName'], cartridge['description'], + cartridge['version'], "True" if cartridge['multiTenant'] == 1 else "False"]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_cartridges_by_filter(self, filter_text , opts=None): + """Retrieve details of available cartridges.""" + try: + if not filter_text: + print("usage: describe-cartridge-by-filter [filter]") + else: + cartridges = Stratos.list_cartridges_by_filter(filter_text) + table = PrintableTable() + rows = [["Type", "Category", "Name", "Description", "Version", "Multi-Tenant"]] + for cartridge in cartridges: + rows.append([cartridge['type'], cartridge['category'], cartridge['displayName'], cartridge['description'], + cartridge['version'], "True" if cartridge['multiTenant'] == 1 else "False"]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_cartridge(self, cartridge_type, opts=None): + """Retrieve details of a specific cartridge.""" + if not cartridge_type: + print("usage: describe-cartridge [cartridge-type]") + else: + try: + cartridge = Stratos.describe_cartridge(cartridge_type) + if not cartridge: + print("Cartridge not found") + else: + print("-------------------------------------") + print("Cartridge Information:") + print("-------------------------------------") + print("Type: "+cartridge['type']) + print("Category: "+cartridge['category']) + print("Name: "+cartridge['displayName']) + print("Description: "+cartridge['description']) + print("Version: "+str(cartridge['version'])) + print("Multi-Tenant: "+str(cartridge['multiTenant'])) + print("Host Name: "+cartridge['host']) + print("-------------------------------------") + except requests.HTTPError as e: + self.perror(str(e)) + + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_cartridge(self, line , opts=None): + """Add a cartridge definition.""" + try: + if not opts.json_file_path: + print("usage: add-cartridge [-f ]") + else: + cartridge = Stratos.add_cartridge(open(opts.json_file_path, 'r').read()) + if cartridge: + print("Cartridge added successfully") + else: + print("Error adding Cartridge") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_update_cartridge(self, line , opts=None): + """Update a cartridge""" + try: + if not opts.json_file_path: + print("usage: update-cartridge [-f ]") + else: + cartridge = Stratos.update_cartridge(open(opts.json_file_path, 'r').read()) + if cartridge: + print("Cartridge updated successfully") + else: + print("Error updating Cartridge") + except BadResponseError as e: + self.perror(str(e)) + + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_cartridge(self, cartridge_type , opts=None): + """Delete a cartridge""" + try: + if not cartridge_type: + print("usage: remove-cartridge [cartridge-type]") + else: + cartridge_removed = Stratos.remove_cartridge(cartridge_type) + if cartridge_removed: + print("Successfully un-deployed cartridge : "+cartridge_type) + else: + print("Could not un-deployed cartridge : "+cartridge_type) + except BadResponseError as e: + self.perror(str(e)) + + """ + # Cartridge groups + * list-cartridge-groups + * describe-cartridge-group + * add-cartridge-group + * remove-cartridge-group + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_cartridge_groups(self, line , opts=None): + """Retrieve details of all the cartridge groups.""" + try: + cartridge_groups = Stratos.list_cartridge_groups() + if not cartridge_groups: + print("No cartridge groups found") + else: + table = PrintableTable() + rows = [["Name", "No. of cartridges", "No of groups"]] + for cartridge_group in cartridge_groups: + rows.append([cartridge_group['name'], len(cartridge_group['cartridges']), + len(cartridge_group['cartridges'])]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_cartridge_group(self, group_definition_name , opts=None): + """Retrieve details of a cartridge group.""" + try: + if not group_definition_name: + print("usage: describe-cartridge-group [cartridge-group-name]") + return + cartridge_group = Stratos.describe_cartridge_group(group_definition_name) + if not cartridge_group: + print("Cartridge group not found") + else: + print("Service Group : "+group_definition_name) + PrintableJSON(cartridge_group).pprint() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_cartridge_group(self, line , opts=None): + """Add a cartridge group.""" + try: + if not opts.json_file_path: + print("usage: add-cartridge-group [-f ]") + else: + cartridge_group = Stratos.add_cartridge_group(open(opts.json_file_path, 'r').read()) + if cartridge_group: + print("Cartridge group added successfully") + else: + print("Error adding Cartridge group") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_update_cartridge_group(self, line , opts=None): + """Add a new user to the system""" + try: + if not opts.json_file_path: + print("usage: update-cartridge-group [-f ]") + else: + cartridge = Stratos.update_cartridge_group(open(opts.json_file_path, 'r').read()) + if cartridge: + print("Cartridge group updated successfully") + else: + print("Error updating Cartridge group") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_cartridge_group(self, group_definition_name , opts=None): + """Delete a cartridge group.""" + try: + if not group_definition_name: + print("usage: remove-cartridge-group [cartridge-group-name]") + else: + cartridge_removed = Stratos.remove_cartridge_group(group_definition_name) + if cartridge_removed: + print("Successfully un-deployed cartridge group : "+group_definition_name) + else: + print("Could not un-deployed cartridge group : "+group_definition_name) + except BadResponseError as e: + self.perror(str(e)) + + """ + # Deployment Policies + * list-deployment-policies + * describe-deployment-policy + * add-deployment-policy + * update-deployment-policy + * remove-deployment-policy + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_deployment_policies(self, line , opts=None): + """Retrieve details of a deployment policy.""" + try: + deployment_policies = Stratos.list_deployment_policies() + if not deployment_policies: + print("No deployment policies found") + else: + table = PrintableTable() + rows = [["Id", "Accessibility"]] + for deployment_policy in deployment_policies: + rows.append([deployment_policy['id'], len(deployment_policy['networkPartitions'])]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_deployment_policy(self, line , opts=None): + """Describe a deployment policy.""" + try: + if not line: + print("usage: describe-deployment-policy [deployment-policy-id]") + return + deployment_policy = Stratos.describe_deployment_policy(line) + if not deployment_policy: + print("Deployment policy not found") + else: + PrintableJSON(deployment_policy).pprint() + except BadResponseError as e: + self.perror(str(e)) + + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_deployment_policy(self, line , opts=None): + """Add a deployment policy definition.""" + try: + if not opts.json_file_path: + print("usage: add-deployment-policy [-f ]") + else: + deployment_policy = Stratos.add_deployment_policy(open(opts.json_file_path, 'r').read()) + if deployment_policy: + print("Deployment policy added successfully") + else: + print("Error creating deployment policy") + except BadResponseError as e: + self.perror(str(e)) + + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_update_deployment_policy(self, line , opts=None): + """Update a deployment policy.""" + try: + if not opts.json_file_path: + print("usage: update-deployment-policy [-f ]") + else: + cartridge = Stratos.update_deployment_policy(open(opts.json_file_path, 'r').read()) + if cartridge: + print("Deployment policy updated successfully") + else: + print("Error updating Deployment policy") + except BadResponseError as e: + self.perror(str(e)) + + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_deployment_policy(self, deployment_policy_id , opts=None): + """Delete a deployment policy.""" + try: + if not deployment_policy_id: + print("usage: remove-deployment-policy [deployment-policy-id]") + else: + cartridge_removed = Stratos.remove_deployment_policy(deployment_policy_id) + if cartridge_removed: + print("Successfully deleted deployment policy : "+deployment_policy_id) + else: + print("Could not deleted deployment policy : "+deployment_policy_id) + except BadResponseError as e: + self.perror(str(e)) + + + """ + # Deployment Policies + * list-application-policies + * describe-application-policy + * update-application-policy + * remove-application-policy + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_application_policies(self, line , opts=None): + """Retrieve details of all the application policies.""" + try: + application_policies = Stratos.list_application_policies() + if not application_policies: + print("No application policies found") + else: + table = PrintableTable() + rows = [["Id", "Accessibility"]] + for application_policy in application_policies: + rows.append([application_policy['id'], len(application_policy['networkPartitions'])]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_application_policy(self, application_policy_id , opts=None): + """Retrieve details of a specific application policy.""" + try: + if not application_policy_id: + print("usage: describe-application-policy [application-policy-id]") + return + application_policy = Stratos.describe_application_policy(application_policy_id) + if not application_policy: + print("Deployment policy not found") + else: + PrintableJSON(application_policy).pprint() + except BadResponseError as e: + self.perror(str(e)) + + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_application_policy(self, line , opts=None): + """Add an application policy.""" + try: + if not opts.json_file_path: + print("usage: add-application-policy [-f ]") + else: + application_policy = Stratos.add_application_policy(open(opts.json_file_path, 'r').read()) + if application_policy: + print("Deployment policy added successfully") + else: + print("Error creating application policy") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_update_application_policy(self, line , opts=None): + """Update an application policy.""" + try: + if not opts.json_file_path: + print("usage: update-application-policy [-f ]") + else: + cartridge = Stratos.update_application_policy(open(opts.json_file_path, 'r').read()) + if cartridge: + print("Deployment policy updated successfully") + else: + print("Error updating Deployment policy") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_application_policy(self, application_policy_id , opts=None): + """Delete an application policy.""" + try: + if not application_policy_id: + print("usage: remove-application-policy [application-policy-id]") + else: + cartridge_removed = Stratos.remove_application_policy(application_policy_id) + if cartridge_removed: + print("Successfully deleted application policy : "+application_policy_id) + else: + print("Could not deleted application policy : "+application_policy_id) + except BadResponseError as e: + self.perror(str(e)) + + """ + # Network Partitions + * list-network-partitions + * describe-network-partition + * add-network-partition + * update-network-partition + * remove-network-partition + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_network_partitions(self, line , opts=None): + """Retrieve details of all the network partitions.""" + try: + network_partitions = Stratos.list_network_partitions() + table = PrintableTable() + rows = [["Network Partition ID", "Number of Partitions"]] + for network_partition in network_partitions: + rows.append([network_partition['id'], len(network_partition['partitions'])]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_network_partition(self, network_partition_id , opts=None): + """Describe a network partition.""" + try: + if not network_partition_id: + print("usage: describe-network-partition [network-partition]") + return + deployment_policy = Stratos.describe_network_partition(network_partition_id) + if not deployment_policy: + print("Network partition not found: "+network_partition_id) + else: + print("Partition: "+network_partition_id) + PrintableJSON(deployment_policy).pprint() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_network_partition(self, line , opts=None): + """Add a new network partition.""" + try: + if not opts.json_file_path: + print("usage: add-network-partition [-f ]") + else: + tenant = Stratos.add_network_partition(open(opts.json_file_path, 'r').read()) + if tenant: + print("Network partition added successfully") + else: + print("Error creating network partition") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_update_network_partition(self, line , opts=None): + """Update a specific network partition.""" + try: + if not opts.json_file_path: + print("usage: update-network-partition [-f ]") + else: + cartridge = Stratos.update_network_partition(open(opts.json_file_path, 'r').read()) + if cartridge: + print("Network partition updated successfully") + else: + print("Error updating Network partition") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_network_partition(self, network_partition_id, opts=None): + """Delete a network partition.""" + try: + if not network_partition_id: + print("usage: remove-network-partition [network-partition-id]") + else: + cartridge_removed = Stratos.remove_network_partition(network_partition_id) + if cartridge_removed: + print("Successfully deleted network-partition : "+network_partition_id) + else: + print("Could not deleted network-partition : "+network_partition_id) + except BadResponseError as e: + self.perror(str(e)) + + """ + # Auto-scaling policies + * list-autoscaling-policies + * describe-autoscaling-policy + * add-autoscaling-policy + * update-autoscaling-policy + * remove-autoscaling-policy + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_autoscaling_policies(self, line , opts=None): + """Retrieve details of auto-scaling policies.""" + try: + autoscaling_policies = Stratos.list_autoscaling_policies() + if not autoscaling_policies: + print("No autoscaling policies found") + else: + table = PrintableTable() + rows = [["Id", "Accessibility"]] + for autoscaling_policy in autoscaling_policies: + rows.append([autoscaling_policy['id'], "Public" if autoscaling_policy['isPublic'] else "Private"]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_autoscaling_policy(self, autoscaling_policy_id , opts=None): + """Retrieve details of a specific auto-scaling policy.""" + try: + if not autoscaling_policy_id: + print("usage: describe-autoscaling-policy [autoscaling-policy-id]") + return + autoscaling_policy = Stratos.describe_autoscaling_policy(autoscaling_policy_id) + if not autoscaling_policy: + print("Autoscaling policy not found : "+autoscaling_policy_id) + else: + print("Autoscaling policy : "+autoscaling_policy_id) + PrintableJSON(autoscaling_policy).pprint() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_autoscaling_policy(self, line , opts=None): + """Add an auto-scaling policy definition.""" + try: + if not opts.json_file_path: + print("usage: add-autoscaling-policy [-f ]") + else: + autoscaling_policy = Stratos.add_autoscaling_policy(open(opts.json_file_path, 'r').read()) + if autoscaling_policy: + print("Autoscaling policy added successfully") + else: + print("Error adding autoscaling policy") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_update_autoscaling_policy(self, line , opts=None): + """Update an auto-scaling policy.""" + try: + if not opts.json_file_path: + print("usage: update-autoscaling-policy [-f ]") + else: + autoscaling_policy = Stratos.update_autoscaling_policy(open(opts.json_file_path, 'r').read()) + if autoscaling_policy: + print("Autoscaling policy updated successfully:") + else: + print("Error updating Autoscaling policy") + except BadResponseError as e: + self.perror(str(e)) + + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_autoscaling_policy(self, autoscaling_policy_id , opts=None): + """Delete an autoscaling_policy.""" + try: + if not autoscaling_policy_id: + print("usage: remove-autoscaling-policy [application-id]") + else: + autoscaling_policy_removed = Stratos.remove_autoscaling_policy(autoscaling_policy_id) + if autoscaling_policy_removed: + print("Successfully deleted Auto-scaling policy : "+autoscaling_policy_id) + else: + print("Auto-scaling policy not found : "+autoscaling_policy_id) + except BadResponseError as e: + self.perror(str(e)) + + + """ + # Kubernetes clusters/hosts + * list-kubernetes-clusters + * describe-kubernetes-cluster + * describe-kubernetes-master + * add-kubernetes-cluster + * add-kubernetes-host + * list-kubernetes-hosts + * update-kubernetes-host + * update-kubernetes-master + * remove-kubernetes-cluster + * remove-kubernetes-host + + """ + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_kubernetes_clusters(self, line , opts=None): + """Retrieving details of all Kubernetes-CoreOS Clusters.""" + try: + kubernetes_clusters = Stratos.list_kubernetes_clusters() + if not kubernetes_clusters: + print("No Kubernetes clusters found") + else: + table = PrintableTable() + rows = [["Group ID", "Description"]] + for kubernetes_cluster in kubernetes_clusters: + rows.append([kubernetes_cluster['clusterId'], kubernetes_cluster['description']]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_kubernetes_cluster(self, kubernetes_cluster_id, opts=None): + """Describe a Kubernetes-CoreOS Cluster.""" + try: + if not kubernetes_cluster_id: + print("usage: describe-kubernetes-cluster [cluster-i]]") + return + kubernetes_cluster = Stratos.describe_kubernetes_cluster(kubernetes_cluster_id) + if not kubernetes_cluster: + print("Kubernetes cluster not found") + else: + print("Kubernetes cluster: "+kubernetes_cluster_id) + PrintableJSON(kubernetes_cluster).pprint() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_describe_kubernetes_master(self, kubernetes_cluster_id , opts=None): + """Retrieve details of the master in a Kubernetes-CoreOS Cluster.""" + try: + if not kubernetes_cluster_id: + print("usage: describe-kubernetes-master [cluster-id]") + return + kubernetes_master = Stratos.describe_kubernetes_master(kubernetes_cluster_id) + if not kubernetes_master: + print("Kubernetes master not found in : "+kubernetes_cluster_id) + else: + print("Cluster : "+kubernetes_cluster_id) + PrintableJSON(kubernetes_master).pprint() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_kubernetes_cluster(self, opts=None): + """Add a Kubernetes-CoreOS Cluster.""" + try: + if not opts.json_file_path: + print("usage: add-kubernetes-cluster [-f ]") + else: + kubernetes_cluster = Stratos.add_kubernetes_cluster(open(opts.json_file_path, 'r').read()) + if kubernetes_cluster: + print("You have successfully deployed the Kubernetes cluster") + else: + print("Error deploying the Kubernetes cluster ") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_kubernetes_host(self, kubernetes_cluster_id , opts=None): + """Add a host to a Kubernetes-CoreOS Cluster.""" + try: + if not kubernetes_cluster_id or not opts.json_file_path: + print("usage: add-kubernetes-host [-f ] [kubernetes cluster id]") + else: + kubernetes_host = Stratos.add_kubernetes_host(kubernetes_cluster_id, open(opts.json_file_path, 'r').read()) + if kubernetes_host: + print("You have successfully deployed host to Kubernetes cluster: "+kubernetes_cluster_id) + else: + print("Error deploying host to Kubernetes cluster: "+kubernetes_cluster_id) + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-c', '--cluster_id', type="str", help="Cluster ID") + ]) + def do_list_kubernetes_hosts(self, line , opts=None): + """Retrieve details of all hosts of a Kubernetes-CoreOS Cluster.""" + try: + if not opts.cluster_id: + print("usage: list-kubernetes-hosts [-c ]") + return + kubernetes_cluster_hosts = Stratos.list_kubernetes_hosts(opts.cluster_id) + if not kubernetes_cluster_hosts: + print("No kubernetes hosts found") + else: + table = PrintableTable() + rows = [["Host ID", "Hostname", "Private IP Address", "Public IP Address"]] + for kubernetes_cluster_host in kubernetes_cluster_hosts: + rows.append([kubernetes_cluster_host['hostId'], kubernetes_cluster_host['hostname'], + kubernetes_cluster_host['privateIPAddress'], kubernetes_cluster_host['publicIPAddress']]) + table.add_rows(rows) + table.print_table() + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-c', '--cluster_id', type="str", help="Cluster id of the cluster"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_update_kubernetes_master(self, line , opts=None): + """Update the master node of the Kubernetes-CoreOS Cluster.""" + try: + if not opts.json_file_path: + print("usage: update-kubernetes-master [-c ] [-p ]") + else: + cartridge = Stratos.update_kubernetes_master(opts.cluster_id, open(opts.json_file_path, 'r').read()) + if cartridge: + print("Kubernetes master updated successfully") + else: + print("Error updating Kubernetes master") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_update_kubernetes_host(self, line , opts=None): + """Update the host of a Kubernetes-CoreOS Cluster.""" + try: + if not opts.json_file_path: + print("usage: update-kubernetes-host [-f ]") + else: + cartridge = Stratos.update_kubernetes_host(open(opts.json_file_path, 'r').read()) + if cartridge: + print(cartridge) + print("You have succesfully updated host to Kubernetes cluster") + else: + print("Error updating Kubernetes host") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_kubernetes_cluster(self, kubernetes_cluster_id, opts=None): + """Delete a Kubernetes-CoreOS Cluster.""" + try: + if not kubernetes_cluster_id: + print("usage: remove-kubernetes-cluster [cluster-id]") + else: + kubernetes_cluster_removed = Stratos.remove_kubernetes_cluster(kubernetes_cluster_id) + if kubernetes_cluster_removed: + print("Successfully un-deployed kubernetes cluster : "+kubernetes_cluster_id) + else: + print("Kubernetes cluster not found : "+kubernetes_cluster_id) + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-c', '--cluster_id', type="str", help="Cluster id of Kubernets cluster"), + make_option('-o', '--host_id', type="str", help="Host id of Kubernets cluster") + ]) + @auth + def do_remove_kubernetes_host(self, line, opts=None): + """Delete the host of a Kubernetes-CoreOS Cluster.""" + try: + if not opts.cluster_id or not opts.host_id: + print("usage: remove-kubernetes-host [-c cluster-id] [-o host-id]") + else: + kubernetes_host_removed = Stratos.remove_kubernetes_host(opts.cluster_id, opts.host_id) + if kubernetes_host_removed: + print("Successfully un-deployed kubernetes host : "+opts.host_id) + else: + print("Kubernetes host not found : "+opts.cluster_id+"/"+opts.host_id) + except BadResponseError as e: + self.perror(str(e)) + + """ + # Domain Mapping + * list-domain-mappings + * add-domain-mapping + * remove-domain-mapping + + """ + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_list_domain_mappings(self, application_id , opts=None): + """Retrieve details of domain mappings of an application.""" + try: + if not application_id: + print("usage: list-domain-mappings [application-id]") + else: + domain_mappings = Stratos.list_domain_mappings(application_id) + if domain_mappings: + table = PrintableTable() + rows = [["Domain", "Tenant ID", "Email", " State", "Created Date"]] + for domain_mapping in domain_mappings: + rows.append([domain_mapping['domain_mappingsDomain'], domain_mapping['domain_mappingId'], domain_mapping['email'], + "Active" if domain_mapping['active'] else "De-Active", datetime.datetime.fromtimestamp(domain_mapping['createdDate']/1000).strftime('%Y-%m-%d %H:%M:%S')]) + table.add_rows(rows) + table.print_table() + else: + print("No domain mappings found in application: "+application_id) + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user"), + make_option('-f', '--json_file_path', type="str", help="Path of the JSON file") + ]) + @auth + def do_add_domain_mapping(self, application_id, opts=None): + """Map domain to a subscribed cartridge.""" + try: + if not application_id or not opts.json_file_path: + print("usage: add-domain-mapping [-f ] [application id]") + else: + domain_mapping = Stratos.add_domain_mapping(application_id, open(opts.json_file_path, 'r').read()) + if domain_mapping: + print(" Domain mapping added successfully") + else: + print("Error creating domain mapping") + except BadResponseError as e: + self.perror(str(e)) + + @options([ + make_option('-u', '--username', type="str", help="Username of the user"), + make_option('-p', '--password', type="str", help="Password of the user") + ]) + @auth + def do_remove_domain_mappings(self, domain , opts=None): + """Remove domain mappings of an application.""" + try: + if not domain: + print("usage: remove-domain-mappings [domain]") + else: + domain_removed = Stratos.remove_domain_mappings(domain) + if domain_removed: + print("You have successfully deleted domain: "+domain) + else: + print("Could not delete domain: "+domain) + except BadResponseError as e: + self.perror(str(e)) + diff --git a/components/org.apache.stratos.python.cli/src/main/python/cli/Configs.py b/components/org.apache.stratos.python.cli/src/main/python/cli/Configs.py new file mode 100644 index 0000000000..bc813a48ad --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/cli/Configs.py @@ -0,0 +1,31 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 os + +stratos_prompt = "stratos> " + +stratos_dir = "~/.stratos" +log_file_name = "stratos-cli.log" + +stratos_dir_path = os.path.expanduser(stratos_dir) +log_file_path = os.path.join(stratos_dir_path, log_file_name) + +stratos_url = os.getenv('STRATOS_URL', "https://localhost:9443/") +stratos_api_url = stratos_url + "api/" +stratos_username = os.getenv('STRATOS_USERNAME', "") +stratos_password = os.getenv('STRATOS_PASSWORD', "") diff --git a/components/org.apache.stratos.python.cli/src/main/python/cli/Logging.py b/components/org.apache.stratos.python.cli/src/main/python/cli/Logging.py new file mode 100644 index 0000000000..3caa892b1c --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/cli/Logging.py @@ -0,0 +1,29 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 logging +import os +import Configs + +if not os.path.exists(Configs.stratos_dir_path): + try: + os.makedirs(Configs.stratos_dir_path) + logging.info("Created directory: "+Configs.stratos_dir_path) + except OSError: + logging.warning("Failed to create directory: "+Configs.stratos_dir_path) + +logging.basicConfig(filename=Configs.log_file_path, level=logging.DEBUG) diff --git a/components/org.apache.stratos.python.cli/src/main/python/cli/Main.py b/components/org.apache.stratos.python.cli/src/main/python/cli/Main.py new file mode 100755 index 0000000000..707e4a91e6 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/cli/Main.py @@ -0,0 +1,66 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 sys +import readline +import getpass +from CLI import CLI +import Configs + +# Fix Python 2.x. +from cli.Stratos import Stratos +from cli.exceptions import BadResponseError + +try: + input = raw_input +except NameError: + pass + + +def prompt_for_credentials(): + """Prompt for user credentials""" + while Configs.stratos_username is "" or Configs.stratos_password is "": + if Configs.stratos_username is "": + Configs.stratos_username = input("Username: ") + + if Configs.stratos_password is "": + Configs.stratos_password = getpass.getpass("Password: ") + if Stratos.authenticate(): + print("Successfully authenticated") + else: + print("Could not authenticate") + exit() + + + +def main(): + # resolving the '-' issue + readline.set_completer_delims(readline.get_completer_delims().replace('-', '')) + + cli = CLI() + + if len(sys.argv) > 1: + try: + cli.onecmd(' '.join(sys.argv[1:])) + except BadResponseError as e: + print(str(e)) + else: + prompt_for_credentials() + cli.cmdloop() + +if __name__ == '__main__': + main() diff --git a/components/org.apache.stratos.python.cli/src/main/python/cli/Stratos.py b/components/org.apache.stratos.python.cli/src/main/python/cli/Stratos.py new file mode 100755 index 0000000000..ebb3b8eddf --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/cli/Stratos.py @@ -0,0 +1,482 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 requests +import json +import Configs +from Logging import logging +from cli.exceptions.BadResponseError import BadResponseError + + +class Stratos: + """Apache Stratos Python API""" + + def __init__(self): + pass + + """ + # Users + * list-users + * add-users + * update-users + * remove-user + + """ + @staticmethod + def list_users(): + return Stratos.get('users') + + @staticmethod + def add_users(username, password, role_name, first_name, last_name, email, profile_name): + data = { + "userName": username, + "credential": password, + "role": role_name, + "firstName": first_name, + "lastName": last_name, + "email": email + } + return Stratos.post('users', json.dumps(data)) + + @staticmethod + def update_user(username, password, role_name, first_name, last_name, email, profile_name): + data = { + "userName": username, + "credential": password, + "role": role_name, + "firstName": first_name, + "lastName": last_name, + "email": email + } + return Stratos.put('users', json.dumps(data)) + + @staticmethod + def remove_user(name): + return Stratos.delete('users/'+name) + + """ + # Applications + * list-applications + * describe-applications + * add-application + * remove-application + * deploy-application + * describe-application-runtime + + """ + @staticmethod + def list_applications(): + return Stratos.get('applications') + + @staticmethod + def describe_application(application_id): + return Stratos.get('applications/'+application_id) + + @staticmethod + def add_application(json): + return Stratos.post('applications', json) + + @staticmethod + def update_application(application_id, json): + return Stratos.put('applications/'+application_id, json) + + @staticmethod + def remove_application(application): + return Stratos.delete('applications/'+application) + + @staticmethod + def deploy_application(application_id, application_policy_id): + return Stratos.post('applications/'+application_id+'/deploy/'+application_policy_id, None) + + @staticmethod + def deploy_application(application_id, application_policy_id): + return Stratos.post('applications/'+application_id+'/undeploy/'+application_policy_id, None) + @staticmethod + def describe_application_runtime(application_id): + return Stratos.get('applications/'+application_id+"/runtime") + + """ + # Application signup + * describe-application-signup + * remove-application-signup + + """ + @staticmethod + def describe_application_signup(application_id): + return Stratos.get('applications/'+application_id+'/signup') + @staticmethod + def add_application_signup(application_id, json): + return Stratos.post('applications/'+application_id+"/runtime", json) + + @staticmethod + def remove_application_signup(application_id): + return Stratos.delete('applications/'+application_id + '/signup') + + """ + # Tenants + * list-tenants + * list-tenants-by-partial-domain + * describe-tenant + * add-tenant + * activate-tenant + * deactivate-tenant + + """ + @staticmethod + def list_tenants(): + return Stratos.get('tenants') + + @staticmethod + def list_tenants_by_partial_domain(partial_domain): + return Stratos.get('tenants/search/'+partial_domain) + + @staticmethod + def describe_tenant(tenant_domain_name): + return Stratos.get('tenants/'+tenant_domain_name) + + @staticmethod + def add_tenant(username, first_name, last_name, password, domain_name, email): + data = { + "admin": username, + "firstName": first_name, + "lastName": last_name, + "adminPassword": password, + "tenantDomain": domain_name, + "email": email, + "active": "true" + } + return Stratos.post('tenants', json.dumps(data)) + + @staticmethod + def update_tenant(username, first_name, last_name, password, domain_name, email, tenant_id): + data = { + "tenantId": tenant_id, + "admin": username, + "firstName": first_name, + "lastName": last_name, + "adminPassword": password, + "tenantDomain": domain_name, + "email": email, + "active": "true" + } + return Stratos.put('tenants', json.dumps(data)) + + @staticmethod + def activate_tenant(tenant_domain): + return Stratos.put('tenants/activate/'+tenant_domain, "") + + @staticmethod + def deactivate_tenant(tenant_domain): + return Stratos.put('tenants/deactivate/'+tenant_domain, "") + + """ + # Cartridges + * list-cartridges + * describe-cartridge + * add-cartridge + * remove-cartridges + + """ + @staticmethod + def list_cartridges(): + return Stratos.get('cartridges') + + @staticmethod + def list_cartridges_by_filter(filter_text): + return Stratos.get('cartridges/filter/'+filter_text) + + @staticmethod + def describe_cartridge(cartridge_type): + return Stratos.get('cartridges/'+cartridge_type) + + @staticmethod + def add_cartridge(json): + return Stratos.post('cartridges', json) + + @staticmethod + def update_cartridge(json): + return Stratos.put('cartridges', json) + + @staticmethod + def remove_cartridge(cartridge_type): + return Stratos.delete('cartridges/'+cartridge_type) + + """ + # Cartridge groups + * list-cartridge-groups + * describe-cartridge-group + * update-cartridges-group + * remove-cartridges-group + + """ + + @staticmethod + def list_cartridge_groups(): + return Stratos.get('cartridgeGroups') + + @staticmethod + def describe_cartridge_group(group_definition_name): + return Stratos.get('cartridgeGroups/'+group_definition_name) + + @staticmethod + def add_cartridge_group(json): + return Stratos.post('cartridgeGroups', json) + + @staticmethod + def update_cartridge_group(json): + return Stratos.put('cartridgeGroups', json) + + @staticmethod + def remove_cartridge_group(group_definition_name): + return Stratos.delete('cartridgeGroups/'+group_definition_name) + + """ + # Deployment Policy + * list-deployment-policies + * describe-deployment-policy + * add-deployment-policy + * update-deployment-policy + * remove-deployment-policy + + """ + @staticmethod + def list_deployment_policies(): + return Stratos.get('deploymentPolicies') + @staticmethod + def describe_deployment_policy(deployment_policy_name): + return Stratos.get('deploymentPolicies/'+ deployment_policy_name) + @staticmethod + def add_deployment_policy(json): + return Stratos.post('deploymentPolicies', json) + + @staticmethod + def update_deployment_policy(json): + return Stratos.put('deploymentPolicies', json) + + @staticmethod + def remove_deployment_policy(deployment_policy_id): + return Stratos.delete('deploymentPolicies/'+deployment_policy_id) + + """ + # Application Policy + * list-application-policies + * describe-application-policy + * update-application-policy + * remove-application-policy + + """ + @staticmethod + def list_application_policies(): + return Stratos.get('applicationPolicies') + @staticmethod + def describe_application_policy(application_policy_name): + return Stratos.get('applicationPolicies/'+ application_policy_name) + @staticmethod + def update_application_policy(json): + return Stratos.put('applicationPolicies', json) + + @staticmethod + def remove_application_policy(application_policy_id): + return Stratos.delete('applicationPolicies/'+application_policy_id) + + """ + # Network partitions + * list-network-partitions + * describe-network-partition + * add-network-partition + * update-network-partition + * remove-network-partition + + """ + @staticmethod + def list_network_partitions(): + return Stratos.get('networkPartitions') + + @staticmethod + def describe_network_partition(network_partition_id): + return Stratos.get('networkPartitions/'+network_partition_id) + @staticmethod + def add_network_partition(json): + return Stratos.post('networkPartitions', json) + @staticmethod + def update_network_partition(json): + return Stratos.put('networkPartitions', json) + + + @staticmethod + def remove_network_partition(network_partition_id): + return Stratos.delete('networkPartitions/'+network_partition_id) + + """ + # Auto-scaling policies + * list-autoscaling-policies + * describe-autoscaling-policy + * add-autoscaling-policy + * update-autoscaling-policy + * remove-autoscaling-policy + + """ + @staticmethod + def list_autoscaling_policies(): + return Stratos.get('autoscalingPolicies') + @staticmethod + def describe_autoscaling_policy(autoscaling_policy_id): + return Stratos.get('autoscalingPolicies/'+autoscaling_policy_id) + + @staticmethod + def add_autoscaling_policy(json): + return Stratos.post('autoscalingPolicies', json) + + @staticmethod + def update_autoscaling_policy(json): + return Stratos.put('autoscalingPolicies', json) + + @staticmethod + def remove_autoscaling_policy(autoscaling_policy_id): + return Stratos.delete('autoscalingPolicies/'+autoscaling_policy_id) + + """ + # Kubernetes clusters/hosts + * list-kubernetes-clusters + * describe-kubernetes-cluster + * describe-kubernetes-master + * add-kubernetes-cluster + * list-kubernetes-hosts + * update-kubernetes-host + * update-kubernetes-master + * remove-kubernetes-cluster + * remove-kubernetes-host + + """ + @staticmethod + def list_kubernetes_clusters(): + return Stratos.get('kubernetesClusters') + + @staticmethod + def describe_kubernetes_cluster(kubernetes_cluster_id): + return Stratos.get('kubernetesClusters/'+kubernetes_cluster_id) + @staticmethod + def describe_kubernetes_master(kubernetes_cluster_id): + return Stratos.get('kubernetesClusters/'+kubernetes_cluster_id+'/master') + + @staticmethod + def add_kubernetes_cluster(json): + return Stratos.post('kubernetesClusters', json) + + @staticmethod + def add_kubernetes_host(kubernetes_cluster_id, json): + return Stratos.post('kubernetesClusters/'+kubernetes_cluster_id+'/minion', json) + + @staticmethod + def list_kubernetes_hosts(kubernetes_cluster_id): + return Stratos.get('kubernetesClusters/'+kubernetes_cluster_id+'/hosts') + + @staticmethod + def update_kubernetes_master(cluster_id, json): + return Stratos.put('kubernetesClusters/'+cluster_id+'/master', json) + + @staticmethod + def update_kubernetes_host(json): + return Stratos.put('kubernetesClusters/update/host', json) + + @staticmethod + def remove_kubernetes_cluster(kubernetes_cluster_id): + return Stratos.delete('kubernetesClusters/'+kubernetes_cluster_id) + + @staticmethod + def remove_kubernetes_host(kubernetes_cluster_id, host_id): + return Stratos.delete('kubernetesClusters/'+kubernetes_cluster_id+"/hosts/"+host_id) + + """ + # Domain Mapping + * list-domain-mappings + * add-domain-mapping + * remove-domain-mapping + + """ + + @staticmethod + def list_domain_mappings(application_id): + return Stratos.get('applications/'+application_id+'/domainMappings') + + @staticmethod + def remove_domain_mappings(application_id): + return Stratos.delete('applications/'+application_id+'/domainMappings') + + @staticmethod + def add_domain_mapping(application_id, json): + return Stratos.post('applications/'+application_id+'/domainMappings', json) + + """ + # Utils + + """ + + @staticmethod + def authenticate(): + try: + Stratos.get('init') + return True + except BadResponseError as e: + return False + + @staticmethod + def get(resource): + r = requests.get(Configs.stratos_api_url + resource, + auth=(Configs.stratos_username, Configs.stratos_password), verify=False) + return Stratos.response(r) + + @staticmethod + def delete(resource): + r = requests.delete(Configs.stratos_api_url + resource, + auth=(Configs.stratos_username, Configs.stratos_password), verify=False) + return Stratos.response(r) + + @staticmethod + def post(resource, data): + headers = {'content-type': 'application/json'} + r = requests.post(Configs.stratos_api_url + resource, data, headers=headers, + auth=(Configs.stratos_username, Configs.stratos_password), verify=False) + return Stratos.response(r) + + @staticmethod + def put(resource, data): + headers = {'content-type': 'application/json'} + r = requests.put(Configs.stratos_api_url + resource, data, headers=headers, + auth=(Configs.stratos_username, Configs.stratos_password), verify=False) + return Stratos.response(r) + + + @staticmethod + def response(r): + # print(r) + # print(r.text) + if r.status_code == 200: + return r.json() + elif r.status_code == 201: + return True + elif r.status_code == 202: + return True + elif r.status_code >= 400: + if r.text and r.json() and r.json()['message']: + logging.error("HTTP "+str(r.status_code)+" : "+r.json()['message']) + raise BadResponseError(str(r.status_code), r.json()['message']) + else: + logging.error("HTTP "+str(r.status_code)+" : Could not connect to Stratos server") + raise BadResponseError(str(r.status_code), "Could not connect to Stratos server") + + diff --git a/components/org.apache.stratos.python.cli/src/main/python/cli/Utils.py b/components/org.apache.stratos.python.cli/src/main/python/cli/Utils.py new file mode 100644 index 0000000000..9510273a37 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/cli/Utils.py @@ -0,0 +1,99 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +from __future__ import print_function +import sys +from texttable import * +import json +import Configs +from Logging import logging + + +class PrintableTree: + + def __init__(self, tree_data): + self.tree_data = tree_data + pass + + def print_tree(self): + def _print_tree(t, level=0, ups=""): + if isinstance(t, list): + print('|') + for element in t[:-1]: + print(ups + "+-", end='') + _print_tree(element, level + 1, ups + "| ") + else: + print(ups + "+-", end='') + _print_tree(t[-1], level + 1, ups + " ") + elif isinstance(t, dict): + print('|') + l = [] + for k, v in t.items(): + if isinstance(v, list) or isinstance(v, dict): + l.extend([k, v]) + else: + l.extend([str(k) + ":" + str(v)]) + t = l + for element in t[:-1]: + print(ups + "+-", end='') + _print_tree(element, level + 1, ups + "| ") + else: + print(ups + "+-", end='') + _print_tree(t[-1], level + 1, ups + " ") + else: + print(str(t)) + print("_") + _print_tree(self.tree_data) + + +class PrintableTable(Texttable): + + def __init__(self): + Texttable.__init__(self) + self.set_deco(Texttable.BORDER | Texttable.HEADER | Texttable.VLINES) + + def print_table(self): + print(self.draw()) + + +class PrintableJSON(Texttable): + + def __init__(self, json): + self.json = json + + def pprint(self): + + print(json.dumps(self.json, indent=4, separators=(',', ': '))) + + +def auth(func): + """Authenticate""" + def auth_inner(self, *args, **kwargs): + if len(args) > 1 and hasattr(args[1], 'username') and args[1].username is not None: + Configs.stratos_username = args[1].username + if len(args) > 1 and hasattr(args[1], 'password') and args[1].password is not None: + Configs.stratos_password = args[1].password + + if Configs.stratos_username is "" and Configs.stratos_password is "": + print("Pre authentication failed. Some authentication details are missing") + logging.warning("Pre authentication failed. Some authentication details are missing") + else: + return func(self, *args, **kwargs) + auth_inner.__name__ = func.__name__.replace('_', '-') + auth_inner.__doc__ = func.__doc__ + return auth_inner + diff --git a/components/org.apache.stratos.python.cli/src/main/python/cli/__init__.py b/components/org.apache.stratos.python.cli/src/main/python/cli/__init__.py new file mode 100644 index 0000000000..60d550d605 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/cli/__init__.py @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + diff --git a/components/org.apache.stratos.python.cli/src/main/python/cli/exceptions/BadResponseError.py b/components/org.apache.stratos.python.cli/src/main/python/cli/exceptions/BadResponseError.py new file mode 100644 index 0000000000..775ec65e35 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/cli/exceptions/BadResponseError.py @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +class BadResponseError(Exception): + def __init__(self, error_code, message=""): + self.error_code = error_code + self.message = message + + def __str__(self): + return self.message diff --git a/components/org.apache.stratos.python.cli/src/main/python/cli/exceptions/__init__.py b/components/org.apache.stratos.python.cli/src/main/python/cli/exceptions/__init__.py new file mode 100644 index 0000000000..60d550d605 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/cli/exceptions/__init__.py @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + diff --git a/components/org.apache.stratos.python.cli/src/main/python/setup.cfg b/components/org.apache.stratos.python.cli/src/main/python/setup.cfg new file mode 100644 index 0000000000..a731f96fa9 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/setup.cfg @@ -0,0 +1,2 @@ +[wheel] + diff --git a/components/org.apache.stratos.python.cli/src/main/python/setup.py b/components/org.apache.stratos.python.cli/src/main/python/setup.py new file mode 100644 index 0000000000..07156a2ace --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/setup.py @@ -0,0 +1,46 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 os +from setuptools import setup + + +# Utility function to read the README file. +def read(file_name): + return open(os.path.join(os.path.dirname(__file__), file_name)).read() + +setup( + name="stratos-cli", + version="1.0", + author="Apache Stratos", + author_email="dev@stratos.apache.org", + description="CLI tool to interact with Apache Stratos", + keywords="stratos", + url="http://stratos.apache.org/", + packages=['cli'], + install_requires=['cmd2', 'requests', 'texttable'], + long_description=read('README.rst'), + classifiers=[ + "Development Status :: 1 - Planning", + "Topic :: Utilities", + "License :: OSI Approved :: Apache Software License", + ], + entry_points=''' + [console_scripts] + stratos-cli=cli.Main:main + ''', +) diff --git a/components/org.apache.stratos.python.cli/src/main/python/tests/CLITest.py b/components/org.apache.stratos.python.cli/src/main/python/tests/CLITest.py new file mode 100644 index 0000000000..b0ad3cc089 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/tests/CLITest.py @@ -0,0 +1,11 @@ +from scripttest import TestFileEnvironment + +env = TestFileEnvironment('./scratch') + + +def test_list_users(): + env.clear() + result = env.run('stratos-cli list-users') + assert result.stdout.startswith("") + +test_list_users() \ No newline at end of file diff --git a/components/org.apache.stratos.python.cli/src/main/python/tests/__init__.py b/components/org.apache.stratos.python.cli/src/main/python/tests/__init__.py new file mode 100644 index 0000000000..60d550d605 --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/tests/__init__.py @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + diff --git a/components/org.apache.stratos.python.cli/src/main/python/tests/test_stratos_utils.py b/components/org.apache.stratos.python.cli/src/main/python/tests/test_stratos_utils.py new file mode 100644 index 0000000000..1f20c4b78c --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/tests/test_stratos_utils.py @@ -0,0 +1,97 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 unittest +from cli import Stratos +from cli import Configs +from cli.exceptions import BadResponseError +import responses + + +class MyTestCase(unittest.TestCase): + + + @responses.activate + def test_http_get_handler_on_200(self): + responses.add(responses.GET, Configs.stratos_api_url, + body='{"keyOne": "valueOne"}', status=200, + content_type='application/json') + + r = Stratos.get("") + + assert r == {"keyOne": "valueOne"} + + @responses.activate + def test_http_get_handler_on_400(self): + responses.add(responses.GET, Configs.stratos_api_url, + body='', status=400, + content_type='application/json') + + self.assertRaises(BadResponseError, Stratos.get("")) + + @responses.activate + def test_http_get_handler_on_404(self): + responses.add(responses.GET, Configs.stratos_api_url, + body='', status=404, + content_type='application/json') + + self.assertRaises(BadResponseError, Stratos.get("")) + + @responses.activate + def test_http_get_handler_on_500(self): + responses.add(responses.GET, Configs.stratos_api_url, + body='', status=500, + content_type='application/json') + + self.assertRaises(BadResponseError, Stratos.get("")) + + @responses.activate + def test_http_post_handler_on_200(self): + responses.add(responses.POST, Configs.stratos_api_url, + body='{"keyOne": "valueOne"}', status=200, + content_type='application/json') + + r = Stratos.post("") + + assert r is True + + @responses.activate + def test_http_post_handler_on_400(self): + responses.add(responses.POST, Configs.stratos_api_url, + body='', status=400, + content_type='application/json') + + self.assertRaises(BadResponseError, Stratos.post("")) + + @responses.activate + def test_http_post_handler_on_404(self): + responses.add(responses.POST, Configs.stratos_api_url, + body='', status=404, + content_type='application/json') + + self.assertRaises(BadResponseError, Stratos.post("")) + + @responses.activate + def test_http_post_handler_on_500(self): + responses.add(responses.POST, Configs.stratos_api_url, + body='', status=500, + content_type='application/json') + + self.assertRaises(BadResponseError, Stratos.post("")) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/components/org.apache.stratos.python.cli/src/main/python/tox.ini b/components/org.apache.stratos.python.cli/src/main/python/tox.ini new file mode 100644 index 0000000000..827566e7ff --- /dev/null +++ b/components/org.apache.stratos.python.cli/src/main/python/tox.ini @@ -0,0 +1,5 @@ +[tox] +envlist = py27, py34 +[testenv] +deps=pytest +commands=py.test \ No newline at end of file