Commit c3b95d47 by Heechul Kim

updated

parent 79102c57
# Save token if TOKEN_FILE exists.
import os
from po.config import TOKEN_FILE
TOKEN = ''
if os.path.isfile(TOKEN_FILE):
with open(TOKEN_FILE, 'r') as f:
TOKEN = f.read()
import os
import json
import logging
import getpass
import requests
import importlib
import collections
import po
from cliff.show import ShowOne
from cliff.lister import Lister
from cliff.command import Command
from po.config import API_ENDPOINT
from po.config import TOKEN_FILE
class Show(ShowOne):
"""Show the account information."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Show, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<account-name>',
help='Account name',
)
return parser
def take_action(self, parsed_args):
name = parsed_args.name
url = '{}/account/{}'.format(API_ENDPOINT, name)
headers = {'Authorization': 'Bearer {}'.format(po.TOKEN)}
r = requests.get(url, headers=headers)
if r.status_code == 200:
d = dict()
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
else:
columns = ('Error',)
data = ('User {} is not found.'.format(name),)
return (columns, data)
class List(Lister):
"""Show a list of accounts."""
log = logging.getLogger(__name__)
def take_action(self, parsed_args):
url = '{}/account/'.format(API_ENDPOINT)
headers = {'Authorization': 'Bearer {}'.format(po.TOKEN)}
r = requests.get(url, headers=headers)
if r.status_code == 200:
l = json.loads(r.text)
l_data = list()
for d in l:
t = (d['name'], d['cn'], d['desc'], d['createdAt'])
l_data.append(t)
data = tuple(l_data)
columns = ('Name',
'Common Name',
'Description',
'Created Time',
)
elif r.status_code == 401:
columns = ('Error',)
data = (('Authentication required.',),)
else: # There is an error.
columns = ('Error',)
data = (('Cannot get data.',),)
return (columns, data)
class Create(ShowOne):
"""Create an account."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Create, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<account-name>',
help='New account name',
)
parser.add_argument(
'--cn',
metavar='<common-name>',
help='A common name for the account',
)
parser.add_argument(
'--desc',
metavar='<account-description>',
default='',
help='Account description',
)
return parser
def take_action(self, parsed_args):
p1 = getpass.getpass('New password: ')
p2 = getpass.getpass('Retype new password: ')
if p1 != p2:
columns = ('Error',)
data = ('Password is not matched.',)
return (columns, data)
d = dict()
d['name'] = parsed_args.name
d['pass'] = p1
d['cn'] = parsed_args.cn
d['desc'] = parsed_args.desc
url = '{}/account'.format(API_ENDPOINT)
headers = {'Authorization': 'Bearer {}'.format(po.TOKEN)}
r = requests.post(url, headers=headers, json=d)
if r.status_code == 201:
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
else: # Creation failed.
columns = ('Error',)
data = ('User {} is not created.'.format(d['name']),)
return (columns, data)
class AdminAuth(ShowOne):
"""Authenticate an admin."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(AdminAuth, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<admin-name>',
help='Admin name',
)
return parser
def take_action(self, parsed_args):
d = dict()
d['name'] = parsed_args.name
d['pass'] = getpass.getpass('{} Password: '.format(d['name']))
url = '{}/account/admin/login/'.format(API_ENDPOINT)
r = requests.post(url, json=d)
if r.status_code == 200:
d = json.loads(r.text)
od = collections.OrderedDict(sorted(d.items()))
# update token file and TOKEN
with open(TOKEN_FILE, 'w') as f_token:
f_token.write(d['token'])
os.chmod(TOKEN_FILE, 0o600)
importlib.reload(po)
columns = tuple([k for k in od])
data = tuple([v for k, v in od.items()])
else: # Update failed.
columns = ('Error',)
data = ('Admin {} is not authenticated.'.format(d['name']),)
return (columns, data)
class Auth(ShowOne):
"""Authenticate an account."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Auth, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<account-name>',
help='Account name',
)
return parser
def take_action(self, parsed_args):
d = dict()
d['name'] = parsed_args.name
d['pass'] = getpass.getpass('{} Password: '.format(d['name']))
url = '{}/account/login'.format(API_ENDPOINT)
r = requests.post(url, json=d)
if r.status_code == 200:
d = json.loads(r.text)
# update token file and TOKEN
with open(TOKEN_FILE, 'w') as f_token:
f_token.write(d['token'])
os.chmod(TOKEN_FILE, 0o600)
importlib.reload(po)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
else: # Update failed.
columns = ('Error',)
data = ('User {} is not authenticated.'.format(d['name']),)
return (columns, data)
class Update(ShowOne):
"""Update the account information."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Update, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<account-name>',
help='Account name',
)
parser.add_argument(
'--cn',
metavar='<common-name>',
help='A common name for the account',
)
parser.add_argument(
'--desc',
metavar='<account-description>',
default='',
help='Account description',
)
return parser
def take_action(self, parsed_args):
d = dict()
name = parsed_args.name
url = '{}/account/{}'.format(API_ENDPOINT, name)
d['cn'] = parsed_args.cn
d['desc'] = parsed_args.desc
headers = {'Authorization': 'Bearer {}'.format(po.TOKEN)}
r = requests.patch(url, headers=headers, json=d)
if r.status_code == 200:
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
else: # Update failed.
columns = ('Error',)
data = ('User {} is not updated.'.format(name),)
return (columns, data)
class Delete(ShowOne):
"""Delete the account."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Delete, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<account-name>',
help='Account name',
)
return parser
def take_action(self, parsed_args):
name = parsed_args.name
url = '{}/account/{}'.format(API_ENDPOINT, name)
headers = {'Authorization': 'Bearer {}'.format(po.TOKEN)}
r = requests.delete(url, headers=headers)
if r.status_code == 204:
columns = ('msg',)
data = ('User {} is deleted.'.format(name),)
else:
columns = ('error',)
data = ('User {} is not deleted.'.format(name),)
return (columns, data)
import ast
import logging
import requests
import json
from cliff.show import ShowOne
from cliff.lister import Lister
from cliff.command import Command
from po.config import API_ENDPOINT
from po import TOKEN
class Show(ShowOne):
"""Show the app information."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Show, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<app-name>',
help='App name',
)
return parser
def take_action(self, parsed_args):
name = parsed_args.name
url = '{}/app/{}'.format(API_ENDPOINT, name)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.get(url, headers=headers)
if r.status_code == 200:
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else: # There is an error.
columns = ('Error',)
data = ('Cannot get data.',)
return (columns, data)
class List(Lister):
"""Show a list of apps."""
log = logging.getLogger(__name__)
def take_action(self, parsed_args):
url = '{}/app/'.format(API_ENDPOINT)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.get(url, headers=headers)
if r.status_code == 200:
l = json.loads(r.text)
l_data = list()
for d in l:
t = (d['name'], d['repo'], d['tag'], d['createdAt'])
l_data.append(t)
data = tuple(l_data)
columns = ('Name',
'Repo',
'Tag',
'Created Time',
)
elif r.status_code == 401:
columns = ('Error',)
data = (('Authentication required.',),)
else: # There is an error.
columns = ('Error',)
data = (('Cannot get data.',),)
return (columns, data)
class Create(ShowOne):
"""Create a app."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Create, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<app-name>',
help='New app name',
)
parser.add_argument(
'--repo',
metavar='<git-repo-name>',
required=True,
help='app git repo name',
)
parser.add_argument(
'--desc',
metavar='<app-description>',
required=False,
default='',
help='App description',
)
return parser
def take_action(self, parsed_args):
t = tuple()
d = dict()
d['name'] = parsed_args.name
d['repo'] = parsed_args.repo
d['desc'] = parsed_args.desc
url = '{}/app'.format(API_ENDPOINT)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.post(url, headers=headers, json=d)
if r.status_code == 201:
url = '{}/app/{}'.format(API_ENDPOINT, d['name'])
r = requests.get(url, headers=headers)
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else: # There is an error.
columns = ('Error',)
data = ('Cannot create a app.',)
return (columns, data)
class Update(ShowOne):
"""Update a app."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Update, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<app-name>',
help='New app name',
)
parser.add_argument(
'--repo',
metavar='<git-repo-name>',
required=False,
help='app git repo name',
)
parser.add_argument(
'--desc',
metavar='<app-description>',
required=False,
default='',
help='App description',
)
return parser
def take_action(self, parsed_args):
t = tuple()
d = dict()
d['name'] = parsed_args.name
if parsed_args.repo:
d['repo'] = parsed_args.repo
if parsed_args.desc:
d['desc'] = parsed_args.desc
url = '{}/app/{}'.format(API_ENDPOINT, d['name'])
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.patch(url, headers=headers, json=d)
if r.status_code == 200:
url = '{}/app/{}'.format(API_ENDPOINT, d['name'])
r = requests.get(url, headers=headers)
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else: # There is an error.
columns = ('Error',)
data = ('app {} update is failed.'.format(d['name']),)
return (columns, data)
class Delete(ShowOne):
"""Delete the app."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Delete, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<app-name>',
help='App name',
)
return parser
def take_action(self, parsed_args):
name = parsed_args.name
url = '{}/app/{}'.format(API_ENDPOINT, name)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.delete(url, headers=headers)
if r.status_code == 204:
columns = ('msg',)
data = ('The app {} is deleted.'.format(name),)
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else:
columns = ('Error',)
data = ('app {} is not deleted.'.format(d['name']),)
return (columns, data)
API_ENDPOINT = 'http://localhost:8000/api'
TOKEN_FILE = '.token'
import ast
import logging
import requests
import json
from cliff.show import ShowOne
from cliff.lister import Lister
from cliff.command import Command
from po.config import API_ENDPOINT
from po import TOKEN
class Show(ShowOne):
"""Show the machine information."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Show, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<machine-name>',
help='Machine name',
)
return parser
def take_action(self, parsed_args):
name = parsed_args.name
url = '{}/machine/{}'.format(API_ENDPOINT, name)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.get(url, headers=headers)
if r.status_code == 200:
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else: # There is an error.
columns = ('Error',)
data = ('Cannot get data.',)
return (columns, data)
class List(Lister):
"""Show a list of machines."""
log = logging.getLogger(__name__)
def take_action(self, parsed_args):
url = '{}/machine/'.format(API_ENDPOINT)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.get(url, headers=headers)
if r.status_code == 200:
l = json.loads(r.text)
l_data = list()
for d in l:
t = (d['name'], d['section'], d['os'], d['mac'], d['ip'],
d['createdAt'])
l_data.append(t)
data = tuple(l_data)
columns = ('Name',
'Section',
'OS',
'IP',
'MAC',
'Created Time',
)
elif r.status_code == 401:
columns = ('Error',)
data = (('Authentication required.',),)
else: # There is an error.
columns = ('Error',)
data = (('Cannot get data.',),)
return (columns, data)
class Create(ShowOne):
"""Create a machine."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Create, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<machine-name>',
help='New machine name',
)
parser.add_argument(
'--type',
metavar='<machine-type>',
required=False,
default='PM',
help='machine type - PM or VM',
)
parser.add_argument(
'--section',
metavar='<section-name>',
required=False,
default='default',
help='A section this machine belongs to',
)
parser.add_argument(
'--desc',
metavar='<machine-description>',
required=False,
default='',
help='Machine description',
)
parser.add_argument(
'--os',
metavar='<os>',
required=True,
default='',
help='Select OS for the machine.(JESSIE,CENTOS7,TRUSTY,XENIAL)'
)
parser.add_argument(
'--preseed',
metavar='<preseed>',
required=False,
default='',
help='Preseed for the machine'
)
parser.add_argument(
'--mac',
metavar='<mac-address>',
required=True,
help='Mac address for the machine'
)
parser.add_argument(
'--ip',
metavar='<ip-address>',
required=True,
help='IP address for the machine'
)
return parser
def take_action(self, parsed_args):
t = tuple()
d = dict()
d['name'] = parsed_args.name
d['type'] = parsed_args.type
d['section'] = parsed_args.section
d['desc'] = parsed_args.desc
d['os'] = parsed_args.os
d['preseed'] = parsed_args.preseed
d['mac'] = parsed_args.mac
d['ip'] = parsed_args.ip
url = '{}/machine'.format(API_ENDPOINT)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.post(url, headers=headers, json=d)
if r.status_code == 201:
url = '{}/machine/{}'.format(API_ENDPOINT, d['name'])
r = requests.get(url, headers=headers)
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else: # There is an error.
columns = ('Error',)
data = ('Cannot get data.',)
return (columns, data)
class Update(ShowOne):
"""Update a machine."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Update, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<machine-name>',
help='New machine name',
)
parser.add_argument(
'--type',
metavar='<machine-type>',
required=False,
default='',
help='machine type - PM or VM',
)
parser.add_argument(
'--section',
metavar='<section-name>',
required=False,
default='',
help='A section this machine belongs to',
)
parser.add_argument(
'--desc',
metavar='<machine-description>',
required=False,
default='',
help='Machine description',
)
parser.add_argument(
'--os',
metavar='<os=os>',
required=False,
default='',
help='Select OS for the machine.(JESSIE,CENTOS7,TRUSTY,XENIAL)'
)
parser.add_argument(
'--preseed',
metavar='<preseed>',
required=False,
default='',
help='Preseed for the machine'
)
parser.add_argument(
'--mac',
metavar='<mac-address>',
required=False,
default='',
help='Mac address for the machine'
)
parser.add_argument(
'--ip',
metavar='<ip-address>',
required=False,
default='',
help='IP address for the machine'
)
parser.add_argument(
'--installed',
metavar='<install flag>',
required=False,
type=ast.literal_eval,
help='machine install flag'
)
return parser
def take_action(self, parsed_args):
t = tuple()
d = dict()
d['name'] = parsed_args.name
d['type'] = parsed_args.type
d['section'] = parsed_args.section
d['desc'] = parsed_args.desc
d['os'] = parsed_args.os
d['preseed'] = parsed_args.preseed
d['mac'] = parsed_args.mac
d['ip'] = parsed_args.ip
if parsed_args.installed != None:
d['is_installed'] = parsed_args.installed
url = '{}/machine/{}'.format(API_ENDPOINT, d['name'])
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.patch(url, headers=headers, json=d)
if r.status_code == 200:
url = '{}/machine/{}'.format(API_ENDPOINT, d['name'])
r = requests.get(url, headers=headers)
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
else: # There is an error.
d = r.json()
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
return (columns, data)
class Delete(ShowOne):
"""Delete the machine."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Delete, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<machine-name>',
help='Machine name',
)
return parser
def take_action(self, parsed_args):
name = parsed_args.name
url = '{}/machine/{}'.format(API_ENDPOINT, name)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.delete(url, headers=headers)
d = r.json()
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
if r.status_code == 204:
columns = ('msg',)
data = ('The machine {} is deleted.'.format(name),)
return (columns, data)
class Provision(ShowOne):
"""Provision a machine."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Provision, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<machine-name>',
help='machine name',
)
return parser
def take_action(self, parsed_args):
t = tuple()
d = dict()
name = parsed_args.name
url = '{}/machine/{}/provision'.format(API_ENDPOINT, name)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.post(url, headers=headers, json=d)
d = r.json()
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
return (columns, data)
import sys
from cliff.app import App
from cliff.commandmanager import CommandManager
class PorchShell(App):
def __init__(self):
super(PorchShell, self).__init__(
description='Porch CLI App',
version='0.1',
command_manager=CommandManager('porch.cli'),
deferred_help=True,
)
def initialize_app(self, argv):
self.LOG.debug('initialize_app')
def prepare_to_run_command(self, cmd):
self.LOG.debug('prepare_to_run_command %s', cmd.__class__.__name__)
def clean_up(self, cmd, result, err):
self.LOG.debug('got an error: %s', err)
def main(argv=sys.argv[1:]):
shell = PorchShell()
return shell.run(argv)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
import ast
import logging
import requests
import json
from cliff.show import ShowOne
from cliff.lister import Lister
from cliff.command import Command
from po.config import API_ENDPOINT
from po import TOKEN
class Show(ShowOne):
"""Show the section information."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Show, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<section-name>',
help='Section name',
)
return parser
def take_action(self, parsed_args):
name = parsed_args.name
url = '{}/section/{}'.format(API_ENDPOINT, name)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.get(url, headers=headers)
if r.status_code == 200:
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else: # There is an error.
columns = ('Error',)
data = ('Cannot get data.',)
return (columns, data)
class List(Lister):
"""Show a list of sections."""
log = logging.getLogger(__name__)
def take_action(self, parsed_args):
url = '{}/section/'.format(API_ENDPOINT)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.get(url, headers=headers)
if r.status_code == 200:
l = json.loads(r.text)
l_data = list()
for d in l:
t = (d['name'], d['cn'], d['desc'], d['createdAt'])
l_data.append(t)
data = tuple(l_data)
columns = ('Name',
'Common Name',
'Description',
'Created Time',
)
elif r.status_code == 401:
columns = ('Error',)
data = (('Authentication required.',),)
else: # There is an error.
columns = ('Error',)
data = (('Cannot get data.',),)
return (columns, data)
class Create(ShowOne):
"""Create a section."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Create, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<section-name>',
help='New section name',
)
parser.add_argument(
'--cn',
metavar='<common-name>',
required=False,
default='',
help='A common name of section',
)
parser.add_argument(
'--desc',
metavar='<section-description>',
required=False,
default='',
help='Section description',
)
return parser
def take_action(self, parsed_args):
t = tuple()
d = dict()
d['name'] = parsed_args.name
d['cn'] = parsed_args.cn
d['desc'] = parsed_args.desc
url = '{}/section'.format(API_ENDPOINT)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.post(url, headers=headers, json=d)
if r.status_code == 201:
url = '{}/section/{}'.format(API_ENDPOINT, d['name'])
r = requests.get(url, headers=headers)
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else: # There is an error.
columns = ('Error',)
data = ('Cannot create a section.',)
return (columns, data)
class Update(ShowOne):
"""Update a section."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Update, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<section-name>',
help='New section name',
)
parser.add_argument(
'--cn',
metavar='<common-name>',
required=False,
default='',
help='A common name of section',
)
parser.add_argument(
'--desc',
metavar='<section-description>',
required=False,
default='',
help='Section description',
)
return parser
def take_action(self, parsed_args):
t = tuple()
d = dict()
d['name'] = parsed_args.name
d['cn'] = parsed_args.cn
d['desc'] = parsed_args.desc
url = '{}/section/{}'.format(API_ENDPOINT, d['name'])
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.patch(url, headers=headers, json=d)
if r.status_code == 200:
url = '{}/section/{}'.format(API_ENDPOINT, d['name'])
r = requests.get(url, headers=headers)
d = json.loads(r.text)
columns = tuple([k for k in d])
data = tuple([v for k, v in d.items()])
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else: # There is an error.
columns = ('Error',)
data = ('section {} update is failed.'.format(d['name']),)
return (columns, data)
class Delete(ShowOne):
"""Delete the section."""
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(Delete, self).get_parser(prog_name)
parser.add_argument(
'name',
metavar='<section-name>',
help='Section name',
)
return parser
def take_action(self, parsed_args):
name = parsed_args.name
url = '{}/section/{}'.format(API_ENDPOINT, name)
headers = {'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.delete(url, headers=headers)
if r.status_code == 204:
columns = ('msg',)
data = ('The section {} is deleted.'.format(name),)
elif r.status_code == 401:
columns = ('Error',)
data = ('Authentication required.',)
else:
columns = ('Error',)
data = ('section {} is not deleted.'.format(d['name']),)
return (columns, data)
PROJECT = 'po'
# Change docs/sphinx/conf.py too!
VERSION = '0.1'
from setuptools import setup, find_packages
try:
long_description = open('README.rst', 'rt').read()
except IOError:
long_description = ''
setup(
name=PROJECT,
version=VERSION,
description='PORCH CLI App',
long_description=long_description,
author='Heechul Kim',
author_email='jijisa@iorchard.net',
url='https://github.com/jijisa/porch',
download_url='https://github.com/jijisa/porch/tarball/master',
classifiers=['Development Status :: 3 - Alpha',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Intended Audience :: Developers',
'Environment :: Console',
],
platforms=['Any'],
scripts=[],
provides=[],
install_requires=['cliff'],
namespace_packages=[],
packages=find_packages(),
include_package_data=True,
entry_points={
'console_scripts': [
'po = po.main:main'
],
'porch.cli': [
'section list = po.section.client:List',
'section show = po.section.client:Show',
'section create = po.section.client:Create',
'section update = po.section.client:Update',
'section delete = po.section.client:Delete',
'machine list = po.machine.client:List',
'machine show = po.machine.client:Show',
'machine create = po.machine.client:Create',
'machine update = po.machine.client:Update',
'machine delete = po.machine.client:Delete',
'machine provision = po.machine.client:Provision',
'user list = po.account.client:List',
'user show = po.account.client:Show',
'user create = po.account.client:Create',
'user update = po.account.client:Update',
'user delete = po.account.client:Delete',
'user auth = po.account.client:Auth',
'admin auth = po.account.client:AdminAuth',
'app list = po.app.client:List',
'app show = po.app.client:Show',
'app create = po.app.client:Create',
'app update = po.app.client:Update',
'app delete = po.app.client:Delete',
],
},
zip_safe=False,
)
......@@ -8,6 +8,7 @@ import logging.config
from datetime import datetime
from porch.database import etcdc
from porch.config import ADMIN_ID
logging.config.fileConfig('logging.conf')
log = logging.getLogger('porch')
......@@ -61,6 +62,24 @@ def create_account(data):
finally:
return t_ret
def admin_auth_account(data):
"""Authenticate admin account.
data = {'name':, 'pass':}
"""
b_ret = False
s_rsc = '{}/account/{}'.format(etcdc.prefix, data['name'])
try:
r = etcdc.read(s_rsc)
except etcd.EtcdKeyNotFound as e:
log.error(e)
return b_ret
d = ast.literal_eval(r.value)
s_pass = bcrypt.hashpw(data['pass'].encode(),
d['salt'].encode()).decode()
return data['name'] == ADMIN_ID and s_pass == d['pass']
def auth_account(data):
"""Auth account.
data = {'name':, 'pass'}
......
......@@ -26,6 +26,7 @@ from porch.api.account.serializers import accountPasswordSerializer
from porch.api.account.bizlogic import get_account
from porch.api.account.bizlogic import create_account
from porch.api.account.bizlogic import admin_auth_account
from porch.api.account.bizlogic import auth_account
from porch.api.account.bizlogic import update_account
from porch.api.account.bizlogic import delete_account
......@@ -64,6 +65,29 @@ class AccountCollection(Resource):
l_account = get_account(data['name'])
return l_account[0], 201
@ns.route('/admin/login/')
class AdminAccountAuth(Resource):
@api.response(200, 'Account is successfully authenticated.')
@api.expect(accountAuthSerializer)
def post(self):
"""Authenticate an account.
"""
data = request.json
b_ret = admin_auth_account(data)
if not b_ret:
d_msg = {'error': 'Admin Authentication is failed.'}
return d_msg, 401
# create token
d_resp = {
'token': create_access_token(identity=data['name']),
'refresh_token': create_refresh_token(identity=data['name']),
'role': 'admin'
}
return d_resp, 200
@ns.route('/login')
class AccountAuth(Resource):
......@@ -165,7 +189,7 @@ class AccountItem(Resource):
@api.response(404, 'Account not found.')
class AccountPassword(Resource):
#@ns.expect(accountPasswordSerializer)
@ns.expect(accountPasswordSerializer)
@ns.response(204, "The account is successfully updated.")
@jwt_required
def patch(self, name):
......
......@@ -26,12 +26,14 @@ machinePostSerializer = api.model('RegisterMachine', {
'type': fields.String(required=True, description='type: PM or VM'),
'desc': fields.String(required=False, description='machine description'),
'os': fields.String(required=True, description='machine os'),
'preseed': fields.String(required=True, description='machine preseed'),
'preseed': fields.String(required=True, default='',
description='machine preseed'),
'mac': fields.String(required=True, description='machine mac'),
'ip': fields.String(required=True, description='machine ip address'),
})
machinePatchSerializer = api.model('ModifyMachine', {
'type': fields.String(required=False, description='type: PM or VM'),
'desc': fields.String(required=False, description='machine description'),
'section': fields.String(required=False,
description='the section machine belongs to'),
......
......@@ -22,7 +22,7 @@
# For the first stage, set the CentOS/SLC mirror in /etc/rinse/rinse.conf
MIRROR_DEBIAN=http://httpredir.debian.org/debian/
#MIRROR_DEBIAN=http://localmirror/debian/
MIRROR_UBUNTU=http://mirror.netcologne.de/ubuntu/
MIRROR_UBUNTU=http://ftp.daum.net/ubuntu/
MIRROR_CENTOS=http://mirror.netcologne.de/
#MIRROR_CENTOS=http://localmirror
#MIRROR_SLC=http://localmirror
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment