Adds Project CLI commands
Adding cli commands associated with /projects api. Closes-Bug: 1659237 Change-Id: Ic3375176ddf85d283f784d59307be434cefac9e0
This commit is contained in:
parent
3912b47732
commit
24de28869d
108
cratonclient/shell/v1/projects_shell.py
Normal file
108
cratonclient/shell/v1/projects_shell.py
Normal file
@ -0,0 +1,108 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""Projects resource and resource shell wrapper."""
|
||||
from __future__ import print_function
|
||||
|
||||
from cratonclient.common import cliutils
|
||||
from cratonclient import exceptions as exc
|
||||
from cratonclient.v1 import projects
|
||||
|
||||
|
||||
@cliutils.arg('id',
|
||||
metavar='<project>',
|
||||
help='ID of the project.')
|
||||
def do_project_show(cc, args):
|
||||
"""Show detailed information about a project."""
|
||||
project = cc.projects.get(args.id)
|
||||
data = {f: getattr(project, f, '') for f in projects.PROJECT_FIELDS}
|
||||
cliutils.print_dict(data, wrap=72)
|
||||
|
||||
|
||||
@cliutils.arg('-n', '--name',
|
||||
metavar='<name>',
|
||||
help='Name of the project.')
|
||||
@cliutils.arg('--detail',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Show detailed information about the projects.')
|
||||
@cliutils.arg('--limit',
|
||||
metavar='<limit>',
|
||||
type=int,
|
||||
help='Maximum number of projects to return.')
|
||||
@cliutils.arg('--fields',
|
||||
nargs='+',
|
||||
metavar='<fields>',
|
||||
default=[],
|
||||
help='Comma-separated list of fields to display. '
|
||||
'Only these fields will be fetched from the server. '
|
||||
'Can not be used when "--detail" is specified')
|
||||
def do_project_list(cc, args):
|
||||
"""Print list of projects which are registered with the Craton service."""
|
||||
params = {}
|
||||
default_fields = ['id', 'name']
|
||||
if args.limit is not None:
|
||||
if args.limit < 0:
|
||||
raise exc.CommandError('Invalid limit specified. Expected '
|
||||
'non-negative limit, got {0}'
|
||||
.format(args.limit))
|
||||
params['limit'] = args.limit
|
||||
|
||||
if args.fields and args.detail:
|
||||
raise exc.CommandError('Cannot specify both --fields and --detail.')
|
||||
|
||||
if args.name:
|
||||
params['name'] = args.name
|
||||
if args.detail:
|
||||
fields = projects.PROJECT_FIELDS
|
||||
elif args.fields:
|
||||
try:
|
||||
fields = {x: projects.PROJECT_FIELDS[x] for x in args.fields}
|
||||
except KeyError as keyerr:
|
||||
raise exc.CommandError('Invalid field "{}"'.format(keyerr.args[0]))
|
||||
else:
|
||||
fields = {x: projects.PROJECT_FIELDS[x] for x in default_fields}
|
||||
|
||||
listed_projects = cc.projects.list(**params)
|
||||
cliutils.print_list(listed_projects, list(fields))
|
||||
|
||||
|
||||
@cliutils.arg('-n', '--name',
|
||||
metavar='<name>',
|
||||
required=True,
|
||||
help='Name of the project.')
|
||||
def do_project_create(cc, args):
|
||||
"""Register a new project with the Craton service."""
|
||||
fields = {k: v for (k, v) in vars(args).items()
|
||||
if k in projects.PROJECT_FIELDS and not (v is None)}
|
||||
project = cc.projects.create(**fields)
|
||||
data = {f: getattr(project, f, '') for f in projects.PROJECT_FIELDS}
|
||||
cliutils.print_dict(data, wrap=72)
|
||||
|
||||
|
||||
@cliutils.arg('id',
|
||||
metavar='<project>',
|
||||
help='ID of the project.')
|
||||
def do_project_delete(cc, args):
|
||||
"""Delete a project that is registered with the Craton service."""
|
||||
try:
|
||||
response = cc.projects.delete(args.id)
|
||||
except exc.ClientException as client_exc:
|
||||
raise exc.CommandError(
|
||||
'Failed to delete project {} due to "{}:{}"'.format(
|
||||
args.id, client_exc.__class__, str(client_exc)
|
||||
)
|
||||
)
|
||||
else:
|
||||
print("Project {0} was {1} deleted.".
|
||||
format(args.id, 'successfully' if response else 'not'))
|
@ -12,11 +12,13 @@
|
||||
"""Command-line interface to the OpenStack Craton API V1."""
|
||||
from cratonclient.shell.v1 import cells_shell
|
||||
from cratonclient.shell.v1 import hosts_shell
|
||||
from cratonclient.shell.v1 import projects_shell
|
||||
from cratonclient.shell.v1 import regions_shell
|
||||
|
||||
|
||||
COMMAND_MODULES = [
|
||||
# TODO(cmspence): project_shell, cell_shell, device_shell, user_shell, etc.
|
||||
projects_shell,
|
||||
regions_shell,
|
||||
hosts_shell,
|
||||
cells_shell,
|
||||
|
178
cratonclient/tests/integration/test_projects_shell.py
Normal file
178
cratonclient/tests/integration/test_projects_shell.py
Normal file
@ -0,0 +1,178 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Tests for `cratonclient.shell.v1.projects_shell` module."""
|
||||
|
||||
import mock
|
||||
import re
|
||||
|
||||
from argparse import Namespace
|
||||
from testtools import matchers
|
||||
|
||||
from cratonclient import exceptions as exc
|
||||
from cratonclient.shell.v1 import projects_shell
|
||||
from cratonclient.tests.integration import base
|
||||
from cratonclient.v1 import projects
|
||||
|
||||
|
||||
class TestProjectsShell(base.ShellTestCase):
|
||||
"""Test our craton projects shell commands."""
|
||||
|
||||
re_options = re.DOTALL | re.MULTILINE
|
||||
project_valid_fields = None
|
||||
project_invalid_field = None
|
||||
|
||||
def setUp(self):
|
||||
"""Setup required test fixtures."""
|
||||
super(TestProjectsShell, self).setUp()
|
||||
self.project_valid_fields = Namespace(name='mock_project')
|
||||
self.project_invalid_field = Namespace(name='mock_project',
|
||||
invalid_foo='ignored')
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.list')
|
||||
def test_project_list_success(self, mock_list):
|
||||
"""Verify that no arguments prints out all project projects."""
|
||||
self.shell('project-list')
|
||||
self.assertTrue(mock_list.called)
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.list')
|
||||
def test_project_list_parse_param_success(self, mock_list):
|
||||
"""Verify that success of parsing a subcommand argument."""
|
||||
self.shell('project-list --limit 0')
|
||||
self.assertTrue(mock_list.called)
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.list')
|
||||
def test_project_list_limit_0_success(self, mock_list):
|
||||
"""Verify that --limit 0 prints out all project projects."""
|
||||
self.shell('project-list --limit 0')
|
||||
mock_list.assert_called_once_with(
|
||||
limit=0
|
||||
)
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.list')
|
||||
def test_project_list_limit_positive_num_success(self, mock_list):
|
||||
"""Verify --limit X, where X is a positive integer, succeeds.
|
||||
|
||||
The command will print out X number of project projects.
|
||||
"""
|
||||
self.shell('project-list --limit 1')
|
||||
mock_list.assert_called_once_with(
|
||||
limit=1
|
||||
)
|
||||
|
||||
def test_project_list_limit_negative_num_failure(self):
|
||||
"""Verify --limit X, where X is a negative integer, fails.
|
||||
|
||||
The command will cause a Command Error message response.
|
||||
"""
|
||||
self.assertRaises(exc.CommandError,
|
||||
self.shell,
|
||||
'project-list --limit -1')
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.list')
|
||||
def test_project_list_detail_success(self, mock_list):
|
||||
"""Verify --detail argument successfully pass detail to Client."""
|
||||
self.shell('project-list --detail')
|
||||
mock_list.assert_called_once_with()
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.list')
|
||||
@mock.patch('cratonclient.common.cliutils.print_list')
|
||||
def test_project_list_fields_success(self, mock_printlist, mock_list):
|
||||
"""Verify --fields argument successfully passed to Client."""
|
||||
self.shell('project-list --fields id name')
|
||||
mock_list.assert_called_once_with()
|
||||
mock_printlist.assert_called_once_with(mock.ANY,
|
||||
list({'id': 'ID',
|
||||
'name': 'Name'}))
|
||||
|
||||
def test_project_create_missing_required_args(self):
|
||||
"""Verify that missing required args results in error message."""
|
||||
expected_responses = [
|
||||
'.*?^usage: craton project-create',
|
||||
'.*?^craton project-create: error:.*$'
|
||||
]
|
||||
stdout, stderr = self.shell('project-create')
|
||||
actual_output = stdout + stderr
|
||||
for r in expected_responses:
|
||||
self.assertThat(actual_output,
|
||||
matchers.MatchesRegex(r, self.re_options))
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.create')
|
||||
def test_do_project_create_calls_project_manager_with_fields(self,
|
||||
mock_create):
|
||||
"""Verify that do project create calls ProjectManager create."""
|
||||
client = mock.Mock()
|
||||
client.projects = projects.ProjectManager(
|
||||
mock.ANY, 'http://127.0.0.1/',
|
||||
region_id=mock.ANY,
|
||||
)
|
||||
projects_shell.do_project_create(client, self.project_valid_fields)
|
||||
mock_create.assert_called_once_with(**vars(self.project_valid_fields))
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.create')
|
||||
def test_do_project_create_ignores_unknown_fields(self, mock_create):
|
||||
"""Verify that do project create ignores unknown field."""
|
||||
client = mock.Mock()
|
||||
client.projects = projects.ProjectManager(
|
||||
mock.ANY, 'http://127.0.0.1/',
|
||||
region_id=mock.ANY,
|
||||
)
|
||||
projects_shell.do_project_create(client, self.project_invalid_field)
|
||||
mock_create.assert_called_once_with(**vars(self.project_valid_fields))
|
||||
|
||||
def test_project_show_missing_required_args(self):
|
||||
"""Verify that missing required args results in error message."""
|
||||
expected_responses = [
|
||||
'.*?^usage: craton project-show',
|
||||
'.*?^craton project-show: error:.*$',
|
||||
]
|
||||
stdout, stderr = self.shell('project-show')
|
||||
actual_output = stdout + stderr
|
||||
for r in expected_responses:
|
||||
self.assertThat(actual_output,
|
||||
matchers.MatchesRegex(r, self.re_options))
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.get')
|
||||
def test_do_project_show_calls_project_manager_with_fields(self, mock_get):
|
||||
"""Verify that do project show calls ProjectManager get."""
|
||||
client = mock.Mock()
|
||||
client.projects = projects.ProjectManager(
|
||||
mock.ANY, 'http://127.0.0.1/',
|
||||
region_id=mock.ANY,
|
||||
)
|
||||
test_args = Namespace(id=1)
|
||||
projects_shell.do_project_show(client, test_args)
|
||||
mock_get.assert_called_once_with(vars(test_args)['id'])
|
||||
|
||||
def test_project_delete_missing_required_args(self):
|
||||
"""Verify that missing required args results in error message."""
|
||||
expected_responses = [
|
||||
'.*?^usage: craton project-delete',
|
||||
'.*?^craton project-delete: error:.*$',
|
||||
]
|
||||
stdout, stderr = self.shell('project-delete')
|
||||
for r in expected_responses:
|
||||
self.assertThat((stdout + stderr),
|
||||
matchers.MatchesRegex(r, self.re_options))
|
||||
|
||||
@mock.patch('cratonclient.v1.projects.ProjectManager.delete')
|
||||
def test_do_project_delete_calls_project_manager_with_fields(self,
|
||||
mock_delete):
|
||||
"""Verify that do project delete calls ProjectManager delete."""
|
||||
client = mock.Mock()
|
||||
client.projects = projects.ProjectManager(
|
||||
mock.ANY, 'http://127.0.0.1/',
|
||||
region_id=mock.ANY,
|
||||
)
|
||||
test_args = Namespace(id=1, region=1)
|
||||
projects_shell.do_project_delete(client, test_args)
|
||||
mock_delete.assert_called_once_with(vars(test_args)['id'])
|
222
cratonclient/tests/unit/shell/v1/test_projects_shell.py
Normal file
222
cratonclient/tests/unit/shell/v1/test_projects_shell.py
Normal file
@ -0,0 +1,222 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""Tests for the shell functions for the projects resource."""
|
||||
import uuid
|
||||
|
||||
import mock
|
||||
|
||||
from cratonclient import exceptions
|
||||
from cratonclient.shell.v1 import projects_shell
|
||||
from cratonclient.tests.unit.shell import base
|
||||
from cratonclient.v1 import projects
|
||||
|
||||
|
||||
class TestDoShellShow(base.TestShellCommandUsingPrintDict):
|
||||
"""Unit tests for the project show command."""
|
||||
|
||||
def test_simple_usage(self):
|
||||
"""Verify the behaviour of do_project_show."""
|
||||
args = self.args_for(
|
||||
region=123,
|
||||
id=456,
|
||||
)
|
||||
|
||||
projects_shell.do_project_show(self.craton_client, args)
|
||||
|
||||
self.craton_client.projects.get.assert_called_once_with(456)
|
||||
self.print_dict.assert_called_once_with(
|
||||
{f: mock.ANY for f in projects.PROJECT_FIELDS},
|
||||
wrap=72,
|
||||
)
|
||||
|
||||
|
||||
class TestDoProjectList(base.TestShellCommandUsingPrintList):
|
||||
"""Unit tests for the project list command."""
|
||||
|
||||
def assertNothingWasCalled(self):
|
||||
"""Assert inventory, list, and print_list were not called."""
|
||||
super(TestDoProjectList, self).assertNothingWasCalled()
|
||||
self.assertFalse(self.print_list.called)
|
||||
|
||||
def args_for(self, **kwargs):
|
||||
"""Generate the default argument list for project-list."""
|
||||
kwargs.setdefault('name', None)
|
||||
kwargs.setdefault('limit', None)
|
||||
kwargs.setdefault('detail', False)
|
||||
kwargs.setdefault('fields', [])
|
||||
return super(TestDoProjectList, self).args_for(**kwargs)
|
||||
|
||||
def test_with_defaults(self):
|
||||
"""Verify behaviour of do_project_list with mostly default values."""
|
||||
args = self.args_for()
|
||||
|
||||
projects_shell.do_project_list(self.craton_client, args)
|
||||
|
||||
self.craton_client.projects.list.assert_called_once_with()
|
||||
self.assertTrue(self.print_list.called)
|
||||
self.assertEqual(['id', 'name'],
|
||||
sorted(self.print_list.call_args[0][-1]))
|
||||
|
||||
def test_negative_limit(self):
|
||||
"""Ensure we raise an exception for negative limits."""
|
||||
args = self.args_for(limit=-1)
|
||||
|
||||
self.assertRaisesCommandErrorWith(projects_shell.do_project_list,
|
||||
args)
|
||||
self.assertNothingWasCalled()
|
||||
|
||||
def test_positive_limit(self):
|
||||
"""Verify that we pass positive limits to the call to list."""
|
||||
args = self.args_for(limit=5)
|
||||
|
||||
projects_shell.do_project_list(self.craton_client, args)
|
||||
|
||||
self.craton_client.projects.list.assert_called_once_with(
|
||||
limit=5,
|
||||
)
|
||||
self.assertTrue(self.print_list.called)
|
||||
self.assertEqual(['id', 'name'],
|
||||
sorted(self.print_list.call_args[0][-1]))
|
||||
|
||||
def test_detail(self):
|
||||
"""Verify the behaviour of specifying --detail."""
|
||||
args = self.args_for(detail=True)
|
||||
|
||||
projects_shell.do_project_list(self.craton_client, args)
|
||||
|
||||
self.craton_client.projects.list.assert_called_once_with()
|
||||
self.assertEqual(sorted(list(projects.PROJECT_FIELDS)),
|
||||
sorted(self.print_list.call_args[0][-1]))
|
||||
|
||||
def test_list_name(self):
|
||||
"""Verify the behaviour of specifying --detail."""
|
||||
args = self.args_for(name='project_1')
|
||||
|
||||
projects_shell.do_project_list(self.craton_client, args)
|
||||
|
||||
self.craton_client.projects.list.assert_called_once_with(
|
||||
name='project_1'
|
||||
)
|
||||
self.assertEqual(['id', 'name'],
|
||||
sorted(self.print_list.call_args[0][-1]))
|
||||
|
||||
def test_raises_exception_with_detail_and_fields(self):
|
||||
"""Verify that we fail when users specify --detail and --fields."""
|
||||
args = self.args_for(
|
||||
detail=True,
|
||||
fields=['id', 'name'],
|
||||
)
|
||||
|
||||
self.assertRaisesCommandErrorWith(projects_shell.do_project_list, args)
|
||||
self.assertNothingWasCalled()
|
||||
|
||||
def test_fields(self):
|
||||
"""Verify that we print out specific fields."""
|
||||
args = self.args_for(fields=['id', 'name'])
|
||||
|
||||
projects_shell.do_project_list(self.craton_client, args)
|
||||
|
||||
self.craton_client.projects.list.assert_called_once_with()
|
||||
self.assertEqual(['id', 'name'],
|
||||
sorted(self.print_list.call_args[0][-1]))
|
||||
|
||||
def test_invalid_fields(self):
|
||||
"""Verify that we error out with invalid fields."""
|
||||
args = self.args_for(fields=['uuid', 'not-name', 'nate'])
|
||||
|
||||
self.assertRaisesCommandErrorWith(projects_shell.do_project_list, args)
|
||||
self.assertNothingWasCalled()
|
||||
|
||||
|
||||
class TestDoProjectCreate(base.TestShellCommandUsingPrintDict):
|
||||
"""Unit tests for the project create command."""
|
||||
|
||||
def args_for(self, **kwargs):
|
||||
"""Generate the default args for project-create."""
|
||||
kwargs.setdefault('name', 'New Project')
|
||||
return super(TestDoProjectCreate, self).args_for(**kwargs)
|
||||
|
||||
def test_create(self):
|
||||
"""Verify our parameters to projects.create."""
|
||||
args = self.args_for()
|
||||
|
||||
projects_shell.do_project_create(self.craton_client, args)
|
||||
|
||||
self.craton_client.projects.create.assert_called_once_with(
|
||||
name='New Project'
|
||||
)
|
||||
self.print_dict.assert_called_once_with(mock.ANY, wrap=72)
|
||||
|
||||
|
||||
class TestDoProjectDelete(base.TestShellCommand):
|
||||
"""Tests for the do_project_delete command."""
|
||||
|
||||
def setUp(self):
|
||||
"""Initialize our print mock."""
|
||||
super(TestDoProjectDelete, self).setUp()
|
||||
self.print_func_mock = mock.patch(
|
||||
'cratonclient.shell.v1.projects_shell.print'
|
||||
)
|
||||
self.print_func = self.print_func_mock.start()
|
||||
self.project_id = uuid.uuid4()
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up our print mock."""
|
||||
super(TestDoProjectDelete, self).tearDown()
|
||||
self.print_func_mock.stop()
|
||||
|
||||
def test_successful(self):
|
||||
"""Verify the message we print when successful."""
|
||||
self.craton_client.projects.delete.return_value = True
|
||||
args = self.args_for(
|
||||
id=self.project_id,
|
||||
)
|
||||
|
||||
projects_shell.do_project_delete(self.craton_client, args)
|
||||
|
||||
self.craton_client.projects.delete.assert_called_once_with(
|
||||
self.project_id)
|
||||
self.print_func.assert_called_once_with(
|
||||
'Project {} was successfully deleted.'.format(self.project_id)
|
||||
)
|
||||
|
||||
def test_failed(self):
|
||||
"""Verify the message we print when deletion fails."""
|
||||
self.craton_client.projects.delete.return_value = False
|
||||
args = self.args_for(
|
||||
id=self.project_id,
|
||||
)
|
||||
|
||||
projects_shell.do_project_delete(self.craton_client, args)
|
||||
|
||||
self.craton_client.projects.delete.assert_called_once_with(
|
||||
self.project_id)
|
||||
self.print_func.assert_called_once_with(
|
||||
'Project {} was not deleted.'.format(self.project_id)
|
||||
)
|
||||
|
||||
def test_failed_with_exception(self):
|
||||
"""Verify the message we print when deletion fails."""
|
||||
self.craton_client.projects.delete.side_effect = exceptions.NotFound
|
||||
args = self.args_for(
|
||||
region=123,
|
||||
id=self.project_id,
|
||||
)
|
||||
|
||||
self.assertRaisesCommandErrorWith(projects_shell.do_project_delete,
|
||||
args)
|
||||
|
||||
self.craton_client.projects.delete.assert_called_once_with(
|
||||
self.project_id)
|
||||
self.assertFalse(self.print_func.called)
|
@ -14,6 +14,7 @@
|
||||
"""Top-level client for version 1 of Craton's API."""
|
||||
from cratonclient.v1 import cells
|
||||
from cratonclient.v1 import hosts
|
||||
from cratonclient.v1 import projects
|
||||
from cratonclient.v1 import regions
|
||||
|
||||
|
||||
@ -40,4 +41,5 @@ class Client(object):
|
||||
manager_kwargs = {'session': self._session, 'url': self._url}
|
||||
self.hosts = hosts.HostManager(**manager_kwargs)
|
||||
self.cells = cells.CellManager(**manager_kwargs)
|
||||
self.projects = projects.ProjectManager(**manager_kwargs)
|
||||
self.regions = regions.RegionManager(**manager_kwargs)
|
||||
|
37
cratonclient/v1/projects.py
Normal file
37
cratonclient/v1/projects.py
Normal file
@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""Regions manager code."""
|
||||
from cratonclient import crud
|
||||
|
||||
|
||||
class Project(crud.Resource):
|
||||
"""Representation of a Project."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ProjectManager(crud.CRUDClient):
|
||||
"""A manager for projects."""
|
||||
|
||||
key = 'project'
|
||||
base_path = '/projects'
|
||||
resource_class = Project
|
||||
|
||||
|
||||
PROJECT_FIELDS = {
|
||||
'id': 'ID',
|
||||
'name': 'Name',
|
||||
'created_at': 'Created At',
|
||||
'update_at': 'Updated At'
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user