nixos/taskserver: Don't change imperative users
Whenever the nixos-taskserver tool was invoked manually for creating an organisation/group/user we now add an empty file called .imperative to the data directory. During the preStart of the Taskserver service, we use process-json which in turn now checks whether those .imperative files exist and if so, it doesn't do anything with it. This should now ensure that whenever there is a manually created user, it doesn't get killed off by the declarative configuration in case it shouldn't exist within that configuration. In addition, we also add a small subtest to check whether this is happening or not and fail if the imperatively created user got deleted by process-json. Signed-off-by: aszlig <aszlig@redmoonstudios.org>
This commit is contained in:
parent
9586795ef2
commit
a41b109bc1
@ -96,6 +96,28 @@ def mkpath(*args):
|
|||||||
return os.path.join(TASKD_DATA_DIR, "orgs", *args)
|
return os.path.join(TASKD_DATA_DIR, "orgs", *args)
|
||||||
|
|
||||||
|
|
||||||
|
def mark_imperative(*path):
|
||||||
|
"""
|
||||||
|
Mark the specified path as being imperatively managed by creating an empty
|
||||||
|
file called ".imperative", so that it doesn't interfere with the
|
||||||
|
declarative configuration.
|
||||||
|
"""
|
||||||
|
open(os.path.join(mkpath(*path), ".imperative"), 'a').close()
|
||||||
|
|
||||||
|
|
||||||
|
def is_imperative(*path):
|
||||||
|
"""
|
||||||
|
Check whether the given path is marked as imperative, see mark_imperative()
|
||||||
|
for more information.
|
||||||
|
"""
|
||||||
|
full_path = []
|
||||||
|
for component in path:
|
||||||
|
full_path.append(component)
|
||||||
|
if os.path.exists(os.path.join(mkpath(*full_path), ".imperative")):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def fetch_username(org, key):
|
def fetch_username(org, key):
|
||||||
for line in open(mkpath(org, "users", key, "config"), "r"):
|
for line in open(mkpath(org, "users", key, "config"), "r"):
|
||||||
match = RE_CONFIGUSER.match(line)
|
match = RE_CONFIGUSER.match(line)
|
||||||
@ -247,8 +269,9 @@ class Group(object):
|
|||||||
|
|
||||||
|
|
||||||
class Organisation(object):
|
class Organisation(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name, ignore_imperative):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.ignore_imperative = ignore_imperative
|
||||||
|
|
||||||
def add_user(self, name):
|
def add_user(self, name):
|
||||||
"""
|
"""
|
||||||
@ -256,6 +279,8 @@ class Organisation(object):
|
|||||||
|
|
||||||
Returns a 'User' object or None if the user already exists.
|
Returns a 'User' object or None if the user already exists.
|
||||||
"""
|
"""
|
||||||
|
if self.ignore_imperative and is_imperative(self.name):
|
||||||
|
return None
|
||||||
if name not in self.users.keys():
|
if name not in self.users.keys():
|
||||||
output = taskd_cmd("add", "user", self.name, name,
|
output = taskd_cmd("add", "user", self.name, name,
|
||||||
capture_stdout=True)
|
capture_stdout=True)
|
||||||
@ -265,7 +290,7 @@ class Organisation(object):
|
|||||||
raise TaskdError(msg.format(name))
|
raise TaskdError(msg.format(name))
|
||||||
|
|
||||||
generate_key(self.name, name)
|
generate_key(self.name, name)
|
||||||
newuser = User(self.name, name, key)
|
newuser = User(self.name, name, key.group(1))
|
||||||
self._lazy_users[name] = newuser
|
self._lazy_users[name] = newuser
|
||||||
return newuser
|
return newuser
|
||||||
return None
|
return None
|
||||||
@ -275,8 +300,12 @@ class Organisation(object):
|
|||||||
Delete a user and revoke its keys.
|
Delete a user and revoke its keys.
|
||||||
"""
|
"""
|
||||||
if name in self.users.keys():
|
if name in self.users.keys():
|
||||||
# Work around https://bug.tasktools.org/browse/TD-40:
|
|
||||||
user = self.get_user(name)
|
user = self.get_user(name)
|
||||||
|
if self.ignore_imperative and \
|
||||||
|
is_imperative(self.name, "users", user.key):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Work around https://bug.tasktools.org/browse/TD-40:
|
||||||
rmtree(mkpath(self.name, "users", user.key))
|
rmtree(mkpath(self.name, "users", user.key))
|
||||||
|
|
||||||
revoke_key(self.name, name)
|
revoke_key(self.name, name)
|
||||||
@ -288,6 +317,8 @@ class Organisation(object):
|
|||||||
|
|
||||||
Returns a 'Group' object or None if the group already exists.
|
Returns a 'Group' object or None if the group already exists.
|
||||||
"""
|
"""
|
||||||
|
if self.ignore_imperative and is_imperative(self.name):
|
||||||
|
return None
|
||||||
if name not in self.groups.keys():
|
if name not in self.groups.keys():
|
||||||
taskd_cmd("add", "group", self.name, name)
|
taskd_cmd("add", "group", self.name, name)
|
||||||
newgroup = Group(self.name, name)
|
newgroup = Group(self.name, name)
|
||||||
@ -300,6 +331,9 @@ class Organisation(object):
|
|||||||
Delete a group.
|
Delete a group.
|
||||||
"""
|
"""
|
||||||
if name in self.users.keys():
|
if name in self.users.keys():
|
||||||
|
if self.ignore_imperative and \
|
||||||
|
is_imperative(self.name, "groups", name):
|
||||||
|
return
|
||||||
taskd_cmd("remove", "group", self.name, name)
|
taskd_cmd("remove", "group", self.name, name)
|
||||||
del self._lazy_groups[name]
|
del self._lazy_groups[name]
|
||||||
|
|
||||||
@ -327,6 +361,16 @@ class Organisation(object):
|
|||||||
|
|
||||||
|
|
||||||
class Manager(object):
|
class Manager(object):
|
||||||
|
def __init__(self, ignore_imperative=False):
|
||||||
|
"""
|
||||||
|
Instantiates an organisations manager.
|
||||||
|
|
||||||
|
If ignore_imperative is True, all actions that modify data are checked
|
||||||
|
whether they're created imperatively and if so, they will result in no
|
||||||
|
operation.
|
||||||
|
"""
|
||||||
|
self.ignore_imperative = ignore_imperative
|
||||||
|
|
||||||
def add_org(self, name):
|
def add_org(self, name):
|
||||||
"""
|
"""
|
||||||
Create a new organisation.
|
Create a new organisation.
|
||||||
@ -336,7 +380,7 @@ class Manager(object):
|
|||||||
"""
|
"""
|
||||||
if name not in self.orgs.keys():
|
if name not in self.orgs.keys():
|
||||||
taskd_cmd("add", "org", name)
|
taskd_cmd("add", "org", name)
|
||||||
neworg = Organisation(name)
|
neworg = Organisation(name, self.ignore_imperative)
|
||||||
self._lazy_orgs[name] = neworg
|
self._lazy_orgs[name] = neworg
|
||||||
return neworg
|
return neworg
|
||||||
return None
|
return None
|
||||||
@ -348,6 +392,8 @@ class Manager(object):
|
|||||||
"""
|
"""
|
||||||
org = self.get_org(name)
|
org = self.get_org(name)
|
||||||
if org is not None:
|
if org is not None:
|
||||||
|
if self.ignore_imperative and is_imperative(name):
|
||||||
|
return
|
||||||
for user in org.users.keys():
|
for user in org.users.keys():
|
||||||
org.del_user(user)
|
org.del_user(user)
|
||||||
for group in org.groups.keys():
|
for group in org.groups.keys():
|
||||||
@ -362,7 +408,7 @@ class Manager(object):
|
|||||||
def orgs(self):
|
def orgs(self):
|
||||||
result = {}
|
result = {}
|
||||||
for org in os.listdir(mkpath()):
|
for org in os.listdir(mkpath()):
|
||||||
result[org] = Organisation(org)
|
result[org] = Organisation(org, self.ignore_imperative)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@ -452,6 +498,7 @@ def add_org(name):
|
|||||||
sys.exit(msg.format(name))
|
sys.exit(msg.format(name))
|
||||||
|
|
||||||
taskd_cmd("add", "org", name)
|
taskd_cmd("add", "org", name)
|
||||||
|
mark_imperative(name)
|
||||||
|
|
||||||
|
|
||||||
@cli.command("del-org")
|
@cli.command("del-org")
|
||||||
@ -485,6 +532,8 @@ def add_user(organisation, user):
|
|||||||
if userobj is None:
|
if userobj is None:
|
||||||
msg = "User {} already exists in organisation {}."
|
msg = "User {} already exists in organisation {}."
|
||||||
sys.exit(msg.format(user, organisation))
|
sys.exit(msg.format(user, organisation))
|
||||||
|
else:
|
||||||
|
mark_imperative(organisation.name, "users", userobj.key)
|
||||||
|
|
||||||
|
|
||||||
@cli.command("del-user")
|
@cli.command("del-user")
|
||||||
@ -510,10 +559,12 @@ def add_group(organisation, group):
|
|||||||
"""
|
"""
|
||||||
Create a group for the given organisation.
|
Create a group for the given organisation.
|
||||||
"""
|
"""
|
||||||
userobj = organisation.add_group(group)
|
groupobj = organisation.add_group(group)
|
||||||
if userobj is None:
|
if groupobj is None:
|
||||||
msg = "Group {} already exists in organisation {}."
|
msg = "Group {} already exists in organisation {}."
|
||||||
sys.exit(msg.format(group, organisation))
|
sys.exit(msg.format(group, organisation))
|
||||||
|
else:
|
||||||
|
mark_imperative(organisation.name, "groups", groupobj.name)
|
||||||
|
|
||||||
|
|
||||||
@cli.command("del-group")
|
@cli.command("del-group")
|
||||||
@ -562,10 +613,12 @@ def process_json(json_file):
|
|||||||
"""
|
"""
|
||||||
data = json.load(json_file)
|
data = json.load(json_file)
|
||||||
|
|
||||||
mgr = Manager()
|
mgr = Manager(ignore_imperative=True)
|
||||||
add_or_delete(mgr.orgs.keys(), data.keys(), mgr.add_org, mgr.del_org)
|
add_or_delete(mgr.orgs.keys(), data.keys(), mgr.add_org, mgr.del_org)
|
||||||
|
|
||||||
for org in mgr.orgs.values():
|
for org in mgr.orgs.values():
|
||||||
|
if is_imperative(org.name):
|
||||||
|
continue
|
||||||
add_or_delete(org.users.keys(), data[org.name]['users'],
|
add_or_delete(org.users.keys(), data[org.name]['users'],
|
||||||
org.add_user, org.del_user)
|
org.add_user, org.del_user)
|
||||||
add_or_delete(org.groups.keys(), data[org.name]['groups'],
|
add_or_delete(org.groups.keys(), data[org.name]['groups'],
|
||||||
|
@ -41,7 +41,8 @@ import ./make-test.nix {
|
|||||||
for my $client ($client1, $client2) {
|
for my $client ($client1, $client2) {
|
||||||
$client->nest("initialize client for user $user", sub {
|
$client->nest("initialize client for user $user", sub {
|
||||||
$client->succeed(
|
$client->succeed(
|
||||||
su $user, "task rc.confirmation=no config confirmation no"
|
(su $user, "rm -rf /home/$user/.task"),
|
||||||
|
(su $user, "task rc.confirmation=no config confirmation no")
|
||||||
);
|
);
|
||||||
|
|
||||||
my $exportinfo = $server->succeed(
|
my $exportinfo = $server->succeed(
|
||||||
@ -156,5 +157,12 @@ import ./make-test.nix {
|
|||||||
$client1->succeed(su "bar", "task add destroy even more >&2");
|
$client1->succeed(su "bar", "task add destroy even more >&2");
|
||||||
$client1->fail(su "bar", "task sync >&2");
|
$client1->fail(su "bar", "task sync >&2");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
readdImperativeUser;
|
||||||
|
|
||||||
|
subtest "check whether declarative config overrides user bar", sub {
|
||||||
|
restartServer;
|
||||||
|
testSync "bar";
|
||||||
|
};
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user