diff options
author | aszlig <aszlig@redmoonstudios.org> | 2016-04-12 03:42:13 +0200 |
---|---|---|
committer | aszlig <aszlig@redmoonstudios.org> | 2016-04-12 03:42:13 +0200 |
commit | a41b109bc10e66824af5e1f150cb741f9f9399c2 (patch) | |
tree | 0cee8f306bd1f8b2a6ad285e9c45c63dec09fb12 /nixos | |
parent | 9586795ef27ac4d406c10c12f92fc735b5f4ff24 (diff) | |
download | nixlib-a41b109bc10e66824af5e1f150cb741f9f9399c2.tar nixlib-a41b109bc10e66824af5e1f150cb741f9f9399c2.tar.gz nixlib-a41b109bc10e66824af5e1f150cb741f9f9399c2.tar.bz2 nixlib-a41b109bc10e66824af5e1f150cb741f9f9399c2.tar.lz nixlib-a41b109bc10e66824af5e1f150cb741f9f9399c2.tar.xz nixlib-a41b109bc10e66824af5e1f150cb741f9f9399c2.tar.zst nixlib-a41b109bc10e66824af5e1f150cb741f9f9399c2.zip |
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>
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/modules/services/misc/taskserver/helper-tool.py | 69 | ||||
-rw-r--r-- | nixos/tests/taskserver.nix | 10 |
2 files changed, 70 insertions, 9 deletions
diff --git a/nixos/modules/services/misc/taskserver/helper-tool.py b/nixos/modules/services/misc/taskserver/helper-tool.py index 30dcfe0a7a25..512aaa4ab9f8 100644 --- a/nixos/modules/services/misc/taskserver/helper-tool.py +++ b/nixos/modules/services/misc/taskserver/helper-tool.py @@ -96,6 +96,28 @@ def mkpath(*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): for line in open(mkpath(org, "users", key, "config"), "r"): match = RE_CONFIGUSER.match(line) @@ -247,8 +269,9 @@ class Group(object): class Organisation(object): - def __init__(self, name): + def __init__(self, name, ignore_imperative): self.name = name + self.ignore_imperative = ignore_imperative def add_user(self, name): """ @@ -256,6 +279,8 @@ class Organisation(object): 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(): output = taskd_cmd("add", "user", self.name, name, capture_stdout=True) @@ -265,7 +290,7 @@ class Organisation(object): raise TaskdError(msg.format(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 return newuser return None @@ -275,8 +300,12 @@ class Organisation(object): Delete a user and revoke its keys. """ if name in self.users.keys(): - # Work around https://bug.tasktools.org/browse/TD-40: 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)) revoke_key(self.name, name) @@ -288,6 +317,8 @@ class Organisation(object): 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(): taskd_cmd("add", "group", self.name, name) newgroup = Group(self.name, name) @@ -300,6 +331,9 @@ class Organisation(object): Delete a group. """ 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) del self._lazy_groups[name] @@ -327,6 +361,16 @@ class Organisation(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): """ Create a new organisation. @@ -336,7 +380,7 @@ class Manager(object): """ if name not in self.orgs.keys(): taskd_cmd("add", "org", name) - neworg = Organisation(name) + neworg = Organisation(name, self.ignore_imperative) self._lazy_orgs[name] = neworg return neworg return None @@ -348,6 +392,8 @@ class Manager(object): """ org = self.get_org(name) if org is not None: + if self.ignore_imperative and is_imperative(name): + return for user in org.users.keys(): org.del_user(user) for group in org.groups.keys(): @@ -362,7 +408,7 @@ class Manager(object): def orgs(self): result = {} for org in os.listdir(mkpath()): - result[org] = Organisation(org) + result[org] = Organisation(org, self.ignore_imperative) return result @@ -452,6 +498,7 @@ def add_org(name): sys.exit(msg.format(name)) taskd_cmd("add", "org", name) + mark_imperative(name) @cli.command("del-org") @@ -485,6 +532,8 @@ def add_user(organisation, user): if userobj is None: msg = "User {} already exists in organisation {}." sys.exit(msg.format(user, organisation)) + else: + mark_imperative(organisation.name, "users", userobj.key) @cli.command("del-user") @@ -510,10 +559,12 @@ def add_group(organisation, group): """ Create a group for the given organisation. """ - userobj = organisation.add_group(group) - if userobj is None: + groupobj = organisation.add_group(group) + if groupobj is None: msg = "Group {} already exists in organisation {}." sys.exit(msg.format(group, organisation)) + else: + mark_imperative(organisation.name, "groups", groupobj.name) @cli.command("del-group") @@ -562,10 +613,12 @@ def process_json(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) for org in mgr.orgs.values(): + if is_imperative(org.name): + continue add_or_delete(org.users.keys(), data[org.name]['users'], org.add_user, org.del_user) add_or_delete(org.groups.keys(), data[org.name]['groups'], diff --git a/nixos/tests/taskserver.nix b/nixos/tests/taskserver.nix index 5d2e030a8f6d..79a7703f037e 100644 --- a/nixos/tests/taskserver.nix +++ b/nixos/tests/taskserver.nix @@ -41,7 +41,8 @@ import ./make-test.nix { for my $client ($client1, $client2) { $client->nest("initialize client for user $user", sub { $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( @@ -156,5 +157,12 @@ import ./make-test.nix { $client1->succeed(su "bar", "task add destroy even more >&2"); $client1->fail(su "bar", "task sync >&2"); }; + + readdImperativeUser; + + subtest "check whether declarative config overrides user bar", sub { + restartServer; + testSync "bar"; + }; ''; } |