Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backup #314

Merged
merged 7 commits into from
Nov 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions fusillade/clouddirectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,15 @@ def list_policy_attachments(self, policy: str, **kwargs) -> Iterator[str]:
**kwargs
)

def list_object_parent_paths(self, object_ref: str, **kwargs) -> Iterator[str]:
return _paging_loop(cd_client.list_object_parent_paths,
'PathToObjectIdentifiersList',
DirectoryArn=self._dir_arn,
ObjectReference={'Selector': object_ref},
MaxResults=self._page_limit,
**kwargs
)

@retry(**cd_read_retry_parameters)
def _list_typed_links(self,
func: Callable,
Expand Down Expand Up @@ -423,7 +432,7 @@ def list_incoming_typed_links(

@staticmethod
def _make_ref(i):
return '$' + i
return i if i[0] == '$' else '$' + i

def create_object(self, link_name: str, facet_type: str, obj_type: str, **kwargs) -> str:
"""
Expand Down Expand Up @@ -1040,7 +1049,7 @@ class CloudNode:
Contains shared code across the different types of nodes stored in Fusillade CloudDirectory
"""
_attributes = ["name"] # the different attributes of a node stored
_facet = 'LeafNode'
_facet = 'LeafFacet'
object_type = 'node'

def __init__(self,
Expand Down Expand Up @@ -1270,6 +1279,25 @@ def _exists(cls, nodes: List[str]):
except cd_client.exceptions.ResourceNotFoundException:
raise FusilladeBadRequestException(f"One or more {cls.object_type} does not exist.")

def list_owners(self, incoming=True):
get_links = self.cd.list_incoming_typed_links if incoming else self.cd.list_outgoing_typed_links
object_selection = 'SourceObjectReference' if incoming else 'TargetObjectReference'
_owners = [
type_link[object_selection]['Selector']
for type_link in
get_links(self.object_ref, filter_typed_link='ownership_link')
]
owners = []
for owner in _owners:
node = CloudNode(object_ref=owner)
owners.append({
'type': [i for i in
[p['Path'].split('/')[1]
for p in node.cd.list_object_parent_paths(node.object_ref)] if i != 'role'][0],
'name': node.name
})
return owners


class PolicyMixin:
"""Adds policy support to a cloudNode"""
Expand Down
95 changes: 95 additions & 0 deletions scripts/backup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env python
"""
Create a backup of Clouddirectory and output the file ro backup.json
"""

import json
import os
import sys
import typing

pkg_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) # noqa
sys.path.insert(0, pkg_root) # noqa

from fusillade.clouddirectory import User, Group, Role, CloudNode


def format_policies(policies: typing.List[typing.Tuple[str, str]]) -> typing.Dict[str, str]:
rv = dict()
for t, p in policies:
if not p:
continue
else:
rv[t] = json.loads(p)
return rv


def list_node(node, field):
result, next_token = node.list_all(None, None)
while True:
for i in result[field]:
yield i
if next_token:
result, next_token = node.list_all(next_token, None)
else:
break


def backup_users():
users = []
for name in list_node(User, 'users'):
user = User(name)
info = {
'name': user.name,
'status': user.status,
'policies': format_policies([(p, user.get_policy(p)) for p in user.allowed_policy_types]),
'roles': [Role(object_ref=r).name for r in user.roles]
}
users.append(info)
print("USERS:", *users, sep='\n\t')
return users


def backup_groups():
groups = []
for name in list_node(Group, 'groups'):
group = Group(name)
info = {
'name': group.name,
'members': [User(object_ref=u).name for u in group.get_users_iter()],
'policies': format_policies([(p, group.get_policy(p)) for p in group.allowed_policy_types]),
'owners': group.list_owners(),
'roles': [Role(object_ref=r).name for r in group.roles]
}
groups.append(info)
print("GROUPS:", *groups, sep='\n\t')
return groups


def backup_roles():
roles = []
for name in list_node(Role, 'roles'):
role = Role(name)
info = {
'name': role.name,
'policies': format_policies([(p, role.get_policy(p)) for p in role.allowed_policy_types]),
'owners': role.list_owners()
}
roles.append(info)
print("ROLES:", *roles, sep='\n\t')
return roles


def backup():
with open('backup.json', 'w') as fp:
json.dump(
dict(
users=backup_users(),
groups=backup_groups(),
roles=backup_roles()),
fp,
indent=2)


add if __name__ == "__main__":
backup()