Skip to content

Commit

Permalink
Milestone/v1.1.0 (#42)
Browse files Browse the repository at this point in the history
* Task/34  tapipy g UI (#39)

* GUI for tapipy package

* Add editor option for providing request body

* upgrade tapipy to version 1.0.3

* changelog

* Add temporary upload method to tapipy controller

* rename core packages to utils; start jupyter scinco package

* Package name in category error

* Add create example controller on package create

* rename example controller to Systems

* Add Configure controller on package create; Add support for 'tapis package configure'.

* SettingSet class. Settings and configs exposed on BaseController

* use self.config in jupsci Configure controller

* Configure template create config for package

* Register package on create

* Remove unused import

* Prompt for all configs on Configure for jupyterscinco package

* Replace all instances of config with self.config

* Seperate Meta into Groups and Tenants controller; JupSciMetaView; Add aliases for jupsci package

* list all action

* refactor jupsci package

* build_config util

* Mount crud functionality

* update changelog

* Task/40  query params (#41)

* prompt for query parameters

* remove extraneous return

* check for required query parameters when validating kwargs

* update README

* require input for required values in request_body
  • Loading branch information
nathandf authored Dec 15, 2021
1 parent 0fb7d6c commit 7f97980
Show file tree
Hide file tree
Showing 44 changed files with 1,344 additions and 247 deletions.
56 changes: 56 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Features
- GUI for tapipy package [@nathandf](https://github.com/nathandf)
- JupyterSCINCO package

### Breaking Changes
- Router calls index method on BaseController if no command is passed after the resource
- Upgrade tapipy to version 1.0.3

### non-Breaking Changes
- Added CHANGELOG.md
- Added CONTRIBUTORS.md
- select_Action and index methods on TapipyController moved to BaseController
- Prompt util method changed from "not_none" to "text"
- Added prompt util boolean select
- Open API Schema type transform util
- rename core package to utils
- Pacakge create creates Example and Configure controllers
- package settings available on package controllers on instantiation
- Access to settings and config management on the base controller class

### Fixed
- Router: Check if aliases object exists in aliases module before getattr

### Removed
- N/A

## [v1.0.0] - 2021-12-1
### Features
- GUI for tapis package [@nathandf](https://github.com/nathandf)
- Multi-profile support
- Before and After action filters
- Command aliases for packages(except for the tapipy package)
- Base jupyterSCINCO package
.
- Docker deployment option for tapisv3-cli [@nathandf](https://github.com/nathandf) & [@Tyler-Clemens](https://github.com/Tyler-Clemens)

### Breaking Changes
- N/A

### non-Breaking Changes
- N/A

### Fixed
-

### Removed
- N/A

2 changes: 2 additions & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[@nathandf](https://github.com/nathandf)
[@Tyler-Clemens](https://github.com/Tyler-Clemens)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ tapis-cli can be set up and run in 2 ways; Locally, and in a Docker container.
**Initialize a virtual env**\
`pipenv shell`

**Install Tapipy**\
`pip install tapipy`
**Install Requirements**\
`pip install -r requirements.txt`

**Add the following line in your .bashrc file**
`alias tapis="<path/to/tapis_cli_project>/src/tapis.sh"`
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ requests==2.26.0
six==1.16.0
strict-rfc3339==0.7
tabulate==0.8.9
tapipy==1.0.1
tapipy==1.0.3
urllib3==1.26.6
wcwidth==0.2.5
yarg==0.1.9
11 changes: 10 additions & 1 deletion src/conf/settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from re import VERBOSE

ACTION_FILTER_SUFFIX = "_Action"

Expand All @@ -8,10 +9,12 @@
"jupyterscinco"
]

DEFAULT_PACKAGE = "core"
DEFAULT_PACKAGE = "tapipy"

PACKAGES_DIR = "packages/"

TEMPLATES_DIR = "conf/templates/"

DEFAULT_AUTH_METHOD = "PASSWORD"

AUTH_METHODS = [ "PASSWORD" ]
Expand All @@ -23,3 +26,9 @@
PASSWORD = "PASSWORD"
DEFAULT_AUTH_METHOD = PASSWORD

LOG_LEVEL_DEFAULT = 1
LOG_LEVEL_VERBOSE = 2
LOG_LEVEL_DEBUG = 3

LOG_LEVEL = LOG_LEVEL_DEBUG

2 changes: 1 addition & 1 deletion src/conf/templates/core.py → src/conf/templates/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
template = {
"current": {
"package": "tapis",
"package": "tapipy",
"profile": "",
"auth_method": "PASSWORD"
},
Expand Down
17 changes: 17 additions & 0 deletions src/conf/templates/controllers/Configure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from core.BaseController import BaseController

# NOTE This is a special controller. It cannot be accessed via the command line
# except through `tapis package configure`. If you added your package to the
# PACKAGES array in main settings.py, you can select your package and it will
# run the index method on this controller
class Configure(BaseController):
def __init__(self):
BaseController.__init__(self)

# NOTE Do not remove this method. Doing so will result in unexpected behavior.
# Use this method to set configs specific to your package using the ConfigManager
# instance(self.config)
def index(self):
if self.config.has_section(f"package.{self.get_package()}") == False:
self.config.add_section(f"package.{self.get_package()}")

187 changes: 187 additions & 0 deletions src/conf/templates/controllers/Systems.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import json

from tapipy.errors import InvalidInputError

from packages.tapis.TapisController import TapisController


# This example controller queries and mutates the tapis Systems API
class Systems(TapisController):
# Tapis controller abstracts away client initialization and authentication.
# Make calls with the tapis client using self.client
def __init__(self):
TapisController.__init__(self)

# All methods called that are suffixed with the ACTION_FILTER_SUFFIX(_Action by default)
# will run 3 methods. First it calls BaseClass.before(), then itself,
# then BaseClass.after(). Before and after filters are available
# on all controllers that inherit the BaseClass class. By default, they're before
# and after do nothing. You may define your own before and after methods on
# controller classes.
def available_Action(self, system_id) -> None:
"""Check if a system is currently enabled."""
try:
system = self.client.systems.isEnabled(systemId=system_id)
status = "enabled" if system.aBool else "disabled"
self.logger.info(f"The system '{system_id}' is {status}\n")
return
except InvalidInputError:
self.logger.error(f"System not found with id '{system_id}'\n")

def change_owner_Action(self, system_id, username) -> None:
self.client.systems.changeSystemOwner(systemId=system_id, userName=username)
self.logger.complete(f"Changed owner of system '{system_id}' to '{username}'\n")

return

def create_Action(self, system_definition_file: str) -> None:
definition = json.loads(open(system_definition_file, "r").read())
self.client.systems.createSystem(**definition)
self.logger.success(f"System \'{definition['id']}\' created\n")

return

def create_user_creds_Action(self, system_definition_file) -> None:
system_definition = json.loads(open(system_definition_file, "r").read())
self.client.systems.createUserCredential(**system_definition)
self.logger.info(f"User credentials created for user '{system_definition['userName']}'\n")

return

def delete_Action(self, system_id) -> None:
try:
self.client.systems.deleteSystem(systemId=system_id)
self.logger.info(f"Deleted system with id '{system_id}'\n")
return
except InvalidInputError:
self.logger.error(f"System not found with id '{system_id}'\n")
return

def disable_Action(self, system_id) -> None:
try:
self.client.systems.disableSystem(systemId=system_id)
self.logger.success(f"The system '{system_id}' was disabled\n")
return
except InvalidInputError:
self.logger.error(f"System not found with id '{system_id}'\n")
return

def enable_Action(self, system_id) -> None:
try:
self.client.systems.enableSystem(systemId=system_id)
self.logger.success(f"The system '{system_id}' was enabled\n")
return
except InvalidInputError:
self.logger.error(f"System not found with id '{system_id}'\n")
return

def get_Action(self, system_id) -> None:
try:
system = self.client.systems.getSystem(systemId=system_id)
self.logger.log(system)
print()
return
except InvalidInputError:
self.logger.error(f"System not found with id '{system_id}'\n")
return

def getperms_Action(self, system_id, username) -> None:
creds = self.client.systems.getUserPerms(systemId=system_id, userName=username)
self.logger.log(creds)
self.logger.newline(1)

return

def grantperms_Action(self, system_id, username, *args) -> None:
perms = [arg.upper() for arg in args]
self.client.systems.grantUserPerms(systemId=system_id, userName=username, permissions=perms)
self.logger.info(f"Permissions {args} granted to user '{username}'\n")
self.logger.newline(1)

return

def list_Action(self) -> None:
systems = self.client.systems.getSystems()
if len(systems) > 0:
self.logger.newline(1)
for system in systems:
self.logger.log(system.id)
self.logger.newline(1)
return
self.logger.log(f"No systems found for user '{self.client.username}'\n")

return

def patch_Action(self, system_definition_file) -> None:
try:
system_definition = json.loads(open(system_definition_file, "r").read())
except FileNotFoundError as e:
self.logger.error(e)
self.exit(1)

if 'systemId' not in system_definition.keys():
system_definition['systemId'] = system_definition['id']
if 'systemVersion' not in system_definition.keys():
system_definition['systemVersion'] = system_definition['version']

try:
# Update select attributes defined by the system definition file.
self.client.systems.patchSystem(**system_definition)
self.logger.success(f"System '{system_definition.systemId}' updated\n")
return
except InvalidInputError as e:
self.logger.error(f"{e.message}\n")
return

def put_Action(self, system_definition_file) -> None:
try:
system_definition = json.loads(open(system_definition_file, "r").read())
except FileNotFoundError as e:
self.logger.error(e)
self.exit(1)

if 'systemId' not in system_definition.keys():
system_definition['systemId'] = system_definition['id']
if 'systemVersion' not in system_definition.keys():
system_definition['systemVersion'] = system_definition['version']

try:
# Update select attributes defined by the system definition file.
self.client.systems.putSystem(**system_definition)
self.logger.success(f"System '{system_definition['systemId']}'' has been updated\n")
return
except InvalidInputError as e:
self.logger.error(f"Invalid Input Error: '{e.message}'\n")
self.exit(1)

def revokeperms_Action(self, system_id, username, *args) -> None:
perms = [arg.upper() for arg in args]

# The expected input should be a JSONArray, NOT a JSONObject.
self.client.systems.revokeUserPerms(systemId=system_id, userName=username, permissions=perms)
self.logger.info(f"Permissions {perms} revoked from user '{username}'\n")

return

def search_Action(self, *args) -> None:
matched = self.client.systems.searchSystemsRequestBody(search=args)
for system in matched:
print(system)
self.logger.newline(1)

return

def undelete_Action(self, system_id) -> None:
try:
self.client.systems.undeleteSystem(systemId=system_id)
self.logger.success(f"Recovered system with id '{system_id}'\n")
return
except InvalidInputError:
self.logger.info(f"Deleted system not found with id '{system_id}'\n")
return

def update_creds_Action(self, file) -> None:
creds = json.loads(open(file, "r").read())
self.client.systems.createUserCredential(**creds)

return
1 change: 1 addition & 0 deletions src/conf/templates/files/aliases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aliases = {}
File renamed without changes.
Loading

0 comments on commit 7f97980

Please sign in to comment.