mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-30 23:51:03 +01:00 
			
		
		
		
	cli changes for the nodes subcommand:
				
					
				
			* when listing nodes, a namespace is now optional, when it is not provided, all nodes are shown * when deleting, and sharing a node, remove the `namespace` flag, it was superfluous and unused * when unsharing a node, specify the namespace as an argument not a flag, making the UX the same as for sharing. Also refactor the share/unshare code to reuse the shared bits.
This commit is contained in:
		
							parent
							
								
									c8e1afb14b
								
							
						
					
					
						commit
						dd7557850e
					
				| @ -17,12 +17,13 @@ import ( | |||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	rootCmd.AddCommand(nodeCmd) | 	rootCmd.AddCommand(nodeCmd) | ||||||
| 	nodeCmd.PersistentFlags().StringP("namespace", "n", "", "Namespace") | 	listNodesCmd.Flags().StringP("namespace", "n", "", "Namespace") | ||||||
| 	err := nodeCmd.MarkPersistentFlagRequired("namespace") | 	nodeCmd.AddCommand(listNodesCmd) | ||||||
|  | 	registerNodeCmd.Flags().StringP("namespace", "n", "", "Namespace") | ||||||
|  | 	err := registerNodeCmd.MarkFlagRequired("namespace") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatalf(err.Error()) | 		log.Fatalf(err.Error()) | ||||||
| 	} | 	} | ||||||
| 	nodeCmd.AddCommand(listNodesCmd) |  | ||||||
| 	nodeCmd.AddCommand(registerNodeCmd) | 	nodeCmd.AddCommand(registerNodeCmd) | ||||||
| 	nodeCmd.AddCommand(deleteNodeCmd) | 	nodeCmd.AddCommand(deleteNodeCmd) | ||||||
| 	nodeCmd.AddCommand(shareMachineCmd) | 	nodeCmd.AddCommand(shareMachineCmd) | ||||||
| @ -69,7 +70,7 @@ var registerNodeCmd = &cobra.Command{ | |||||||
| 
 | 
 | ||||||
| var listNodesCmd = &cobra.Command{ | var listNodesCmd = &cobra.Command{ | ||||||
| 	Use:   "list", | 	Use:   "list", | ||||||
| 	Short: "List the nodes in a given namespace", | 	Short: "List nodes", | ||||||
| 	Run: func(cmd *cobra.Command, args []string) { | 	Run: func(cmd *cobra.Command, args []string) { | ||||||
| 		n, err := cmd.Flags().GetString("namespace") | 		n, err := cmd.Flags().GetString("namespace") | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| @ -82,22 +83,43 @@ var listNodesCmd = &cobra.Command{ | |||||||
| 			log.Fatalf("Error initializing: %s", err) | 			log.Fatalf("Error initializing: %s", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		namespace, err := h.GetNamespace(n) | 		var namespaces []headscale.Namespace | ||||||
|  | 		var namespace *headscale.Namespace | ||||||
|  | 		var sharedMachines *[]headscale.Machine | ||||||
|  | 		if len(n) == 0 { | ||||||
|  | 			// no namespace provided, list all | ||||||
|  | 			tmp, err := h.ListNamespaces() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				log.Fatalf("Error fetching namespace: %s", err) | 				log.Fatalf("Error fetching namespace: %s", err) | ||||||
| 			} | 			} | ||||||
| 
 | 			namespaces = *tmp | ||||||
| 		machines, err := h.ListMachinesInNamespace(n) | 		} else { | ||||||
|  | 			namespace, err = h.GetNamespace(n) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 			log.Fatalf("Error fetching machines: %s", err) | 				log.Fatalf("Error fetching namespace: %s", err) | ||||||
| 			} | 			} | ||||||
|  | 			namespaces = append(namespaces, *namespace) | ||||||
| 
 | 
 | ||||||
| 		sharedMachines, err := h.ListSharedMachinesInNamespace(n) | 			sharedMachines, err = h.ListSharedMachinesInNamespace(n) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				log.Fatalf("Error fetching shared machines: %s", err) | 				log.Fatalf("Error fetching shared machines: %s", err) | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		allMachines := append(*machines, *sharedMachines...) | 		var allMachines []headscale.Machine | ||||||
|  | 		for _, n := range namespaces { | ||||||
|  | 			machines, err := h.ListMachinesInNamespace(n.Name) | ||||||
|  | 			if err != nil { | ||||||
|  | 				log.Fatalf("Error fetching machines: %s", err) | ||||||
|  | 			} | ||||||
|  | 			allMachines = append(allMachines, *machines...) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// listing sharedMachines is only relevant when a particular namespace is | ||||||
|  | 		// requested | ||||||
|  | 		if sharedMachines != nil { | ||||||
|  | 			allMachines = append(allMachines, *sharedMachines...) | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		if strings.HasPrefix(o, "json") { | 		if strings.HasPrefix(o, "json") { | ||||||
| 			JsonOutput(allMachines, err, o) | 			JsonOutput(allMachines, err, o) | ||||||
| @ -108,7 +130,7 @@ var listNodesCmd = &cobra.Command{ | |||||||
| 			log.Fatalf("Error getting nodes: %s", err) | 			log.Fatalf("Error getting nodes: %s", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		d, err := nodesToPtables(*namespace, allMachines) | 		d, err := nodesToPtables(namespace, allMachines) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Fatalf("Error converting to table: %s", err) | 			log.Fatalf("Error converting to table: %s", err) | ||||||
| 		} | 		} | ||||||
| @ -176,20 +198,7 @@ var deleteNodeCmd = &cobra.Command{ | |||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var shareMachineCmd = &cobra.Command{ | func sharingWorker(cmd *cobra.Command, args []string) (*headscale.Headscale, string, *headscale.Machine, *headscale.Namespace) { | ||||||
| 	Use:   "share ID namespace", |  | ||||||
| 	Short: "Shares a node from the current namespace to the specified one", |  | ||||||
| 	Args: func(cmd *cobra.Command, args []string) error { |  | ||||||
| 		if len(args) < 2 { |  | ||||||
| 			return fmt.Errorf("missing parameters") |  | ||||||
| 		} |  | ||||||
| 		return nil |  | ||||||
| 	}, |  | ||||||
| 	Run: func(cmd *cobra.Command, args []string) { |  | ||||||
| 		namespace, err := cmd.Flags().GetString("namespace") |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatalf("Error getting namespace: %s", err) |  | ||||||
| 		} |  | ||||||
| 	output, _ := cmd.Flags().GetString("output") | 	output, _ := cmd.Flags().GetString("output") | ||||||
| 
 | 
 | ||||||
| 	h, err := getHeadscaleApp() | 	h, err := getHeadscaleApp() | ||||||
| @ -197,14 +206,9 @@ var shareMachineCmd = &cobra.Command{ | |||||||
| 		log.Fatalf("Error initializing: %s", err) | 		log.Fatalf("Error initializing: %s", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 		_, err = h.GetNamespace(namespace) | 	namespace, err := h.GetNamespace(args[1]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 			log.Fatalf("Error fetching origin namespace: %s", err) | 		log.Fatalf("Error fetching namespace %s: %s", args[1], err) | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		destinationNamespace, err := h.GetNamespace(args[1]) |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatalf("Error fetching destination namespace: %s", err) |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	id, err := strconv.Atoi(args[0]) | 	id, err := strconv.Atoi(args[0]) | ||||||
| @ -216,7 +220,21 @@ var shareMachineCmd = &cobra.Command{ | |||||||
| 		log.Fatalf("Error getting node: %s", err) | 		log.Fatalf("Error getting node: %s", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 		err = h.AddSharedMachineToNamespace(machine, destinationNamespace) | 	return h, output, machine, namespace | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var shareMachineCmd = &cobra.Command{ | ||||||
|  | 	Use:   "share ID namespace", | ||||||
|  | 	Short: "Shares a node from the current namespace to the specified one", | ||||||
|  | 	Args: func(cmd *cobra.Command, args []string) error { | ||||||
|  | 		if len(args) < 2 { | ||||||
|  | 			return fmt.Errorf("missing parameters") | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	}, | ||||||
|  | 	Run: func(cmd *cobra.Command, args []string) { | ||||||
|  | 		h, output, machine, namespace := sharingWorker(cmd, args) | ||||||
|  | 		err := h.AddSharedMachineToNamespace(machine, namespace) | ||||||
| 		if strings.HasPrefix(output, "json") { | 		if strings.HasPrefix(output, "json") { | ||||||
| 			JsonOutput(map[string]string{"Result": "Node shared"}, err, output) | 			JsonOutput(map[string]string{"Result": "Node shared"}, err, output) | ||||||
| 			return | 			return | ||||||
| @ -231,41 +249,17 @@ var shareMachineCmd = &cobra.Command{ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var unshareMachineCmd = &cobra.Command{ | var unshareMachineCmd = &cobra.Command{ | ||||||
| 	Use:   "unshare ID", | 	Use:   "unshare ID namespace", | ||||||
| 	Short: "Unshares a node from the specified namespace", | 	Short: "Unshares a node from the specified namespace", | ||||||
| 	Args: func(cmd *cobra.Command, args []string) error { | 	Args: func(cmd *cobra.Command, args []string) error { | ||||||
| 		if len(args) < 1 { | 		if len(args) < 2 { | ||||||
| 			return fmt.Errorf("missing parameters") | 			return fmt.Errorf("missing parameters") | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
| 	}, | 	}, | ||||||
| 	Run: func(cmd *cobra.Command, args []string) { | 	Run: func(cmd *cobra.Command, args []string) { | ||||||
| 		namespace, err := cmd.Flags().GetString("namespace") | 		h, output, machine, namespace := sharingWorker(cmd, args) | ||||||
| 		if err != nil { | 		err := h.RemoveSharedMachineFromNamespace(machine, namespace) | ||||||
| 			log.Fatalf("Error getting namespace: %s", err) |  | ||||||
| 		} |  | ||||||
| 		output, _ := cmd.Flags().GetString("output") |  | ||||||
| 
 |  | ||||||
| 		h, err := getHeadscaleApp() |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatalf("Error initializing: %s", err) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		n, err := h.GetNamespace(namespace) |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatalf("Error fetching namespace: %s", err) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		id, err := strconv.Atoi(args[0]) |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatalf("Error converting ID to integer: %s", err) |  | ||||||
| 		} |  | ||||||
| 		machine, err := h.GetMachineByID(uint64(id)) |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatalf("Error getting node: %s", err) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		err = h.RemoveSharedMachineFromNamespace(machine, n) |  | ||||||
| 		if strings.HasPrefix(output, "json") { | 		if strings.HasPrefix(output, "json") { | ||||||
| 			JsonOutput(map[string]string{"Result": "Node unshared"}, err, output) | 			JsonOutput(map[string]string{"Result": "Node unshared"}, err, output) | ||||||
| 			return | 			return | ||||||
| @ -279,7 +273,7 @@ var unshareMachineCmd = &cobra.Command{ | |||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func nodesToPtables(currentNamespace headscale.Namespace, machines []headscale.Machine) (pterm.TableData, error) { | func nodesToPtables(currentNamespace *headscale.Namespace, machines []headscale.Machine) (pterm.TableData, error) { | ||||||
| 	d := pterm.TableData{{"ID", "Name", "NodeKey", "Namespace", "IP address", "Ephemeral", "Last seen", "Online"}} | 	d := pterm.TableData{{"ID", "Name", "NodeKey", "Namespace", "IP address", "Ephemeral", "Last seen", "Online"}} | ||||||
| 
 | 
 | ||||||
| 	for _, machine := range machines { | 	for _, machine := range machines { | ||||||
| @ -307,9 +301,10 @@ func nodesToPtables(currentNamespace headscale.Namespace, machines []headscale.M | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		var namespace string | 		var namespace string | ||||||
| 		if currentNamespace.ID == machine.NamespaceID { | 		if (currentNamespace == nil) || (currentNamespace.ID == machine.NamespaceID) { | ||||||
| 			namespace = pterm.LightMagenta(machine.Namespace.Name) | 			namespace = pterm.LightMagenta(machine.Namespace.Name) | ||||||
| 		} else { | 		} else { | ||||||
|  | 			// Shared into this namespace | ||||||
| 			namespace = pterm.LightYellow(machine.Namespace.Name) | 			namespace = pterm.LightYellow(machine.Namespace.Name) | ||||||
| 		} | 		} | ||||||
| 		d = append(d, []string{strconv.FormatUint(machine.ID, 10), machine.Name, nodeKey.ShortString(), namespace, machine.IPAddress, strconv.FormatBool(ephemeral), lastSeenTime, online}) | 		d = append(d, []string{strconv.FormatUint(machine.ID, 10), machine.Name, nodeKey.ShortString(), namespace, machine.IPAddress, strconv.FormatBool(ephemeral), lastSeenTime, online}) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user