From 3ad1af8d1df84503046e01a45c266d21ca662f2b Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Tue, 7 Jan 2020 12:32:45 -0800 Subject: [PATCH 1/4] enable default button in service configuration --- daemon/core/gui/dialogs/serviceconfig.py | 67 ++++++++++++++---------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/daemon/core/gui/dialogs/serviceconfig.py b/daemon/core/gui/dialogs/serviceconfig.py index fd4f8c26..c97bb25b 100644 --- a/daemon/core/gui/dialogs/serviceconfig.py +++ b/daemon/core/gui/dialogs/serviceconfig.py @@ -55,25 +55,25 @@ class ServiceConfigDialog(Dialog): def load(self): try: self.app.core.create_nodes_and_links() - service_configs = self.app.core.service_configs + default_config = self.app.core.get_node_service( + self.node_id, self.service_name + ) + custom_configs = self.app.core.service_configs if ( - self.node_id in service_configs - and self.service_name in service_configs[self.node_id] + self.node_id in custom_configs + and self.service_name in custom_configs[self.node_id] ): - service_config = self.app.core.service_configs[self.node_id][ - self.service_name - ] + service_config = custom_configs[self.node_id][self.service_name] else: - service_config = self.app.core.get_node_service( - self.node_id, self.service_name - ) - self.dependencies = [x for x in service_config.dependencies] - self.executables = [x for x in service_config.executables] + service_config = default_config + + self.dependencies = service_config.dependencies[:] + self.executables = service_config.executables[:] self.metadata = service_config.meta - self.filenames = [x for x in service_config.configs] - self.startup_commands = [x for x in service_config.startup] - self.validation_commands = [x for x in service_config.validate] - self.shutdown_commands = [x for x in service_config.shutdown] + self.filenames = service_config.configs[:] + self.startup_commands = service_config.startup[:] + self.validation_commands = service_config.validate[:] + self.shutdown_commands = service_config.shutdown[:] self.validation_mode = service_config.validation_mode self.validation_time = service_config.validation_timer self.original_service_files = { @@ -82,9 +82,7 @@ class ServiceConfigDialog(Dialog): ) for x in self.filenames } - self.temp_service_files = { - x: self.original_service_files[x] for x in self.original_service_files - } + self.temp_service_files = dict(self.original_service_files) file_configs = self.app.core.file_configs if ( self.node_id in file_configs @@ -116,8 +114,6 @@ class ServiceConfigDialog(Dialog): self.draw_tab_startstop() self.draw_tab_configuration() - button = ttk.Button(self.top, text="Only Save Changes") - button.grid(sticky="ew", pady=PADY) self.draw_buttons() def draw_tab_files(self): @@ -332,9 +328,7 @@ class ServiceConfigDialog(Dialog): frame.columnconfigure(i, weight=1) button = ttk.Button(frame, text="Apply", command=self.click_apply) button.grid(row=0, column=0, sticky="ew", padx=PADX) - button = ttk.Button( - frame, text="Defaults", command=self.click_defaults, state="disabled" - ) + button = ttk.Button(frame, text="Defaults", command=self.click_defaults) button.grid(row=0, column=1, sticky="ew", padx=PADX) button = ttk.Button( frame, text="Copy...", command=self.click_copy, state="disabled" @@ -409,8 +403,8 @@ class ServiceConfigDialog(Dialog): ) if self.node_id not in service_configs: service_configs[self.node_id] = {} - if self.service_name not in service_configs[self.node_id]: - self.app.core.service_configs[self.node_id][self.service_name] = config + # if self.service_name not in service_configs[self.node_id]: + self.app.core.service_configs[self.node_id][self.service_name] = config for file in self.modified_files: file_configs = self.app.core.file_configs if self.node_id not in file_configs: @@ -444,10 +438,25 @@ class ServiceConfigDialog(Dialog): self.modified_files.discard(filename) def click_defaults(self): - logging.info("not implemented") + self.app.core.service_configs.pop(self.node_id, None) + self.app.core.file_configs.pop(self.node_id, None) + service_config = self.app.core.get_node_service(self.node_id, self.service_name) + self.startup_commands = service_config.startup[:] + self.validation_commands = service_config.validate[:] + self.shutdown_commands = service_config.shutdown[:] + self.temp_service_files = dict(self.original_service_files) + filename = self.filename_combobox.get() + self.service_file_data.text.delete(1.0, "end") + self.service_file_data.text.insert("end", self.temp_service_files[filename]) + self.startup_commands_listbox.delete(0, tk.END) + self.validate_commands_listbox.delete(0, tk.END) + self.shutdown_commands_listbox.delete(0, tk.END) + for cmd in self.startup_commands: + self.startup_commands_listbox.insert(tk.END, cmd) + for cmd in self.validation_commands: + self.validate_commands_listbox.insert(tk.END, cmd) + for cmd in self.shutdown_commands: + self.shutdown_commands_listbox.insert(tk.END, cmd) def click_copy(self): logging.info("not implemented") - - def click_cancel(self): - logging.info("not implemented") From 6105439ae41dedd5c7448f6526e9beb4d5491a61 Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Tue, 7 Jan 2020 13:36:04 -0800 Subject: [PATCH 2/4] color custom services green --- daemon/core/gui/dialogs/serviceconfig.py | 32 ++++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/daemon/core/gui/dialogs/serviceconfig.py b/daemon/core/gui/dialogs/serviceconfig.py index c97bb25b..2b5e0b4b 100644 --- a/daemon/core/gui/dialogs/serviceconfig.py +++ b/daemon/core/gui/dialogs/serviceconfig.py @@ -17,6 +17,7 @@ class ServiceConfigDialog(Dialog): def __init__(self, master, app, service_name, node_id): title = f"{service_name} Service" super().__init__(master, app, title, modal=True) + self.master = master self.app = app self.core = app.core self.node_id = node_id @@ -30,6 +31,9 @@ class ServiceConfigDialog(Dialog): self.startup_commands = [] self.validation_commands = [] self.shutdown_commands = [] + self.default_startup = [] + self.default_validate = [] + self.default_shutdown = [] self.validation_mode = None self.validation_time = None self.validation_period = None @@ -58,6 +62,9 @@ class ServiceConfigDialog(Dialog): default_config = self.app.core.get_node_service( self.node_id, self.service_name ) + self.default_startup = default_config.startup[:] + self.default_validate = default_config.validate[:] + self.default_shutdown = default_config.shutdown[:] custom_configs = self.app.core.service_configs if ( self.node_id in custom_configs @@ -389,6 +396,11 @@ class ServiceConfigDialog(Dialog): entry.delete(0, tk.END) def click_apply(self): + current_listbox = self.master.current.listbox + if not self.is_custom_service(): + current_listbox.itemconfig(current_listbox.curselection()[0], bg="") + self.destroy() + return service_configs = self.app.core.service_configs startup_commands = self.startup_commands_listbox.get(0, "end") shutdown_commands = self.shutdown_commands_listbox.get(0, "end") @@ -403,7 +415,6 @@ class ServiceConfigDialog(Dialog): ) if self.node_id not in service_configs: service_configs[self.node_id] = {} - # if self.service_name not in service_configs[self.node_id]: self.app.core.service_configs[self.node_id][self.service_name] = config for file in self.modified_files: file_configs = self.app.core.file_configs @@ -418,6 +429,7 @@ class ServiceConfigDialog(Dialog): self.app.core.set_node_service_file( self.node_id, self.service_name, file, self.temp_service_files[file] ) + current_listbox.itemconfig(current_listbox.curselection()[0], bg="green") except grpc.RpcError as e: show_grpc_error(e) self.destroy() @@ -437,13 +449,23 @@ class ServiceConfigDialog(Dialog): else: self.modified_files.discard(filename) + def is_custom_service(self): + startup_commands = self.startup_commands_listbox.get(0, "end") + shutdown_commands = self.shutdown_commands_listbox.get(0, "end") + validate_commands = self.validate_commands_listbox.get(0, "end") + return ( + set(self.default_startup) != set(startup_commands) + or set(self.default_validate) != set(validate_commands) + or set(self.default_shutdown) != set(shutdown_commands) + or len(self.modified_files) > 0 + ) + def click_defaults(self): self.app.core.service_configs.pop(self.node_id, None) self.app.core.file_configs.pop(self.node_id, None) - service_config = self.app.core.get_node_service(self.node_id, self.service_name) - self.startup_commands = service_config.startup[:] - self.validation_commands = service_config.validate[:] - self.shutdown_commands = service_config.shutdown[:] + self.startup_commands = self.default_startup + self.validation_commands = self.default_validate + self.shutdown_commands = self.default_shutdown self.temp_service_files = dict(self.original_service_files) filename = self.filename_combobox.get() self.service_file_data.text.delete(1.0, "end") From be0f170f89bc5f20f7c47da783164d4c1cc4039d Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Tue, 7 Jan 2020 15:05:05 -0800 Subject: [PATCH 3/4] add a button to more conveniently remove a node's service --- daemon/core/gui/dialogs/nodeservice.py | 36 ++++++++++++++++++++++-- daemon/core/gui/dialogs/serviceconfig.py | 29 +++++++++++-------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/daemon/core/gui/dialogs/nodeservice.py b/daemon/core/gui/dialogs/nodeservice.py index 2bbe0589..e0d36412 100644 --- a/daemon/core/gui/dialogs/nodeservice.py +++ b/daemon/core/gui/dialogs/nodeservice.py @@ -68,22 +68,26 @@ class NodeServiceDialog(Dialog): self.current.grid(sticky="nsew") for service in sorted(self.current_services): self.current.listbox.insert(tk.END, service) + if self.is_custom_service(service): + self.current.listbox.itemconfig(tk.END, bg="green") frame = ttk.Frame(self.top) frame.grid(stick="ew") - for i in range(3): + for i in range(4): frame.columnconfigure(i, weight=1) button = ttk.Button(frame, text="Configure", command=self.click_configure) button.grid(row=0, column=0, sticky="ew", padx=PADX) button = ttk.Button(frame, text="Save", command=self.click_save) button.grid(row=0, column=1, sticky="ew", padx=PADX) + button = ttk.Button(frame, text="Remove", command=self.click_remove) + button.grid(row=0, column=2, sticky="ew", padx=PADX) button = ttk.Button(frame, text="Cancel", command=self.click_cancel) - button.grid(row=0, column=2, sticky="ew") + button.grid(row=0, column=3, sticky="ew") # trigger group change self.groups.listbox.event_generate("<>") - def handle_group_change(self, event): + def handle_group_change(self, event=None): selection = self.groups.listbox.curselection() if selection: index = selection[0] @@ -101,6 +105,8 @@ class NodeServiceDialog(Dialog): self.current.listbox.delete(0, tk.END) for name in sorted(self.current_services): self.current.listbox.insert(tk.END, name) + if self.is_custom_service(name): + self.current.listbox.itemconfig(tk.END, bg="green") self.canvas_node.core_node.services[:] = self.current_services def click_configure(self): @@ -132,3 +138,27 @@ class NodeServiceDialog(Dialog): def click_cancel(self): self.current_services = None self.destroy() + + def click_remove(self): + cur = self.current.listbox.curselection() + if cur: + service = self.current.listbox.get(cur[0]) + self.current.listbox.delete(cur[0]) + self.current_services.remove(service) + for checkbutton in self.services.frame.winfo_children(): + if checkbutton["text"] == service: + checkbutton.invoke() + return + + def is_custom_service(self, service): + service_configs = self.app.core.service_configs + file_configs = self.app.core.file_configs + if self.node_id in service_configs and service in service_configs[self.node_id]: + return True + if ( + self.node_id in file_configs + and service in file_configs[self.node_id] + and file_configs[self.node_id][service] + ): + return True + return False diff --git a/daemon/core/gui/dialogs/serviceconfig.py b/daemon/core/gui/dialogs/serviceconfig.py index 2b5e0b4b..9fc1ce1f 100644 --- a/daemon/core/gui/dialogs/serviceconfig.py +++ b/daemon/core/gui/dialogs/serviceconfig.py @@ -22,6 +22,9 @@ class ServiceConfigDialog(Dialog): self.core = app.core self.node_id = node_id self.service_name = service_name + self.service_configs = app.core.service_configs + self.file_configs = app.core.file_configs + self.radiovar = tk.IntVar() self.radiovar.set(2) self.metadata = "" @@ -65,7 +68,7 @@ class ServiceConfigDialog(Dialog): self.default_startup = default_config.startup[:] self.default_validate = default_config.validate[:] self.default_shutdown = default_config.shutdown[:] - custom_configs = self.app.core.service_configs + custom_configs = self.service_configs if ( self.node_id in custom_configs and self.service_name in custom_configs[self.node_id] @@ -398,10 +401,11 @@ class ServiceConfigDialog(Dialog): def click_apply(self): current_listbox = self.master.current.listbox if not self.is_custom_service(): + if self.node_id in self.app.core.service_configs: + self.service_configs[self.node_id].pop(self.service_name, None) current_listbox.itemconfig(current_listbox.curselection()[0], bg="") self.destroy() return - service_configs = self.app.core.service_configs startup_commands = self.startup_commands_listbox.get(0, "end") shutdown_commands = self.shutdown_commands_listbox.get(0, "end") validate_commands = self.validate_commands_listbox.get(0, "end") @@ -413,16 +417,15 @@ class ServiceConfigDialog(Dialog): validate_commands, shutdown_commands, ) - if self.node_id not in service_configs: - service_configs[self.node_id] = {} + if self.node_id not in self.service_configs: + self.service_configs[self.node_id] = {} self.app.core.service_configs[self.node_id][self.service_name] = config for file in self.modified_files: - file_configs = self.app.core.file_configs - if self.node_id not in file_configs: - file_configs[self.node_id] = {} - if self.service_name not in file_configs[self.node_id]: - file_configs[self.node_id][self.service_name] = {} - file_configs[self.node_id][self.service_name][ + if self.node_id not in self.file_configs: + self.file_configs[self.node_id] = {} + if self.service_name not in self.file_configs[self.node_id]: + self.file_configs[self.node_id][self.service_name] = {} + self.file_configs[self.node_id][self.service_name][ file ] = self.temp_service_files[file] @@ -461,8 +464,10 @@ class ServiceConfigDialog(Dialog): ) def click_defaults(self): - self.app.core.service_configs.pop(self.node_id, None) - self.app.core.file_configs.pop(self.node_id, None) + if self.node_id in self.service_configs: + self.service_configs[self.node_id].pop(self.service_name, None) + if self.node_id in self.file_configs: + self.app.core.file_configs[self.node_id].pop(self.service_name, None) self.startup_commands = self.default_startup self.validation_commands = self.default_validate self.shutdown_commands = self.default_shutdown From 1e6e3f09589382f0ed9e7e16f25f25126642890b Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Tue, 7 Jan 2020 15:30:19 -0800 Subject: [PATCH 4/4] some clean up --- daemon/core/gui/dialogs/serviceconfig.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/daemon/core/gui/dialogs/serviceconfig.py b/daemon/core/gui/dialogs/serviceconfig.py index 9fc1ce1f..7823850d 100644 --- a/daemon/core/gui/dialogs/serviceconfig.py +++ b/daemon/core/gui/dialogs/serviceconfig.py @@ -93,7 +93,7 @@ class ServiceConfigDialog(Dialog): for x in self.filenames } self.temp_service_files = dict(self.original_service_files) - file_configs = self.app.core.file_configs + file_configs = self.file_configs if ( self.node_id in file_configs and self.service_name in file_configs[self.node_id] @@ -401,7 +401,7 @@ class ServiceConfigDialog(Dialog): def click_apply(self): current_listbox = self.master.current.listbox if not self.is_custom_service(): - if self.node_id in self.app.core.service_configs: + if self.node_id in self.service_configs: self.service_configs[self.node_id].pop(self.service_name, None) current_listbox.itemconfig(current_listbox.curselection()[0], bg="") self.destroy() @@ -419,7 +419,7 @@ class ServiceConfigDialog(Dialog): ) if self.node_id not in self.service_configs: self.service_configs[self.node_id] = {} - self.app.core.service_configs[self.node_id][self.service_name] = config + self.service_configs[self.node_id][self.service_name] = config for file in self.modified_files: if self.node_id not in self.file_configs: self.file_configs[self.node_id] = {} @@ -467,10 +467,7 @@ class ServiceConfigDialog(Dialog): if self.node_id in self.service_configs: self.service_configs[self.node_id].pop(self.service_name, None) if self.node_id in self.file_configs: - self.app.core.file_configs[self.node_id].pop(self.service_name, None) - self.startup_commands = self.default_startup - self.validation_commands = self.default_validate - self.shutdown_commands = self.default_shutdown + self.file_configs[self.node_id].pop(self.service_name, None) self.temp_service_files = dict(self.original_service_files) filename = self.filename_combobox.get() self.service_file_data.text.delete(1.0, "end") @@ -478,11 +475,11 @@ class ServiceConfigDialog(Dialog): self.startup_commands_listbox.delete(0, tk.END) self.validate_commands_listbox.delete(0, tk.END) self.shutdown_commands_listbox.delete(0, tk.END) - for cmd in self.startup_commands: + for cmd in self.default_startup: self.startup_commands_listbox.insert(tk.END, cmd) - for cmd in self.validation_commands: + for cmd in self.default_validate: self.validate_commands_listbox.insert(tk.END, cmd) - for cmd in self.shutdown_commands: + for cmd in self.default_shutdown: self.shutdown_commands_listbox.insert(tk.END, cmd) def click_copy(self):