mirror of
https://github.com/Hopiu/portainer-cli.git
synced 2026-03-22 08:50:23 +00:00
Update stack ACL command
This commit is contained in:
parent
2d199c2266
commit
a2c36331db
1 changed files with 154 additions and 22 deletions
|
|
@ -31,6 +31,7 @@ class PortainerCLI(object):
|
|||
COMMAND_REQUEST = 'request'
|
||||
COMMAND_CREATE_STACK = 'create_stack'
|
||||
COMMAND_UPDATE_STACK = 'update_stack'
|
||||
COMMAND_UPDATE_STACK_ACL = 'update_stack_acl'
|
||||
COMMAND_CREATE_OR_UPDATE_STACK = 'create_or_update_stack'
|
||||
COMMAND_GET_STACK_ID = 'get_stack_id'
|
||||
COMMAND_UPDATE_REGISTRY = 'update_registry'
|
||||
|
|
@ -40,6 +41,7 @@ class PortainerCLI(object):
|
|||
COMMAND_REQUEST,
|
||||
COMMAND_CREATE_STACK,
|
||||
COMMAND_UPDATE_STACK,
|
||||
COMMAND_UPDATE_STACK_ACL,
|
||||
COMMAND_CREATE_OR_UPDATE_STACK,
|
||||
COMMAND_GET_STACK_ID,
|
||||
COMMAND_UPDATE_REGISTRY
|
||||
|
|
@ -48,6 +50,7 @@ class PortainerCLI(object):
|
|||
METHOD_GET = 'GET'
|
||||
METHOD_POST = 'POST'
|
||||
METHOD_PUT = 'PUT'
|
||||
METHOD_DELETE = 'DELETE'
|
||||
|
||||
local = False
|
||||
_base_url = 'http://localhost:9000/'
|
||||
|
|
@ -149,30 +152,99 @@ class PortainerCLI(object):
|
|||
logger.info('logged with jwt: {}'.format(jwt))
|
||||
self.jwt = jwt
|
||||
|
||||
# Retrieve the stack if. -1 if the stack does not exist
|
||||
@plac.annotations(
|
||||
endpoint_id=('Endpoint id', 'option', 'e'),
|
||||
stack_name=('Stack name', 'option', 'n')
|
||||
)
|
||||
def get_stack_id(self, endpoint_id, stack_name):
|
||||
def get_users(self):
|
||||
users_url = 'users'
|
||||
return self.request(users_url, self.METHOD_GET).json()
|
||||
|
||||
# retrieve users by their names
|
||||
def get_users_by_name(self, names):
|
||||
all_users = self.get_users()
|
||||
if not all_users:
|
||||
logger.debug('No users found')
|
||||
return []
|
||||
users=all_users.
|
||||
for name in names:
|
||||
# searching for user
|
||||
user = next(u for u in all_users if u['Username'] == name)
|
||||
if not user:
|
||||
logger.warn('User with name \'{}\' not found'.format(name))
|
||||
else:
|
||||
logger.debug('User with name \'{}\' found'.format(name))
|
||||
users.append(user)
|
||||
return users
|
||||
|
||||
# retrieve users by their names
|
||||
def get_users_by_name(self, names):
|
||||
all_users = self.get_users()
|
||||
all_users_by_name = dict(map(
|
||||
lambda u: (u['Username'], u),
|
||||
all_users,
|
||||
))
|
||||
users = []
|
||||
for name in names:
|
||||
user = all_users_by_name.get(name)
|
||||
if not user:
|
||||
logger.warn('User with name \'{}\' not found'.format(name))
|
||||
else:
|
||||
logger.debug('User with name \'{}\' found'.format(name))
|
||||
users.append(user)
|
||||
return users
|
||||
|
||||
def get_teams(self):
|
||||
teams_url = 'teams'
|
||||
return self.request(teams_url, self.METHOD_GET).json()
|
||||
|
||||
# retrieve teams by their names
|
||||
def get_teams_by_name(self, names):
|
||||
all_teams = self.get_teams()
|
||||
all_teams_by_name = dict(map(
|
||||
lambda u: (u['Name'], u),
|
||||
all_teams,
|
||||
))
|
||||
teams = []
|
||||
for name in names:
|
||||
team = all_teams_by_name.get(name)
|
||||
if not team:
|
||||
logger.warn('Team with name \'{}\' not found'.format(name))
|
||||
else:
|
||||
logger.debug('Team with name \'{}\' found'.format(name))
|
||||
teams.append(team)
|
||||
return teams
|
||||
|
||||
def get_stacks(self):
|
||||
stack_url = 'stacks'
|
||||
result = self.request(
|
||||
stack_url,
|
||||
self.METHOD_GET
|
||||
).json()
|
||||
|
||||
def get_stack_by_id(self, stack_id, endpoint_id):
|
||||
stack_url = 'stacks/{}?endpointId={}'.format(
|
||||
stack_id,
|
||||
endpoint_id,
|
||||
)
|
||||
return self.request(stack_url).json()
|
||||
|
||||
def get_stack_by_name(self, stack_name):
|
||||
result = self.get_stacks()
|
||||
if not result:
|
||||
logger.debug('Stack with name={} does not exist'.format(
|
||||
stack_name))
|
||||
return -1
|
||||
else:
|
||||
for stack in result:
|
||||
if stack['Name'] == stack_name:
|
||||
logger.debug(
|
||||
'Stack with name={} -> id={}'.format(stack_name, stack['Id']))
|
||||
return stack['Id']
|
||||
logger.debug('Stack with name={} does not exist'.format(
|
||||
stack_name))
|
||||
return None
|
||||
for stack in result:
|
||||
if stack['Name'] == stack_name:
|
||||
return stack
|
||||
return None
|
||||
|
||||
# Retrieve the stack if. -1 if the stack does not exist
|
||||
@plac.annotations(
|
||||
stack_name=('Stack name', 'option', 'n')
|
||||
)
|
||||
def get_stack_id(self, stack_name):
|
||||
stack = self.get_stack_by_name(stack_name)
|
||||
if not stack:
|
||||
logger.debug('Stack with name={} does not exist'.format(stack_name))
|
||||
return -1
|
||||
logger.debug('Stack with name={} -> id={}'.format(stack_name, stack['Id']))
|
||||
return stack['Id']
|
||||
|
||||
def extract_env(self, env_file='', *args):
|
||||
if env_file:
|
||||
|
|
@ -238,6 +310,68 @@ class PortainerCLI(object):
|
|||
self.METHOD_POST,
|
||||
data,
|
||||
)
|
||||
|
||||
def create_or_update_resource_control(self, stack, public, users, teams):
|
||||
# TODO HANDLE RESOURCE_CONTROL CREATION
|
||||
resouce_control = stack['ResourceControl']
|
||||
data = {
|
||||
'Public': public,
|
||||
'Users': users,
|
||||
'Teams': teams
|
||||
}
|
||||
logger.debug('Updating stack acl: {}'.format(data))
|
||||
self.request(
|
||||
'resource_controls/{}'.format(resouce_control['Id']),
|
||||
self.METHOD_PUT,
|
||||
data
|
||||
)
|
||||
|
||||
|
||||
@plac.annotations(
|
||||
stack_id=('Stack id', 'option', 's'),
|
||||
stack_name=('Stack name', 'option', 'n'),
|
||||
endpoint_id=('Endpoint id', 'option', 'e'),
|
||||
ownership_type=('Ownership type', 'option', 'o', ['admin', 'restricted', 'public']),
|
||||
users=('Allowed usernames (comma separated - restricted ownership_type only)', 'option', 'u'),
|
||||
teams=('Allowed teams (comma separated - restricted ownership_type only)', 'option', 't'),
|
||||
clear=('Clear acl (restricted ownership_type only)', 'flag', 'c')
|
||||
)
|
||||
)
|
||||
def update_stack_acl(self, stack_id, stack_name, endpoint_id, ownership_type, users, teams, clear=False):
|
||||
stack = None
|
||||
if stack_id and endpoint_id:
|
||||
stack = self.get_stack_by_id(stack_id, endpoint_id)
|
||||
elif stack_name:
|
||||
stack = self.get_stack_by_name(stack_name)
|
||||
else:
|
||||
logger.error('Please provide either stack_name or (stack_id + endpoint_id)')
|
||||
sys.exit(1)
|
||||
|
||||
logger.info('Updating acl of stack name={} - type={}'.format(stack['Name'], ownership_type))
|
||||
|
||||
resouce_control = stack['ResourceControl']
|
||||
|
||||
if ownership_type == 'admin':
|
||||
if resouce_control:
|
||||
logger.debug('Deleting resource control with id {}'.format(resouce_control['Id']))
|
||||
self.request(
|
||||
'resource_controls/{}'.format(resouce_control['Id']),
|
||||
self.METHOD_DELETE
|
||||
)
|
||||
else:
|
||||
logger.debug('Nothing to do')
|
||||
elif ownership_type == 'public':
|
||||
self.create_or_update_resource_control(stack, true, [], [])
|
||||
elif ownership_type == 'restricted':
|
||||
users = map(lambda u: u['Id'], self.get_users_by_name(users.split(',')))
|
||||
teams = map(lambda t: t['Id'], self.get_teams_by_name(users.split(',')))
|
||||
|
||||
if (not clear) and resouce_control:
|
||||
logger.debug('Merging existing users / teams')
|
||||
users = list(set().union(users, map(lamba u: u['UserId'], resouce_control['UserAccesses'])))
|
||||
teams = list(set().union(teams, map(lamba t: t['TeamId'], resouce_control['TeamAccesses'])))
|
||||
|
||||
self.create_or_update_resource_control(stack, true, users, teams)
|
||||
|
||||
@plac.annotations(
|
||||
stack_id=('Stack id', 'option', 's'),
|
||||
|
|
@ -250,11 +384,7 @@ class PortainerCLI(object):
|
|||
def update_stack(self, stack_id, endpoint_id, stack_file='', env_file='',
|
||||
prune=False, clear_env=False, *args):
|
||||
logger.info('Updating stack id={}'.format(stack_id))
|
||||
stack_url = 'stacks/{}?endpointId={}'.format(
|
||||
stack_id,
|
||||
endpoint_id,
|
||||
)
|
||||
current = self.request(stack_url).json()
|
||||
current = self.get_stack_by_id(stack_id, endpoint_id)
|
||||
stack_file_content = ''
|
||||
if stack_file:
|
||||
stack_file_content = open(stack_file).read()
|
||||
|
|
@ -374,6 +504,8 @@ class PortainerCLI(object):
|
|||
plac.call(self.create_stack, args)
|
||||
elif command == self.COMMAND_UPDATE_STACK:
|
||||
plac.call(self.update_stack, args)
|
||||
elif command == self.COMMAND_UPDATE_STACK_ACL:
|
||||
plac.call(self.update_stack_acl, args)
|
||||
elif command == self.COMMAND_CREATE_OR_UPDATE_STACK:
|
||||
plac.call(self.create_or_update_stack, args)
|
||||
elif command == self.COMMAND_GET_STACK_ID:
|
||||
|
|
|
|||
Loading…
Reference in a new issue